tryd to fix a oid connect related bug, but there is still a BIG problem
This commit is contained in:
@@ -5,11 +5,12 @@
|
|||||||
import logging
|
import logging
|
||||||
import ssl
|
import ssl
|
||||||
import sys
|
import sys
|
||||||
|
import threading
|
||||||
|
|
||||||
from jinja2.exceptions import TemplateNotFound
|
from jinja2.exceptions import TemplateNotFound
|
||||||
|
|
||||||
from backend import app, db
|
from backend import app, db
|
||||||
from backend.cron import get_default_scheduler, add_default_jobs
|
from backend.cron import get_default_scheduler, add_default_jobs, async_permanent_cron_recorder_checker
|
||||||
from backend.models import *
|
from backend.models import *
|
||||||
from backend.models import room_model, recorder_model, RecorderCommand, Recorder
|
from backend.models import room_model, recorder_model, RecorderCommand, Recorder
|
||||||
from backend.recorder_adapters import get_defined_recorder_adapters
|
from backend.recorder_adapters import get_defined_recorder_adapters
|
||||||
@@ -17,13 +18,30 @@ from backend.tools.model_updater import update_recorder_models_database, create_
|
|||||||
from backend.websocket.base import WebSocketBase
|
from backend.websocket.base import WebSocketBase
|
||||||
|
|
||||||
|
|
||||||
|
def _start_initial_recorder_state_update(run_in_thread=True):
|
||||||
|
if run_in_thread:
|
||||||
|
thread = threading.Thread(target=async_permanent_cron_recorder_checker.check_object_state, args=())
|
||||||
|
thread.start()
|
||||||
|
else:
|
||||||
|
async_permanent_cron_recorder_checker.check_object_state() # initial check of all recorders
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def _create_and_start_default_scheduler():
|
||||||
|
print("Starting Scheduler")
|
||||||
|
scheduler = get_default_scheduler()
|
||||||
|
add_default_jobs(scheduler)
|
||||||
|
scheduler.start()
|
||||||
|
return scheduler
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
|
||||||
|
|
||||||
#db.drop_all()
|
# db.drop_all()
|
||||||
#db.create_all()
|
# db.create_all()
|
||||||
|
|
||||||
#Recorder()
|
# Recorder()
|
||||||
room_model.pre_fill_table()
|
room_model.pre_fill_table()
|
||||||
update_recorder_models_database(drop=False)
|
update_recorder_models_database(drop=False)
|
||||||
create_default_recorders()
|
create_default_recorders()
|
||||||
@@ -44,16 +62,14 @@ def main():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
logging.critical(e)
|
logging.critical(e)
|
||||||
|
|
||||||
print("Starting Scheduler")
|
scheduler = _create_and_start_default_scheduler()
|
||||||
scheduler = get_default_scheduler()
|
#_start_initial_recorder_state_update(run_in_thread=False)
|
||||||
add_default_jobs(scheduler)
|
|
||||||
scheduler.start()
|
|
||||||
|
|
||||||
wsb = WebSocketBase()
|
wsb = WebSocketBase()
|
||||||
print("running websocket...(replaces normal app.run()")
|
print("running websocket...(replaces normal app.run()")
|
||||||
wsb.start_websocket(debug=True)
|
wsb.start_websocket(debug=True)
|
||||||
# print("running web app...")
|
# print("running web app...")
|
||||||
#app.run(debug=True, host="0.0.0.0", threaded=True)
|
# app.run(debug=True, host="0.0.0.0", threaded=True)
|
||||||
wsb.send_test_msg()
|
wsb.send_test_msg()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ Login through API does not start a new session, but instead returns JWT.
|
|||||||
"""
|
"""
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
|
import logging
|
||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
@@ -29,6 +30,8 @@ from backend.api import auth_api_bp, auth_api_providers_ns, auth_api_register_ns
|
|||||||
from backend.auth import AUTH_PROVIDERS, oidc_auth
|
from backend.auth import AUTH_PROVIDERS, oidc_auth
|
||||||
from backend.models.user_model import User, Group, BlacklistToken
|
from backend.models.user_model import User, Group, BlacklistToken
|
||||||
|
|
||||||
|
logger = logging.getLogger("lrc.api.auth")
|
||||||
|
|
||||||
|
|
||||||
@auth_api_bp.route('/providers', methods=('GET',))
|
@auth_api_bp.route('/providers', methods=('GET',))
|
||||||
def get_auth_providers():
|
def get_auth_providers():
|
||||||
@@ -92,6 +95,7 @@ def login():
|
|||||||
}
|
}
|
||||||
return jsonify(token), 200
|
return jsonify(token), 200
|
||||||
|
|
||||||
|
|
||||||
# Endpoint for revoking the current users access token
|
# Endpoint for revoking the current users access token
|
||||||
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
|
@auth_api_bp.route('/logout', methods=['GET', 'DELETE'])
|
||||||
@jwt_required
|
@jwt_required
|
||||||
@@ -135,7 +139,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
|
|||||||
user = User.get_by_identifier(email)
|
user = User.get_by_identifier(email)
|
||||||
|
|
||||||
if user is not None:
|
if user is not None:
|
||||||
app.logger.info("user found -> update user")
|
logger.info("user found -> update user")
|
||||||
pprint(user.to_dict())
|
pprint(user.to_dict())
|
||||||
user.first_name = userinfo.get("given_name", "")
|
user.first_name = userinfo.get("given_name", "")
|
||||||
user.last_name = userinfo.get("family_name", "")
|
user.last_name = userinfo.get("family_name", "")
|
||||||
@@ -148,7 +152,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
|
|||||||
last_name=userinfo.get("family_name", ""), external_user=True,
|
last_name=userinfo.get("family_name", ""), external_user=True,
|
||||||
groups=user_groups)
|
groups=user_groups)
|
||||||
|
|
||||||
app.logger.info("creating new user")
|
logger.info("creating new user")
|
||||||
|
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -159,8 +163,11 @@ def create_or_retrieve_user_from_userinfo(userinfo):
|
|||||||
@auth_api_bp.route('/oidc/<redirect_url>', methods=['GET'])
|
@auth_api_bp.route('/oidc/<redirect_url>', methods=['GET'])
|
||||||
@oidc_auth.oidc_auth()
|
@oidc_auth.oidc_auth()
|
||||||
def oidc(redirect_url=None):
|
def oidc(redirect_url=None):
|
||||||
|
logger.debug("oidc auth endpoint:")
|
||||||
|
return "fuck!"
|
||||||
user = create_or_retrieve_user_from_userinfo(flask.session['userinfo'])
|
user = create_or_retrieve_user_from_userinfo(flask.session['userinfo'])
|
||||||
if user is None:
|
if user is None:
|
||||||
|
logger.error("Could not authenticate: could not find or create user.")
|
||||||
return "Could not authenticate: could not find or create user.", 401
|
return "Could not authenticate: could not find or create user.", 401
|
||||||
if current_app.config.get("AUTH_RETURN_EXTERNAL_JWT", False):
|
if current_app.config.get("AUTH_RETURN_EXTERNAL_JWT", False):
|
||||||
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
|
token = jwt.encode(flask.session['id_token'], current_app.config['SECRET_KEY'])
|
||||||
@@ -169,13 +176,13 @@ def oidc(redirect_url=None):
|
|||||||
'access_token': create_access_token(identity=user, fresh=True),
|
'access_token': create_access_token(identity=user, fresh=True),
|
||||||
'refresh_token': create_refresh_token(identity=user)
|
'refresh_token': create_refresh_token(identity=user)
|
||||||
})
|
})
|
||||||
|
logger.info("Token: {}".format(token))
|
||||||
if redirect_url is None:
|
if redirect_url is None:
|
||||||
redirect_url = request.headers.get("Referer")
|
redirect_url = request.headers.get("Referer")
|
||||||
if redirect_url is None:
|
if redirect_url is None:
|
||||||
redirect_url = request.args.get('redirect_url')
|
redirect_url = request.args.get('redirect_url')
|
||||||
if redirect_url is None:
|
if redirect_url is None:
|
||||||
redirect_url = "/"
|
redirect_url = "/"
|
||||||
app.logger.info("Token: {}".format(token))
|
|
||||||
response = make_response(redirect(redirect_url))
|
response = make_response(redirect(redirect_url))
|
||||||
response.set_cookie('tokens', base64.b64encode(token.encode('utf-8')))
|
response.set_cookie('tokens', base64.b64encode(token.encode('utf-8')))
|
||||||
return response
|
return response
|
||||||
@@ -189,8 +196,7 @@ def refresh():
|
|||||||
as we do not actually verify a password in this endpoint."""
|
as we do not actually verify a password in this endpoint."""
|
||||||
jwt_identity = get_jwt_identity()
|
jwt_identity = get_jwt_identity()
|
||||||
user = User.get_by_identifier(jwt_identity)
|
user = User.get_by_identifier(jwt_identity)
|
||||||
app.logger.info("Refreshing token for " + str(user))
|
logger.info("Refreshing token for " + str(user))
|
||||||
new_token = create_access_token(identity=user, fresh=False)
|
new_token = create_access_token(identity=user, fresh=False)
|
||||||
ret = {'access_token': new_token}
|
ret = {'access_token': new_token}
|
||||||
return jsonify(ret), 200
|
return jsonify(ret), 200
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ from backend.models.user_model import User
|
|||||||
from . import auth_bp
|
from . import auth_bp
|
||||||
from .oidc_config import PROVIDER_NAME, OIDC_PROVIDERS
|
from .oidc_config import PROVIDER_NAME, OIDC_PROVIDERS
|
||||||
|
|
||||||
|
|
||||||
OIDCAuthentication.oidc_auth_orig = OIDCAuthentication.oidc_auth
|
OIDCAuthentication.oidc_auth_orig = OIDCAuthentication.oidc_auth
|
||||||
OIDCAuthentication.oidc_logout_orig = OIDCAuthentication.oidc_logout
|
OIDCAuthentication.oidc_logout_orig = OIDCAuthentication.oidc_logout
|
||||||
|
|
||||||
@@ -46,6 +45,7 @@ def create_or_retrieve_user_from_userinfo(userinfo):
|
|||||||
|
|
||||||
if user is not None:
|
if user is not None:
|
||||||
app.logger.info("user found")
|
app.logger.info("user found")
|
||||||
|
app.logger.debug(f"user found: {email}")
|
||||||
user.last_seen = datetime.utcnow()
|
user.last_seen = datetime.utcnow()
|
||||||
# TODO: update user!
|
# TODO: update user!
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
@@ -54,21 +54,24 @@ def create_or_retrieve_user_from_userinfo(userinfo):
|
|||||||
user = User(email=email, first_name=userinfo.get("given_name", ""),
|
user = User(email=email, first_name=userinfo.get("given_name", ""),
|
||||||
last_name=userinfo.get("family_name", ""))
|
last_name=userinfo.get("family_name", ""))
|
||||||
|
|
||||||
app.logger.info("creating new user")
|
app.logger.info(f"creating new user: {email}")
|
||||||
|
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return user
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@auth_bp.route('/oidc', methods=['GET'])
|
@auth_bp.route('/oidc', methods=['GET'])
|
||||||
@oidc_auth.oidc_auth()
|
@oidc_auth.oidc_auth()
|
||||||
def oidc():
|
def oidc():
|
||||||
user_session = UserSession(flask.session)
|
user_session = UserSession(flask.session)
|
||||||
app.logger.info(user_session.userinfo)
|
app.logger.info(user_session.userinfo)
|
||||||
user = create_or_retrieve_user_from_userinfo(user_session.userinfo)
|
user = create_or_retrieve_user_from_userinfo(user_session.userinfo)
|
||||||
|
if user is None:
|
||||||
|
return ''
|
||||||
login_user(user)
|
login_user(user)
|
||||||
|
app.logger.info(f"logged in user: {str(user)}")
|
||||||
|
app.logger.debug(f"id token: {str(user_session.id_token)}")
|
||||||
return jsonify(id_token=user_session.id_token,
|
return jsonify(id_token=user_session.id_token,
|
||||||
access_token=flask.session['access_token'],
|
access_token=flask.session['access_token'],
|
||||||
userinfo=user_session.userinfo)
|
userinfo=user_session.userinfo)
|
||||||
@@ -78,3 +81,9 @@ def oidc():
|
|||||||
def oidc_logout():
|
def oidc_logout():
|
||||||
oidc_auth.oidc_logout()
|
oidc_auth.oidc_logout()
|
||||||
return redirect('/')
|
return redirect('/')
|
||||||
|
|
||||||
|
|
||||||
|
@oidc_auth.error_view
|
||||||
|
def error(error=None, error_description=None):
|
||||||
|
app.logger.error(f"Something wwent wrong with OIDC auth – error: {error}, message: {error_description}")
|
||||||
|
return jsonify({'error': error, 'message': error_description})
|
||||||
|
|||||||
Binary file not shown.
@@ -172,4 +172,4 @@ async_permanent_cron_recorder_checker = StateChecker(
|
|||||||
|
|
||||||
for r in Recorder.get_all():
|
for r in Recorder.get_all():
|
||||||
async_permanent_cron_recorder_checker.add_object_to_state_check(r.id)
|
async_permanent_cron_recorder_checker.add_object_to_state_check(r.id)
|
||||||
async_permanent_cron_recorder_checker.check_object_state() # initial check of all recorders
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
from backend import LrcException
|
from backend import LrcException
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger("lrc.tools.exception_decorator")
|
||||||
|
|
||||||
|
|
||||||
def exception_decorator(*exceptions):
|
def exception_decorator(*exceptions):
|
||||||
@@ -8,6 +11,9 @@ def exception_decorator(*exceptions):
|
|||||||
ret = func(*args, **kwargs)
|
ret = func(*args, **kwargs)
|
||||||
return ret
|
return ret
|
||||||
except exceptions as e:
|
except exceptions as e:
|
||||||
|
logger.error(str(e))
|
||||||
raise LrcException(e)
|
raise LrcException(e)
|
||||||
|
|
||||||
return new_func
|
return new_func
|
||||||
|
|
||||||
return decorator
|
return decorator
|
||||||
@@ -11,6 +11,7 @@ from typing import Union
|
|||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests.auth import HTTPBasicAuth
|
from requests.auth import HTTPBasicAuth
|
||||||
|
from requests.exceptions import ConnectionError
|
||||||
from multiprocessing.pool import ThreadPool
|
from multiprocessing.pool import ThreadPool
|
||||||
from multiprocessing.context import TimeoutError
|
from multiprocessing.context import TimeoutError
|
||||||
|
|
||||||
@@ -26,6 +27,8 @@ from backend.recorder_adapters.extron_smp import SMP35x
|
|||||||
from backend.tools.recorder_streams_sanity_checks import check_frame_is_valid, check_if_audio_is_valid
|
from backend.tools.recorder_streams_sanity_checks import check_frame_is_valid, check_if_audio_is_valid
|
||||||
from backend.tools.send_mail import send_error_mail, get_smtp_error_handler
|
from backend.tools.send_mail import send_error_mail, get_smtp_error_handler
|
||||||
|
|
||||||
|
from backend.tools.exception_decorator import exception_decorator
|
||||||
|
|
||||||
logger = logging.getLogger("lrc.tools.simple_state_checker")
|
logger = logging.getLogger("lrc.tools.simple_state_checker")
|
||||||
|
|
||||||
smtp_error_handler = get_smtp_error_handler(subject="Errors have been detected while checking recorder states!")
|
smtp_error_handler = get_smtp_error_handler(subject="Errors have been detected while checking recorder states!")
|
||||||
@@ -50,6 +53,7 @@ agent_states_lock = threading.RLock()
|
|||||||
agent_states = {}
|
agent_states = {}
|
||||||
|
|
||||||
|
|
||||||
|
@exception_decorator(ConnectionError)
|
||||||
def get_service_url(service_type: str):
|
def get_service_url(service_type: str):
|
||||||
if service_type in config['service_urls']:
|
if service_type in config['service_urls']:
|
||||||
return config['service_urls'][service_type]
|
return config['service_urls'][service_type]
|
||||||
@@ -64,19 +68,23 @@ def get_service_url(service_type: str):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@exception_decorator(ConnectionError)
|
||||||
def get_calender(rec_id):
|
def get_calender(rec_id):
|
||||||
params = {'agentid': rec_id}
|
params = {'agentid': rec_id}
|
||||||
url = get_service_url('org.opencastproject.scheduler') + "/calendars"
|
url = get_service_url('org.opencastproject.scheduler') + "/calendars"
|
||||||
res = session.get(url, params=params)
|
res = session.get(url, params=params)
|
||||||
if res.ok:
|
if res.ok:
|
||||||
return Calendar(res.text)
|
return Calendar(res.text)
|
||||||
|
raise LrcException(res.text, res.status_code)
|
||||||
|
|
||||||
|
|
||||||
|
@exception_decorator(ConnectionError)
|
||||||
def get_capture_agents():
|
def get_capture_agents():
|
||||||
url = get_service_url("org.opencastproject.capture.admin") + "/agents.json"
|
url = get_service_url("org.opencastproject.capture.admin") + "/agents.json"
|
||||||
res = session.get(url)
|
res = session.get(url)
|
||||||
if res.ok:
|
if res.ok:
|
||||||
return res.json()["agents"]["agent"]
|
return res.json()["agents"]["agent"]
|
||||||
|
raise LrcException(res.text, res.status_code)
|
||||||
|
|
||||||
|
|
||||||
def get_recorder_details_old():
|
def get_recorder_details_old():
|
||||||
@@ -117,19 +125,25 @@ def get_recorder_adapter(recorder_info: Union[dict, Recorder]) -> RecorderAdapte
|
|||||||
type = recorder_info.get("type")
|
type = recorder_info.get("type")
|
||||||
except KeyError:
|
except KeyError:
|
||||||
type = RecorderModel.get_by_id(recorder_info.get('recorder_model_id')).model_name
|
type = RecorderModel.get_by_id(recorder_info.get('recorder_model_id')).model_name
|
||||||
|
try:
|
||||||
if "SMP" in type:
|
if "SMP" in type:
|
||||||
rec = SMP35x(recorder_info.get('ip'), recorder_info.get('password'))
|
rec = SMP35x(recorder_info.get('ip'), recorder_info.get('password'))
|
||||||
else:
|
else:
|
||||||
rec = Epiphan(recorder_info.get('ip'), recorder_info.get("username"), recorder_info.get("password"))
|
rec = Epiphan(recorder_info.get('ip'), recorder_info.get("username"), recorder_info.get("password"))
|
||||||
return rec
|
return rec
|
||||||
|
except LrcException:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def check_stream_sanity(recorder_agent: Union[Recorder, dict], recorder_adapter: RecorderAdapter = None):
|
def check_stream_sanity(recorder_agent: Union[Recorder, dict], recorder_adapter: RecorderAdapter = None):
|
||||||
|
try:
|
||||||
if recorder_adapter is None:
|
if recorder_adapter is None:
|
||||||
recorder_info = get_recorder_by_name(recorder_agent.get('name'))
|
recorder_info = get_recorder_by_name(recorder_agent.get('name'))
|
||||||
recorder_adapter = get_recorder_adapter(recorder_info)
|
recorder_adapter = get_recorder_adapter(recorder_info)
|
||||||
if not recorder_adapter.is_recording():
|
if not recorder_adapter.is_recording():
|
||||||
return True, "not recording, so there is no stream!", recorder_agent.get('name')
|
return True, "not recording, so there is no stream!", recorder_agent.get('name')
|
||||||
|
except LrcException:
|
||||||
|
return False, "Could not determine if recorder is recording!", recorder_agent.get('name')
|
||||||
if recorder_agent.get('archive_stream1') is None and recorder_agent.get(
|
if recorder_agent.get('archive_stream1') is None and recorder_agent.get(
|
||||||
'archive_stream2') is None: # fall back to default names and rtsp
|
'archive_stream2') is None: # fall back to default names and rtsp
|
||||||
archive_stream_1_url = "rtsp://{}/{}".format(recorder_adapter.address, Config.DEFAULT_ARCHIVE_STREAM_1_NAME)
|
archive_stream_1_url = "rtsp://{}/{}".format(recorder_adapter.address, Config.DEFAULT_ARCHIVE_STREAM_1_NAME)
|
||||||
@@ -186,7 +200,12 @@ def check_capture_agent_state(recorder_agent: Union[Recorder, dict]):
|
|||||||
return True, "Recorder is in offline / maintenance mode", recorder_agent.get('name')
|
return True, "Recorder is in offline / maintenance mode", recorder_agent.get('name')
|
||||||
agent_state_error_msg = None
|
agent_state_error_msg = None
|
||||||
logger.debug("Checking Agent {}".format(recorder_agent.get('name')))
|
logger.debug("Checking Agent {}".format(recorder_agent.get('name')))
|
||||||
|
try:
|
||||||
c = get_calender(recorder_agent.get('name'))
|
c = get_calender(recorder_agent.get('name'))
|
||||||
|
except LrcException:
|
||||||
|
error_msg = "Could not get calender of recorder agent: {}!".format(recorder_agent.get('name'))
|
||||||
|
logger.fatal(error_msg)
|
||||||
|
return False, error_msg, recorder_agent.get('name')
|
||||||
is_recording_in_calendar = len(list(c.timeline.now())) >= 1
|
is_recording_in_calendar = len(list(c.timeline.now())) >= 1
|
||||||
if is_recording_in_calendar:
|
if is_recording_in_calendar:
|
||||||
logger.info("{} has entry in Calender and should therefore be recording... checking now!".format(
|
logger.info("{} has entry in Calender and should therefore be recording... checking now!".format(
|
||||||
|
|||||||
Reference in New Issue
Block a user