1
0
Fork 0
mirror of https://github.com/fastogt/fastocloud_admin.git synced 2025-03-09 23:38:52 +00:00

Send subscribers to service

This commit is contained in:
topilski 2019-06-10 04:36:05 -04:00
parent 2e5f60ab17
commit 7c178982f5
10 changed files with 247 additions and 5 deletions

View file

@ -78,6 +78,8 @@ class ServiceClient(IClientHandler):
streams.append(stream.config()) streams.append(stream.config())
subscribers = [] subscribers = []
for subscriber in self._service_settings.subscribers:
subscribers.append(subscriber.to_service())
return self._client.sync_service(self._gen_request_id(), streams, subscribers) return self._client.sync_service(self._gen_request_id(), streams, subscribers)
def get_http_host(self) -> str: def get_http_host(self) -> str:

View file

@ -20,6 +20,7 @@ class ServiceSettings(Document, ServerSettings):
streams = ListField(EmbeddedDocumentField(Stream), default=[]) streams = ListField(EmbeddedDocumentField(Stream), default=[])
users = ListField(EmbeddedDocumentField(UserPair), default=[]) users = ListField(EmbeddedDocumentField(UserPair), default=[])
subscribers = ListField(ReferenceField('Subscriber'), default=[])
def generate_playlist(self) -> str: def generate_playlist(self) -> str:
result = '#EXTM3U\n' result = '#EXTM3U\n'
@ -47,4 +48,16 @@ class ServiceSettings(Document, ServerSettings):
for user in self.users: for user in self.users:
if user.id == uid: if user.id == uid:
self.users.remove(user) self.users.remove(user)
break
self.save()
def add_subscriber(self, sid):
self.subscribers.append(sid)
self.save()
def remove_subscriber(self, sid):
for subscriber in self.subscribers:
if subscriber == sid:
self.subscribers.remove(subscriber)
break
self.save() self.save()

View file

@ -6,9 +6,11 @@ from flask_login import login_required, current_user
from app import get_runtime_folder from app import get_runtime_folder
from app.service.forms import ServiceSettingsForm, ActivateForm, UploadM3uForm, UserServerForm from app.service.forms import ServiceSettingsForm, ActivateForm, UploadM3uForm, UserServerForm
from app.subscriber.forms import SubscriberForm
from app.service.service_entry import ServiceSettings, UserPair from app.service.service_entry import ServiceSettings, UserPair
from app.utils.m3u_parser import M3uParser from app.utils.m3u_parser import M3uParser
from app.home.user_loging_manager import User from app.home.user_loging_manager import User
from app.subscriber.subscriber_entry import Subscriber
import app.constants as constants import app.constants as constants
@ -157,11 +159,26 @@ class ServiceView(FlaskView):
return render_template('service/user/add.html', form=form) return render_template('service/user/add.html', form=form)
@login_required
@route('/subscriber/add/<sid>', methods=['GET', 'POST'])
def subscriber_add(self, sid):
form = SubscriberForm(obj=Subscriber())
if request.method == 'POST' and form.validate_on_submit():
server = ServiceSettings.objects(id=sid).first()
if server:
new_entry = form.make_entry()
new_entry.save()
server.add_subscriber(new_entry.id)
new_entry.add_server(server)
return jsonify(status='ok'), 200
return render_template('service/subscriber/add.html', form=form)
@login_required @login_required
@route('/add', methods=['GET', 'POST']) @route('/add', methods=['GET', 'POST'])
def add(self): def add(self):
model = ServiceSettings() form = ServiceSettingsForm(obj=ServiceSettings())
form = ServiceSettingsForm(obj=model)
if request.method == 'POST' and form.validate_on_submit(): if request.method == 'POST' and form.validate_on_submit():
new_entry = form.make_entry() new_entry = form.make_entry()
admin = UserPair(current_user.id, constants.Roles.ADMIN) admin = UserPair(current_user.id, constants.Roles.ADMIN)

26
app/subscriber/forms.py Normal file
View file

@ -0,0 +1,26 @@
from flask_wtf import FlaskForm
from flask_babel import lazy_gettext
from wtforms.fields import StringField, PasswordField, SubmitField, SelectField
from wtforms.validators import InputRequired, Length, Email
from app.subscriber.subscriber_entry import Subscriber
class SubscriberForm(FlaskForm):
AVAILABLE_COUNTRIES = [('UK', 'United kingdom'), ('RU', 'Russian'), ('BY', 'Belarus')]
email = StringField(lazy_gettext(u'Email:'),
validators=[InputRequired(), Email(message=lazy_gettext(u'Invalid email')), Length(max=30)])
password = PasswordField(lazy_gettext(u'Password:'), validators=[InputRequired(), Length(min=6, max=80)])
country = SelectField(lazy_gettext(u'Locale:'), coerce=str, validators=[InputRequired()],
choices=AVAILABLE_COUNTRIES)
apply = SubmitField(lazy_gettext(u'Apply'))
def make_entry(self):
return self.update_entry(Subscriber())
def update_entry(self, subscriber: Subscriber):
subscriber.email = self.email.data
subscriber.password = Subscriber.make_md5_hash_from_password(self.password.data)
subscriber.country = self.country.data
return subscriber

View file

@ -0,0 +1,98 @@
from datetime import datetime
from hashlib import md5
from bson.objectid import ObjectId
from enum import IntEnum
from mongoengine import Document, EmbeddedDocument, StringField, DateTimeField, IntField, ListField, ReferenceField, \
PULL, ObjectIdField
from app.service.service_entry import ServiceSettings
from app.stream.stream_entry import Stream
class Device(EmbeddedDocument):
DEFAULT_DEVICE_NAME = 'Device'
MIN_DEVICE_NAME_LENGTH = 3
MAX_DEVICE_NAME_LENGTH = 32
meta = {'allow_inheritance': False, 'auto_create_index': True}
id = ObjectIdField(required=True, default=ObjectId, unique=True, primary_key=True)
created_date = DateTimeField(default=datetime.now)
name = StringField(default=DEFAULT_DEVICE_NAME, min_length=MIN_DEVICE_NAME_LENGTH,
max_length=MAX_DEVICE_NAME_LENGTH,
required=True)
class Subscriber(Document):
ID_FIELD = "id"
EMAIL_FIELD = "login"
PASSWORD_FIELD = "password"
STATUS_FIELD = "status"
DEVICES_FIELD = "devices"
STREAMS_FIELD = "streams"
class Status(IntEnum):
NO_ACTIVE = 0
ACTIVE = 1
BANNED = 2
class Type(IntEnum):
USER = 0,
SUPPORT = 1
SUBSCRIBER_HASH_LENGHT = 32
meta = {'collection': 'subscribers', 'auto_create_index': False}
email = StringField(max_length=30, required=True)
password = StringField(min_length=SUBSCRIBER_HASH_LENGHT, max_length=SUBSCRIBER_HASH_LENGHT, required=True)
created_date = DateTimeField(default=datetime.now)
status = IntField(default=Status.ACTIVE)
type = IntField(default=Type.USER)
country = StringField(min_length=2, max_length=3, required=True)
servers = ListField(ReferenceField(ServiceSettings, reverse_delete_rule=PULL), default=[])
devices = ListField(Device, default=[])
streams = ListField(ReferenceField(Stream, reverse_delete_rule=PULL), default=[])
def add_server(self, server: ServiceSettings):
self.servers.append(server)
self.save()
def add_stream(self, sid):
self.streams.append(sid)
self.save()
def remove_stream(self, sid):
for stream in self.streams:
if stream == sid:
self.streams.remove(stream)
break
self.save()
def to_service(self) -> dict:
devices = []
for dev in self.devices:
devices.append(str(dev.id))
streams = []
for stream in self.streams:
streams.append(str(stream))
conf = {
Subscriber.ID_FIELD: str(self.id), Subscriber.EMAIL_FIELD: self.email,
Subscriber.PASSWORD_FIELD: self.password, Subscriber.STATUS_FIELD: self.status,
Subscriber.DEVICES_FIELD: devices, Subscriber.STREAMS_FIELD: streams}
return conf
@staticmethod
def make_md5_hash_from_password(password: str) -> str:
m = md5()
m.update(password.encode())
return m.hexdigest()
@classmethod
def md5_user(cls, email: str, password: str, country: str):
return cls(email=email, password=Subscriber.make_md5_hash_from_password(password), country=country)
Subscriber.register_delete_rule(ServiceSettings, "subscribers", PULL)

View file

@ -0,0 +1,4 @@
{% extends 'service/subscriber/base.html' %}
{% block title %}
Add subscriber to server
{% endblock %}

View file

@ -0,0 +1,45 @@
{% from 'bootstrap/wtf.html' import form_field %}
{% macro render_bootstrap_field(field) %}
<div class="row">
<label class="col-md-4">{{ field.label }}</label>
<div class="col-md-8">
{{ field(class='form-control')|safe }}
</div>
</div>
{% endmacro %}
{% macro render_bootstrap_form(form) %}
<div class="row">
<label class="col-md-4">{{ form.label }}</label>
<div class="col-md-8">
{{ form() }}
</div>
</div>
{% endmacro %}
<form id="subscriber_entry_form" name="subscriber_entry_form" class="form" method="post">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="close">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">
{% block title %}
{% endblock %}
</h4>
</div>
<div class="modal-body">
{{ form.hidden_tag() }}
<br>
{{ render_bootstrap_field(form.email) }}
<br>
{{ render_bootstrap_field(form.password) }}
<br>
{{ render_bootstrap_field(form.country) }}
</div>
<div class="modal-footer">
{% block footer %}
<button type="button" class="btn btn-danger" data-dismiss="modal">{% trans %}Cancel{% endtrans %}</button>
{{ form_field(form.apply, class="btn btn-success") }}
{% endblock %}
</div>
</form>

View file

@ -0,0 +1,4 @@
{% extends 'service/subscriber/base.html' %}
{% block title %}
Edit subscriber
{% endblock %}

View file

@ -1,4 +1,4 @@
{% extends 'service/base.html' %} {% extends 'service/user/base.html' %}
{% block title %} {% block title %}
Edit service Edit service
{% endblock %} {% endblock %}

View file

@ -74,6 +74,10 @@ Settings | {{ config['PUBLIC_CONFIG'].site.title }}
onclick="add_user_to_server('{{ server.id }}')"> onclick="add_user_to_server('{{ server.id }}')">
{% trans %}Add user{% endtrans %} {% trans %}Add user{% endtrans %}
</button> </button>
<button type="submit" class="btn btn-success btn-xs"
onclick="add_subscriber_to_server('{{ server.id }}')">
{% trans %}Add subscriber{% endtrans %}
</button>
<button type="submit" class="btn btn-danger btn-xs" <button type="submit" class="btn btn-danger btn-xs"
onclick="remove_server('{{ server.id }}')"> onclick="remove_server('{{ server.id }}')">
{% trans %}Remove{% endtrans %} {% trans %}Remove{% endtrans %}
@ -155,6 +159,37 @@ Settings | {{ config['PUBLIC_CONFIG'].site.title }}
} }
function add_subscriber_to_server_entry(url) {
$.ajax({
url: url,
type: "POST",
dataType: 'json',
data: $('#subscriber_entry_form').serialize(),
success: function (response) {
console.log(response);
$('#service_dialog').modal('hide');
window.location.reload();
},
error: function (error) {
console.error(error);
$('#service_dialog .modal-content').html(data);
}
});
}
function add_subscriber_to_server(sid) {
var url = "/service/subscriber/add/" + sid;
$.get(url, function(data) {
$('#service_dialog .modal-content').html(data);
$('#service_dialog').modal();
$('#apply').click(function(event) {
event.preventDefault();
add_subscriber_to_server_entry(url);
})
});
}
function add_server() { function add_server() {
var url = "{{ url_for('ServiceView:add') }}"; var url = "{{ url_for('ServiceView:add') }}";
$.get(url, function(data) { $.get(url, function(data) {
@ -215,7 +250,5 @@ Settings | {{ config['PUBLIC_CONFIG'].site.title }}
}); });
} }
</script> </script>
{% endblock %} {% endblock %}