コード例 #1
0
ファイル: views.py プロジェクト: quru/qis
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))
コード例 #2
0
ファイル: views_pages.py プロジェクト: quru/qis
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)
コード例 #3
0
ファイル: views_pages.py プロジェクト: quru/qis
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()
コード例 #4
0
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))
コード例 #5
0
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))
コード例 #6
0
ファイル: views_pages.py プロジェクト: quru/qis
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
コード例 #7
0
ファイル: views_pages.py プロジェクト: quru/qis
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()
コード例 #8
0
ファイル: views_pages.py プロジェクト: quru/qis
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)
コード例 #9
0
ファイル: views_pages.py プロジェクト: quru/qis
def portfolio_view(human_id):
    try:
        # Find the portfolio
        folio = data_engine.get_portfolio(human_id=human_id, load_images=True)
        if not folio:
            raise DoesNotExistError('Portfolio \'%s\' does not exist' % human_id)

        # Ensure that the user has permission to view the portfolio
        user = get_session_user()
        permissions_engine.ensure_portfolio_permitted(
            folio,
            FolioPermission.ACCESS_VIEW,
            user
        )

        # Filter out images that the user can't view
        # so that we don't get broken images in the UI
        checked_folders = {}  # cache folders already checked
        folio_images_1 = folio.images
        folio_images_2 = []
        for fol_img in folio_images_1:
            folder_path = fol_img.image.folder.path
            if folder_path in checked_folders:
                folio_images_2.append(fol_img)
            elif permissions_engine.is_folder_permitted(
                folder_path,
                FolderPermission.ACCESS_VIEW,
                user,
                folder_must_exist=False  # though it should exist!
            ):
                checked_folders[folder_path] = True
                folio_images_2.append(fol_img)

        # Replace the original image list with the filtered one
        folio.images = folio_images_2

        # Generate the image viewing URLs, including any portfolio-specific changes
        web_view_params = {
            'format': 'jpg',
            'colorspace': 'srgb'
        }
        sizing_view_params = {
            'width': 800,
            'height': 800,
            'size_fit': True
        }
        pre_sized_images = [
            fol_img for fol_img in folio.images if fol_img.parameters and (
                ('width' in fol_img.parameters and fol_img.parameters['width']['value']) or
                ('height' in fol_img.parameters and fol_img.parameters['height']['value'])
            )
        ]
        for fol_img in folio.images:
            image_attrs = get_portfolio_image_attrs(fol_img, False, False, False)
            image_attrs.apply_dict(web_view_params, True, False, False)
            if len(pre_sized_images) == 0:
                image_attrs.apply_dict(sizing_view_params, True, False, False)
            # Here we normalise the attrs only after everything has been applied
            image_attrs.normalise_values()
            fol_img.url = url_for_image_attrs(image_attrs)

        return render_template(
            'portfolio_view.html',
            title=folio.name,
            folio=folio,
            removed_count=(len(folio_images_1) - len(folio_images_2))
        )
    except Exception as e:
        # Although this isn't a JSON API, we're still using it like a viewing API,
        # so get the correct HTTP status code to return. create_api_error_dict() also
        # logs security errors so we don't need to do that separately here.
        error_dict = create_api_error_dict(e, logger)
        if app.config['DEBUG']:
            raise
        return render_template(
            'portfolio_view.html',
            title='Portfolio',
            err_msg='This portfolio cannot be viewed: ' + safe_error_str(e)
        ), error_dict['status']
コード例 #10
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))