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:
parent
2e5f60ab17
commit
7c178982f5
10 changed files with 247 additions and 5 deletions
|
@ -78,6 +78,8 @@ class ServiceClient(IClientHandler):
|
|||
streams.append(stream.config())
|
||||
|
||||
subscribers = []
|
||||
for subscriber in self._service_settings.subscribers:
|
||||
subscribers.append(subscriber.to_service())
|
||||
return self._client.sync_service(self._gen_request_id(), streams, subscribers)
|
||||
|
||||
def get_http_host(self) -> str:
|
||||
|
|
|
@ -20,6 +20,7 @@ class ServiceSettings(Document, ServerSettings):
|
|||
|
||||
streams = ListField(EmbeddedDocumentField(Stream), default=[])
|
||||
users = ListField(EmbeddedDocumentField(UserPair), default=[])
|
||||
subscribers = ListField(ReferenceField('Subscriber'), default=[])
|
||||
|
||||
def generate_playlist(self) -> str:
|
||||
result = '#EXTM3U\n'
|
||||
|
@ -47,4 +48,16 @@ class ServiceSettings(Document, ServerSettings):
|
|||
for user in self.users:
|
||||
if user.id == uid:
|
||||
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()
|
||||
|
|
|
@ -6,9 +6,11 @@ from flask_login import login_required, current_user
|
|||
|
||||
from app import get_runtime_folder
|
||||
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.utils.m3u_parser import M3uParser
|
||||
from app.home.user_loging_manager import User
|
||||
from app.subscriber.subscriber_entry import Subscriber
|
||||
import app.constants as constants
|
||||
|
||||
|
||||
|
@ -157,11 +159,26 @@ class ServiceView(FlaskView):
|
|||
|
||||
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
|
||||
@route('/add', methods=['GET', 'POST'])
|
||||
def add(self):
|
||||
model = ServiceSettings()
|
||||
form = ServiceSettingsForm(obj=model)
|
||||
form = ServiceSettingsForm(obj=ServiceSettings())
|
||||
if request.method == 'POST' and form.validate_on_submit():
|
||||
new_entry = form.make_entry()
|
||||
admin = UserPair(current_user.id, constants.Roles.ADMIN)
|
||||
|
|
26
app/subscriber/forms.py
Normal file
26
app/subscriber/forms.py
Normal 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
|
98
app/subscriber/subscriber_entry.py
Normal file
98
app/subscriber/subscriber_entry.py
Normal 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)
|
4
app/templates/service/subscriber/add.html
Normal file
4
app/templates/service/subscriber/add.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
{% extends 'service/subscriber/base.html' %}
|
||||
{% block title %}
|
||||
Add subscriber to server
|
||||
{% endblock %}
|
45
app/templates/service/subscriber/base.html
Normal file
45
app/templates/service/subscriber/base.html
Normal 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">×</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>
|
4
app/templates/service/subscriber/edit.html
Normal file
4
app/templates/service/subscriber/edit.html
Normal file
|
@ -0,0 +1,4 @@
|
|||
{% extends 'service/subscriber/base.html' %}
|
||||
{% block title %}
|
||||
Edit subscriber
|
||||
{% endblock %}
|
|
@ -1,4 +1,4 @@
|
|||
{% extends 'service/base.html' %}
|
||||
{% extends 'service/user/base.html' %}
|
||||
{% block title %}
|
||||
Edit service
|
||||
{% endblock %}
|
|
@ -74,6 +74,10 @@ Settings | {{ config['PUBLIC_CONFIG'].site.title }}
|
|||
onclick="add_user_to_server('{{ server.id }}')">
|
||||
{% trans %}Add user{% endtrans %}
|
||||
</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"
|
||||
onclick="remove_server('{{ server.id }}')">
|
||||
{% 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() {
|
||||
var url = "{{ url_for('ServiceView:add') }}";
|
||||
$.get(url, function(data) {
|
||||
|
@ -215,7 +250,5 @@ Settings | {{ config['PUBLIC_CONFIG'].site.title }}
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue