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

227 lines
7.7 KiB

import argparse
import json
import os
from getpass import getpass
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)
user = get_current_user()
if user:
if user.root_access or r.creator == user:
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://vid.w3ic.org/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/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}), 00
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)