def system_stats(): # Get parameters time_from = request.args.get('from', '') time_to = request.args.get('to', '') data_type = request.args.get('data_type', '1') embed = request.args.get('embed', '') try: # Validate params, get iso and datetime versions (iso_time_from, iso_time_to) = process_time_parameters(time_from, time_to) dt_time_from = parse_iso_datetime(iso_time_from) dt_time_to = parse_iso_datetime(iso_time_to) embed = parse_boolean(embed) return render_template('reports_system_stats.html', timezone=get_timezone_code(), timezone_seconds=get_timezone_offset(), time_from=dt_time_from, time_to=dt_time_to, data_type=data_type, embed=embed) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(safe_error_str(e))
def image_stats(): # Get parameters image_id = request.args.get('id', '') time_from = request.args.get('from', '') time_to = request.args.get('to', '') data_type = request.args.get('data_type', '1') embed = request.args.get('embed', '') try: # Validate params, get iso and datetime versions if image_id == '': raise ValueError('No image was specified.') image_id = parse_long(image_id) (iso_time_from, iso_time_to) = process_time_parameters(time_from, time_to) dt_time_from = parse_iso_datetime(iso_time_from) dt_time_to = parse_iso_datetime(iso_time_to) embed = parse_boolean(embed) return render_template( 'reports_image_stats.html', timezone=get_timezone_code(), timezone_seconds=get_timezone_offset(), time_from=dt_time_from, time_to=dt_time_to, data_type=data_type, db_image=data_engine.get_image(image_id=image_id), embed=embed) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(safe_error_str(e))
def trace_permissions(): embed = request.args.get('embed', '') user_id = request.args.get('user', '') folder_path = request.args.get('path', '') if folder_path == '': folder_path = os.path.sep folder = None user = None users = [] user_has_admin = False trace = None err_msg = None db_session = data_engine.db_get_session() try: # Get folder and selected user info # User can be None for an anonymous user user_id = parse_int(user_id) if user_id != 0: user = data_engine.get_user(user_id, _db_session=db_session) if user is None: raise DoesNotExistError('This user no longer exists') folder = data_engine.get_folder(folder_path=folder_path, _db_session=db_session) if folder is None or folder.status == Folder.STATUS_DELETED: raise DoesNotExistError('This folder no longer exists') # Get users list users = data_engine.list_users(status=User.STATUS_ACTIVE, order_field=User.username, _db_session=db_session) # Get the folder+user traced permissions trace = permissions_engine._trace_folder_permissions(folder, user) # Flag on the UI if the user has admin for gdict in trace['groups']: gperms = gdict['group'].permissions if gperms.admin_files or gperms.admin_all: user_has_admin = True break except Exception as e: log_security_error(e, request) err_msg = safe_error_str(e) finally: try: return render_template( 'admin_trace_permissions.html', embed=embed, folder=folder, folder_is_root=folder.is_root() if folder else False, user=user, user_list=users, trace=trace, user_has_admin=user_has_admin, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC) finally: db_session.close()
def image_stats(): # Get parameters image_id = request.args.get('id', '') time_from = request.args.get('from', '') time_to = request.args.get('to', '') data_type = request.args.get('data_type', '1') embed = request.args.get('embed', '') try: # Validate params, get iso and datetime versions if image_id == '': raise ValueError('No image was specified.') image_id = parse_long(image_id) (iso_time_from, iso_time_to) = process_time_parameters(time_from, time_to) dt_time_from = parse_iso_datetime(iso_time_from) dt_time_to = parse_iso_datetime(iso_time_to) embed = parse_boolean(embed) return render_template( 'reports_image_stats.html', timezone=get_timezone_code(), timezone_seconds=get_timezone_offset(), time_from=dt_time_from, time_to=dt_time_to, data_type=data_type, db_image=data_engine.get_image(image_id=image_id), embed=embed ) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(str(e))
def system_stats(): # Get parameters time_from = request.args.get('from', '') time_to = request.args.get('to', '') data_type = request.args.get('data_type', '1') embed = request.args.get('embed', '') try: # Validate params, get iso and datetime versions (iso_time_from, iso_time_to) = process_time_parameters(time_from, time_to) dt_time_from = parse_iso_datetime(iso_time_from) dt_time_to = parse_iso_datetime(iso_time_to) embed = parse_boolean(embed) return render_template( 'reports_system_stats.html', timezone=get_timezone_code(), timezone_seconds=get_timezone_offset(), time_from=dt_time_from, time_to=dt_time_to, data_type=data_type, embed=embed ) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(str(e))
def portfolio_download(human_id, filename): logger.debug('GET ' + request.url) try: # Find the portfolio folio = data_engine.get_portfolio(human_id=human_id) if not folio: raise DoesNotExistError('Portfolio \'%s\' does not exist' % human_id) # Ensure that the user has permission to download the portfolio user = get_session_user() permissions_engine.ensure_portfolio_permitted( folio, FolioPermission.ACCESS_DOWNLOAD, user) # Check that the filename is valid (note: assumes folio.downloads is eager loaded) if not filename: raise DoesNotExistError('No filename specified') folio_exports = [ dl for dl in folio.downloads if dl.filename == filename ] if not folio_exports: raise DoesNotExistError('Download \'%s\' is not available' % filename) folio_export = folio_exports[0] # The physical file should always exist when the data+filename exists # This also checks that the file path lies inside IMAGES_BASE_DIR zip_path = get_portfolio_export_file_path(folio_export) ensure_path_exists(zip_path, require_file=True) # Prepare to serve the file response = send_file( get_abs_path(zip_path), mimetype='application/zip', as_attachment=True, conditional=True, cache_timeout=31536000 # zips never change once created ) # Lastly write an audit record data_engine.add_portfolio_history(folio, user, FolioHistory.ACTION_DOWNLOADED, folio_export.filename) return response except httpexc.HTTPException: # Pass through HTTP 4xx and 5xx raise except SecurityError as e: if app.config['DEBUG']: raise log_security_error(e, request) raise httpexc.Forbidden() except DoesNotExistError as e: logger.warning('404 Not found: ' + str(e)) raise httpexc.NotFound(safe_error_str(e)) except Exception as e: if app.config['DEBUG']: raise logger.error('500 Error for ' + request.url + '\n' + str(e)) raise httpexc.InternalServerError(safe_error_str(e))
def template_edit(template_id): embed = request.args.get('embed', '') fields = None field_values = None db_template = None err_msg = None try: if template_id > 0: db_template = data_engine.get_image_template(template_id) # See also views_pages.publish fields = ImageAttrs.validators().copy() fields.update(TemplateAttrs.validators().copy()) # ...but here we use the template values as field values if db_template: template = TemplateAttrs(db_template.name, db_template.template) field_values = template.get_values_dict() else: # New template defaults field_values = { 'record_stats': True, 'expiry_secs': image_engine.DEFAULT_EXPIRY_SECS } except Exception as e: log_security_error(e, request) err_msg = safe_error_str(e) return render_template( 'admin_template_edit.html', fields=fields, field_values=field_values, supported_fields=image_engine.get_supported_operations(), embed=embed, template=db_template, err_msg=err_msg)
def folder_permissions(): folder_path = request.args.get('path', '') if folder_path == '': folder_path = os.path.sep group_id = request.args.get('group', '') if group_id == '': group_id = Group.ID_PUBLIC group = None folder = None current_perms = None groups = [] err_msg = None db_session = data_engine.db_get_session() try: # Get folder and group info group = data_engine.get_group(group_id, _db_session=db_session) if group is None: raise DoesNotExistError('This group no longer exists') folder = data_engine.get_folder(folder_path=folder_path, _db_session=db_session) if folder is None or folder.status == Folder.STATUS_DELETED: raise DoesNotExistError('This folder no longer exists') # Get groups list groups = data_engine.list_objects(Group, Group.name, _db_session=db_session) # Get the current permissions for the folder+group, which can be None. # Note that permissions_manager might fall back to the Public group if # this is None, but to keep the admin manageable we're going to deal # only with folder inheritance, not group inheritance too. current_perms = data_engine.get_nearest_folder_permission( folder, group, _load_nearest_folder=True, _db_session=db_session ) except Exception as e: log_security_error(e, request) err_msg = str(e) finally: try: return render_template( 'admin_folder_permissions.html', group=group, folder=folder, folder_is_root=folder.is_root() if folder else False, current_permissions=current_perms, group_list=groups, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC, GROUP_ID_EVERYONE=Group.ID_EVERYONE ) finally: db_session.close()
def token_login(): status = API_CODES.SUCCESS err_msg = '' token = request.args.get('token', '') next_url = request.args.get('next', '') try: if token: token_auth_class = app.config['API_AUTHENTICATION_CLASS'] auth_cls = getattr(flask_ext, token_auth_class, None) if not auth_cls: raise ValueError('Class flask_ext.%s was not found' % token_auth_class) auth_module = auth_cls(app) auth_object = auth_module.decode_auth_token(token) if auth_object: # The token is valid - set as logged in on the API auth_module.set_authenticated(auth_object) # Now set as logged in on the web session too auth_user = session_manager.get_session_user() if not auth_user: raise ValueError( 'Internal error - no session user returned - has BaseHttpAuthentication ' 'or session_manager been changed?' ) session_manager.log_in(auth_user) else: status = API_CODES.UNAUTHORISED err_msg = 'Invalid or expired token' else: status = API_CODES.INVALID_PARAM err_msg = 'No token value supplied' except SecurityError as se: if app.config['DEBUG']: raise log_security_error(se, request) status = API_CODES.UNAUTHORISED err_msg = str(se) except Exception as e: if app.config['DEBUG']: raise logger.error('Error performing API token to web login: '******'Sorry, an error occurred. Please try again later.' finally: if status != API_CODES.SUCCESS: session_manager.log_out() if next_url and status == API_CODES.SUCCESS: return redirect(next_url) else: return render_template( 'token_login.html', err_msg=safe_error_str(err_msg) ), status
def folder_permissions(): folder_path = request.args.get('path', '') if folder_path == '': folder_path = os.path.sep group_id = request.args.get('group', '') if group_id == '': group_id = Group.ID_PUBLIC group = None folder = None current_perms = None groups = [] err_msg = None db_session = data_engine.db_get_session() try: # Get folder and group info group = data_engine.get_group(group_id, _db_session=db_session) if group is None: raise DoesNotExistError('This group no longer exists') folder = data_engine.get_folder(folder_path=folder_path, _db_session=db_session) if folder is None or folder.status == Folder.STATUS_DELETED: raise DoesNotExistError('This folder no longer exists') # Get groups list groups = data_engine.list_objects(Group, Group.name, _db_session=db_session) # Get the current permissions for the folder+group, which can be None. # Note that permissions_manager might fall back to the Public group if # this is None, but to keep the admin manageable we're going to deal # only with folder inheritance, not group inheritance too. current_perms = data_engine.get_nearest_folder_permission( folder, group, _load_nearest_folder=True, _db_session=db_session) except Exception as e: log_security_error(e, request) err_msg = safe_error_str(e) finally: try: return render_template( 'admin_folder_permissions.html', group=group, folder=folder, folder_is_root=folder.is_root() if folder else False, current_permissions=current_perms, group_list=groups, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC, GROUP_ID_EVERYONE=Group.ID_EVERYONE) finally: db_session.close()
def user_edit(user_id): embed = request.args.get('embed', '') user = None err_msg = None try: if user_id > 0: user = data_engine.get_user(user_id=user_id, load_groups=True) except Exception as e: log_security_error(e, request) err_msg = str(e) return render_template('admin_user_edit.html', embed=embed, user=user, err_msg=err_msg, AUTH_TYPE_PASSWORD=User.AUTH_TYPE_PASSWORD, STATUS_ACTIVE=User.STATUS_ACTIVE)
def datafeed_image(): try: # Get parameters image_id = parse_long(request.args.get('id', '')) dt_time_from = parse_iso_datetime(request.args.get('from')) dt_time_to = parse_iso_datetime(request.args.get('to')) data_type = parse_int(request.args.get('data_type', '')) require_full_period = (data_type < 8) if require_full_period: # Stop at 'now' minus the stats gap so we don't return incomplete stats dt_time_limit = datetime.utcnow() - timedelta( minutes=app.config['STATS_FREQUENCY']) if dt_time_to > dt_time_limit: dt_time_to = dt_time_limit # Get stats and convert to chart data results = data_engine.search_image_stats(dt_time_from, dt_time_to, image_id) results = add_zero_stats(dt_time_from, dt_time_to, app.config['STATS_FREQUENCY'], results, ImageStats) data = _db_results_to_flot_data(results, data_type) return make_json_response(200, data=data, first=0 if len(data) == 0 else data[0][0], last=0 if len(data) == 0 else data[-1][0]) except Exception as e: if not log_security_error(e, request): logger.error('Error reading image stats: ' + str(e)) if app.config['DEBUG']: raise return make_json_response(200, data=[], first=0, last=0)
def user_edit(user_id): embed = request.args.get('embed', '') user = None err_msg = None try: if user_id > 0: user = data_engine.get_user(user_id=user_id, load_groups=True) except Exception as e: log_security_error(e, request) err_msg = str(e) return render_template( 'admin_user_edit.html', embed=embed, user=user, err_msg=err_msg, AUTH_TYPE_PASSWORD=User.AUTH_TYPE_PASSWORD, STATUS_ACTIVE=User.STATUS_ACTIVE )
def group_edit(group_id): embed = request.args.get('embed', '') group = None users = [] err_msg = None try: users = data_engine.list_users(status=User.STATUS_ACTIVE, order_field=User.username) if group_id > 0: group = data_engine.get_group(group_id=group_id, load_users=True) except Exception as e: log_security_error(e, request) err_msg = safe_error_str(e) return render_template('admin_group_edit.html', embed=embed, users=users, group=group, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC, GROUP_TYPE_LOCAL=Group.GROUP_TYPE_LOCAL, GROUP_TYPE_SYSTEM=Group.GROUP_TYPE_SYSTEM, STATUS_ACTIVE=User.STATUS_ACTIVE)
def group_edit(group_id): embed = request.args.get('embed', '') group = None users = [] err_msg = None try: users = data_engine.list_users(status=User.STATUS_ACTIVE, order_field=User.username) if group_id > 0: group = data_engine.get_group(group_id=group_id, load_users=True) except Exception as e: log_security_error(e, request) err_msg = str(e) return render_template( 'admin_group_edit.html', embed=embed, users=users, group=group, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC, GROUP_TYPE_LOCAL=Group.GROUP_TYPE_LOCAL, GROUP_TYPE_SYSTEM=Group.GROUP_TYPE_SYSTEM, STATUS_ACTIVE=User.STATUS_ACTIVE )
def datafeed_image(): try: # Get parameters image_id = parse_long(request.args.get('id', '')) dt_time_from = parse_iso_datetime(request.args.get('from')) dt_time_to = parse_iso_datetime(request.args.get('to')) data_type = parse_int(request.args.get('data_type', '')) require_full_period = (data_type < 8) if require_full_period: # Stop at 'now' minus the stats gap so we don't return incomplete stats dt_time_limit = datetime.utcnow() - timedelta(minutes=app.config['STATS_FREQUENCY']) if dt_time_to > dt_time_limit: dt_time_to = dt_time_limit # Get stats and convert to chart data results = data_engine.search_image_stats(dt_time_from, dt_time_to, image_id) results = add_zero_stats( dt_time_from, dt_time_to, app.config['STATS_FREQUENCY'], results, ImageStats ) data = _db_results_to_flot_data(results, data_type) return make_json_response( 200, data=data, first=0 if len(data) == 0 else data[0][0], last=0 if len(data) == 0 else data[-1][0] ) except Exception as e: if not log_security_error(e, request): logger.error('Error reading image stats: ' + str(e)) if app.config['DEBUG']: raise return make_json_response( 200, data=[], first=0, last=0 )
def topten(): # Get parameters days = request.args.get('days', '1') limit = request.args.get('number', '10') data_type = request.args.get('data_type', '2') try: results = [] db_session = data_engine.db_get_session() try: # Convert params to ints days = parse_int(days) limit = parse_int(limit) data_type = parse_int(data_type) # Set options if days < 1: days = 1 if days > 30: days = 30 if limit < 10: limit = 10 if limit > 100: limit = 100 if data_type == 1: order = '-total_requests' elif data_type == 2: order = '-total_views' elif data_type == 3: order = '-total_cached_views' elif data_type == 4: order = '-total_downloads' elif data_type == 5: order = '-total_bytes' elif data_type == 6: order = '-total_seconds' elif data_type == 7: order = '-max_seconds' else: raise ValueError('Invalid data_type %d' % data_type) # Get initial stats top_stats = data_engine.summarise_image_stats( datetime.utcnow() - timedelta(days=days), datetime.utcnow(), limit=limit, order_by=order, _db_session=db_session) # Convert stats list to an image list for result in top_stats: db_image = data_engine.get_image(image_id=result[0], _db_session=db_session) if db_image: results.append({ 'id': db_image.id, 'src': db_image.src, 'requests': result[1], 'views': result[2], 'cached_views': result[3], 'downloads': result[4], 'bytes': result[5], 'seconds': result[6], 'max_seconds': result[7] }) finally: db_session.close() return render_template('reports_topten.html', days=days, data_type=data_type, number=limit, results=results) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(safe_error_str(e))
def trace_permissions(): embed = request.args.get('embed', '') user_id = request.args.get('user', '') folder_path = request.args.get('path', '') if folder_path == '': folder_path = os.path.sep folder = None user = None users = [] user_has_admin = False trace = None err_msg = None db_session = data_engine.db_get_session() try: # Get folder and selected user info # User can be None for an anonymous user user_id = parse_int(user_id) if user_id != 0: user = data_engine.get_user(user_id, _db_session=db_session) if user is None: raise DoesNotExistError('This user no longer exists') folder = data_engine.get_folder(folder_path=folder_path, _db_session=db_session) if folder is None or folder.status == Folder.STATUS_DELETED: raise DoesNotExistError('This folder no longer exists') # Get users list users = data_engine.list_users( status=User.STATUS_ACTIVE, order_field=User.username, _db_session=db_session ) # Get the folder+user traced permissions trace = permissions_engine._trace_folder_permissions(folder, user) # Flag on the UI if the user has admin for gdict in trace['groups']: gperms = gdict['group'].permissions if gperms.admin_files or gperms.admin_all: user_has_admin = True break except Exception as e: log_security_error(e, request) err_msg = str(e) finally: try: return render_template( 'admin_trace_permissions.html', embed=embed, folder=folder, folder_is_root=folder.is_root() if folder else False, user=user, user_list=users, trace=trace, user_has_admin=user_has_admin, err_msg=err_msg, GROUP_ID_PUBLIC=Group.ID_PUBLIC ) finally: db_session.close()
def topten(): # Get parameters days = request.args.get('days', '1') limit = request.args.get('number', '10') data_type = request.args.get('data_type', '2') try: results = [] db_session = data_engine.db_get_session() try: # Convert params to ints days = parse_int(days) limit = parse_int(limit) data_type = parse_int(data_type) # Set options if days < 1: days = 1 if days > 30: days = 30 if limit < 10: limit = 10 if limit > 100: limit = 100 if data_type == 1: order = '-total_requests' elif data_type == 2: order = '-total_views' elif data_type == 3: order = '-total_cached_views' elif data_type == 4: order = '-total_downloads' elif data_type == 5: order = '-total_bytes' elif data_type == 6: order = '-total_seconds' elif data_type == 7: order = '-max_seconds' else: raise ValueError('Invalid data_type %d' % data_type) # Get initial stats top_stats = data_engine.summarise_image_stats( datetime.utcnow() - timedelta(days=days), datetime.utcnow(), limit=limit, order_by=order, _db_session=db_session ) # Convert stats list to an image list for result in top_stats: db_image = data_engine.get_image(image_id=result[0], _db_session=db_session) if db_image: results.append({ 'id': db_image.id, 'src': db_image.src, 'requests': result[1], 'views': result[2], 'cached_views': result[3], 'downloads': result[4], 'bytes': result[5], 'seconds': result[6], 'max_seconds': result[7] }) finally: db_session.close() return render_template( 'reports_topten.html', days=days, data_type=data_type, number=limit, results=results ) except Exception as e: log_security_error(e, request) if app.config['DEBUG']: raise raise InternalServerError(str(e))