You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
backend/app.py

260 lines
8.6 KiB

import argparse
import base64
import json
import os
from getpass import getpass
from pathlib import Path
from random import randint
import sh
from flask import Flask, request, jsonify
from flask_cors import CORS
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, jwt_optional, get_jwt_identity
from flask_mongoengine import MongoEngine
from werkzeug.security import generate_password_hash, check_password_hash
from string import ascii_lowercase, ascii_uppercase, digits
from mainapp.janus import Janus
from mainapp.models import User, Room
app = Flask(__name__)
app.config['MONGODB_SETTINGS'] = {
'host': os.environ.get('MONGODB_URL')
}
app.config['JWT_SECRET_KEY'] = os.environ.get('JWT_SECRET_KEY', 'changeme')
app.config['JANUS_URL'] = os.environ.get('JANUS_URL')
app.config['JANUS_ADMIN_KEY'] = os.environ.get('JANUS_ADMIN_KEY', '')
db = MongoEngine()
db.init_app(app)
jwt = JWTManager(app)
cors = CORS(app, resources={r"/api/*": {"origins": "*"}})
def get_current_user():
try:
current_user = get_jwt_identity()
return User.objects.get(id=current_user)
except:
return False
@app.route('/api/kick/<rid>/<publisher>', methods=['GET'])
@jwt_optional
def kick(rid, publisher):
r = Room.objects.get(ridn=rid)
user = get_current_user()
if user:
if user.root_access or r.creator == user:
jan = Janus(os.environ.get('JANUS_URL'), app.config['JANUS_ADMIN_KEY'])
jan.connect()
jan.kick(r.room_id, int(publisher))
return "ok"
sh_coms = {}
@app.route("/api/sh")
def sh_coms_list():
room_rs = []
for room_id , sh_item in sh_coms.items():
room_rs.append({"room":room_id, "status":sh_item.exit_code})
return jsonify(room_rs)
@app.route("/api/sh/kill/<rid>")
def sh_kill(rid):
if sh_coms.get(int(rid)):
print(sh_coms.get(int(rid)).kill())
return "ok"
def done(cmd, success, exit_code):
print('done')
@app.route('/api/rtp/<rid>/<publisher>', methods=['GET'])
@jwt_optional
def rtp_forward(rid, publisher):
r = Room.objects.get(ridn=rid)
if not sh_coms.get(r.room_id,None) or sh_coms.get(r.room_id).exit_code:
room_sh = sh.python(['forward_stream.py', '--room',r.room_id, "https://kahvehane.oyd.org.tr/janus"],_bg=True, _done=done)
sh_coms.update({r.room_id:room_sh})
return "ok"
@app.route('/api/room/<rid>', methods=['GET'])
@jwt_optional
def room(rid):
r = Room.objects.get(ridn=rid)
user = get_current_user()
if user:
return jsonify({'rid': r.room_id, "can_modify": user.root_access or r.creator == user})
else:
return jsonify({'rid': r.room_id, "can_modify": False})
@app.route('/api/upload', methods=('POST',))
@jwt_required
def upload_file():
file = request.json.get('file')
file_name = request.json.get('file_name')
file_content = base64.b64decode(file)
with open("static/{}".format(file_name), "wb+") as f:
f.write(file_content)
return "ok"
@app.route('/api/files')
@jwt_required
def get_file():
p = Path("./static")
files = []
for i in p.glob("*.*"):
files.append(i.name)
return jsonify(files)
@app.route('/api/recreate/room', methods=['GET'])
def recreate_room():
rms = Room.objects.all()
for i in rms:
jan = Janus(os.environ.get('JANUS_URL'), app.config['JANUS_ADMIN_KEY'])
jan.connect()
room_id = jan.create_room(name=i.room_name, video_codec="vp8", audio_codec="opus",
publisher_count=int(16), bitrate=128*1000, data=False)
i.room_id = room_id
i.save()
return "ok"
@app.route('/api/create/room', methods=['POST'])
@jwt_required
def create_room():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
room_name = request.json.get('room_name', 'No name room')
video_codec = request.json.get('video_codec', 'vp9')
audio_codec = request.json.get('audio_codec', 'opus')
publisher_count = request.json.get('publisher_count', 16)
bitrate = request.json.get('bitrate', 128000)
data = request.json.get('data', False)
user = get_current_user()
if user.create_room_access or user.root_access:
jan = Janus(os.environ.get('JANUS_URL'), app.config['JANUS_ADMIN_KEY'])
jan.connect()
room_id = jan.create_room(name=room_name, video_codec=video_codec, audio_codec=audio_codec,
publisher_count=int(publisher_count), bitrate=bitrate, data=data)
room = Room()
room.room_name = room_name
room.creator = user
room.room_id = room_id
have_room = True
ridn = None
letters = ascii_lowercase + ascii_uppercase + digits
while have_room:
ridn = ''.join([letters[randint(0, len(letters) - 1)] for rid in range(6)])
if Room.objects.filter(ridn=ridn).count() == 0:
have_room = False
room.ridn = ridn
room.save()
return jsonify({"msg": "seccess", "ridn": ridn}), 200
else:
return jsonify({"msg": "You don't have a this access"}), 403
@app.route('/api/rooms', methods=['GET'])
@jwt_required
def rooms():
user = get_current_user()
if user.root_access:
json_data = json.dumps({
"rooms": json.loads(Room.objects.all().to_json()),
"can_create": True
})
else:
json_data = json.dumps({
"rooms": user.rooms.to_json(),
"can_create": False
})
return json_data
@app.route('/api/create/user', methods=['POST'])
@jwt_required
def create_user():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
room_id = request.json.get('room', None)
create_room = request.json.get('create_room', False)
root_access = request.json.get('root_access', False)
password = request.json.get('password', False)
user = get_current_user()
if not user.create_room_access and not user.root_access:
return jsonify({"msg": "You don't have a this access"}), 403
room = Room.objects.get(ridn=room_id)
if room.creator != user and not user.root_access:
return jsonify({"msg": "You don't have a this access"}), 403
if (create_room or root_access) and not user.root_access:
return jsonify({"msg": "You don't have a this access"}), 403
letters = ascii_lowercase + ascii_uppercase + digits
have_user = True
user_id = None
while have_user:
user_id = ''.join([letters[randint(len(letters) - 1)] for rid in range(6)])
if User.objects.filter(uidn=user_id).count() == 0:
have_user = False
new_user = User()
new_user.create_room_access = create_room
new_user.root_access = root_access
new_user.uidn = user_id
new_user.rooms.append(room)
if create_room or root_access:
new_user.passw = generate_password_hash(password, method='sha256')
new_user.save()
return jsonify({'msg': 'user created', 'uid': user_id})
@app.route('/api/login', methods=['POST'])
def login():
if not request.is_json:
return jsonify({"msg": "Missing JSON in request"}), 400
username = request.json.get('username', None)
password = request.json.get('password', None)
if not username:
return jsonify({"msg": "Missing username parameter"}), 400
user = User.objects.filter(uidn=username)
if user.count() == 0:
return jsonify({"msg": "Bad username or password"}), 401
else:
user = user.get()
if not password and (user.root_access or user.create_room_access):
return jsonify({"msg": "Password need for this user"}), 401
if password or user.passw:
if not check_password_hash(user.passw, password):
return jsonify({"msg": "Bad username or password"}), 401
# Identity can be any data that is json serializable
access_token = create_access_token(identity=str(user.id))
return jsonify(access_token=access_token), 200
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Albatros Backend')
parser.add_argument('--create-user', nargs='?', help='Create a root user')
args = parser.parse_args()
if args.create_user:
new_user = User()
new_user.uidn = args.create_user
new_user.root_access = True
passcheck = False
while not passcheck:
passwd = getpass('Password: ')
passwd_check = getpass('Password Check: ')
if passwd_check == passwd:
passcheck = True
new_user.passw = generate_password_hash(passwd, method='sha256')
new_user.save()
exit()
app.run(debug=True)