示例#1
0
 def _task_response(self, task, timeout_secs):
     task_completed = False
     try:
         # Wait for task to complete
         task = task_engine.wait_for_task(task.id, timeout_secs)
         if task is None:
             # Someone else deleted it? Shouldn't normally get here.
             raise TimeoutError()
         task_completed = True
         # Return the updated folder (or raise the exception)
         if isinstance(task.result, Exception):
             raise task.result
         return make_api_success_response(object_to_dict(task.result))
     except TimeoutError:
         # Return a 202 "task ongoing" response
         task_dict = object_to_dict(task) if task is not None else None
         # Decode the params before returning
         if task_dict and task_dict.get('params'):
             task_dict['params'] = pickle.loads(task_dict['params'])
         return make_api_success_response(task_dict, task_accepted=True)
     finally:
         if task and task_completed:
             try:
                 # Delete the task so another API call can be made immediately
                 data_engine.delete_object(task)
             except Exception:
                 pass
示例#2
0
 def get(self, folio_id, image_id=None):
     if image_id is None:
         # List images in the portfolio
         folio = data_engine.get_portfolio(folio_id, load_images=True)
         if folio is None:
             raise DoesNotExistError(str(folio_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_VIEW, get_session_user())
         image_list = [_prep_folioimage_object(fi) for fi in folio.images]
         return make_api_success_response(
             object_to_dict_list(image_list, _omit_fields))
     else:
         # Get a single portfolio-image
         db_session = data_engine.db_get_session()
         try:
             folio_image = data_engine.get_portfolio_image(
                 AttrObject(id=folio_id),
                 AttrObject(id=image_id),
                 _db_session=db_session)
             if folio_image is None:
                 raise DoesNotExistError(
                     str(folio_id) + '/' + str(image_id))
             # Check permissions
             permissions_engine.ensure_portfolio_permitted(
                 folio_image.portfolio, FolioPermission.ACCESS_VIEW,
                 get_session_user())
             return make_api_success_response(
                 object_to_dict(_prep_folioimage_object(folio_image),
                                _omit_fields + ['portfolio']))
         finally:
             db_session.close()
示例#3
0
 def get(self, folio_id, export_id=None):
     # Get the portfolio
     folio = data_engine.get_portfolio(folio_id)
     if folio is None:
         raise DoesNotExistError(str(folio_id))
     # Check permissions
     permissions_engine.ensure_portfolio_permitted(
         folio, FolioPermission.ACCESS_VIEW, get_session_user())
     if export_id is None:
         # List portfolio exports
         exports_list = [
             _prep_folioexport_object(folio, fe) for fe in folio.downloads
         ]
         return make_api_success_response(
             object_to_dict_list(exports_list, _omit_fields))
     else:
         # Get a single portfolio-export
         folio_export = data_engine.get_object(FolioExport, export_id)
         if folio_export is None:
             raise DoesNotExistError(str(export_id))
         if folio_export.folio_id != folio_id:
             raise ParameterError(
                 'export ID %d does not belong to portfolio ID %d' %
                 (export_id, folio_id))
         return make_api_success_response(
             object_to_dict(_prep_folioexport_object(folio, folio_export),
                            _omit_fields))
示例#4
0
 def get(self, permission_id=None):
     if permission_id is None:
         # List all permissions
         fp_list = data_engine.list_objects(FolderPermission)
         return make_api_success_response(object_to_dict_list(fp_list))
     else:
         # Get permission entry
         fp = data_engine.get_object(FolderPermission, permission_id)
         if fp is None:
             raise DoesNotExistError(str(permission_id))
         return make_api_success_response(object_to_dict(fp))
示例#5
0
 def get(self, permission_id=None):
     if permission_id is None:
         # List all permissions
         fp_list = data_engine.list_objects(FolderPermission)
         return make_api_success_response(object_to_dict_list(fp_list))
     else:
         # Get permission entry
         fp = data_engine.get_object(FolderPermission, permission_id)
         if fp is None:
             raise DoesNotExistError(str(permission_id))
         return make_api_success_response(object_to_dict(fp))
示例#6
0
 def get(self, group_id=None):
     if group_id is None:
         # List groups
         return make_api_success_response(
             object_to_dict_list(data_engine.list_objects(
                 Group, Group.name)))
     else:
         # Get single group
         group = data_engine.get_group(group_id=group_id, load_users=True)
         if group is None:
             raise DoesNotExistError(str(group_id))
         return make_api_success_response(object_to_dict(group))
示例#7
0
 def get(self, user_id=None):
     if user_id is None:
         # List users
         status_filter = self._get_validated_status_arg(request)
         ulist = data_engine.list_users(status=status_filter,
                                        order_field=User.username)
         return make_api_success_response(object_to_dict_list(ulist))
     else:
         # Get single user
         user = data_engine.get_user(user_id)
         if user is None:
             raise DoesNotExistError(str(user_id))
         return make_api_success_response(object_to_dict(user))
示例#8
0
 def get(self, group_id=None):
     if group_id is None:
         # List groups
         return make_api_success_response(
             object_to_dict_list(data_engine.list_objects(Group, Group.name))
         )
     else:
         # Get single group
         group = data_engine.get_group(group_id=group_id, load_users=True)
         if group is None:
             raise DoesNotExistError(str(group_id))
         # Do not give out anything password related
         gdict = object_to_dict(group)
         for udict in gdict['users']:
             del udict['password']
         return make_api_success_response(gdict)
示例#9
0
    def post(self, group_id):
        params = self._get_validated_object_parameters(request.form)
        group = data_engine.get_group(group_id=group_id, load_users=True)
        if group is None:
            raise DoesNotExistError(str(group_id))

        # Check permissions! The current user must have user admin to be here.
        # But if they don't also have permissions admin or superuser then we
        # must block the change if the new group would grant one of the same.
        if group.permissions.admin_permissions or group.permissions.admin_all:
            if not permissions_engine.is_permitted(
                SystemPermissions.PERMIT_ADMIN_PERMISSIONS, get_session_user()
            ):
                raise SecurityError(
                    'You cannot add users to a group that ' +
                    'grants permissions administration, because you do not ' +
                    'have permissions administration access yourself.'
                )

        user = data_engine.get_user(user_id=params['user_id'])
        if user is not None:
            if user not in group.users:
                group.users.append(user)
                data_engine.save_object(group)
                permissions_engine.reset()
        return make_api_success_response()
示例#10
0
 def delete(self, folio_id, export_id):
     db_session = data_engine.db_get_session()
     try:
         # Get the portfolio
         folio = data_engine.get_portfolio(folio_id, _db_session=db_session)
         if folio is None:
             raise DoesNotExistError(str(folio_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_EDIT, get_session_user())
         # Get the single portfolio-export
         folio_export = data_engine.get_object(FolioExport,
                                               export_id,
                                               _db_session=db_session)
         if folio_export is None:
             raise DoesNotExistError(str(export_id))
         if folio_export.folio_id != folio_id:
             raise ParameterError(
                 'export ID %d does not belong to portfolio ID %d' %
                 (export_id, folio_id))
         # Delete it and the export files
         delete_portfolio_export(folio_export,
                                 get_session_user(),
                                 'Deleted: ' + folio_export.describe(True),
                                 _db_session=db_session)
         return make_api_success_response()
     finally:
         db_session.close()
示例#11
0
    def post(self):
        params = self._get_validated_object_parameters(request.form)
        db_session = data_engine.db_get_session()
        db_commit = False
        try:
            db_group = data_engine.get_group(params['group_id'], _db_session=db_session)
            if db_group is None:
                raise DoesNotExistError(str(params['group_id']))
            db_folder = data_engine.get_folder(params['folder_id'], _db_session=db_session)
            if db_folder is None:
                raise DoesNotExistError(str(params['folder_id']))

            # This commits (needed for refresh to get the new ID)
            fp = FolderPermission(db_folder, db_group, params['access'])
            fp = data_engine.save_object(
                fp, refresh=True, _db_session=db_session, _commit=True
            )
            db_commit = True
            return make_api_success_response(object_to_dict(fp))
        finally:
            try:
                if db_commit:
                    db_session.commit()
                    permissions_engine.reset()
                else:
                    db_session.rollback()
            finally:
                db_session.close()
示例#12
0
 def post(self):
     # Require folios or admin_folios permission to create a portfolio
     permissions_engine.ensure_permitted(SystemPermissions.PERMIT_FOLIOS,
                                         get_session_user())
     db_session = data_engine.db_get_session()
     try:
         params = self._get_validated_object_parameters(request.form)
         folio = Folio(params['human_id'] or Folio.create_human_id(),
                       params['name'], params['description'],
                       get_session_user())
         self._set_permissions(folio, params, db_session)
         data_engine.create_portfolio(
             folio,
             get_session_user(),
             _db_session=db_session,
             _commit=True  # fail here if human_id not unique
         )
         # Return a clean object the same as for get(id)
         folio = data_engine.get_portfolio(folio.id,
                                           load_images=True,
                                           load_history=True)
         folio = _prep_folio_object(folio)
         return make_api_success_response(
             object_to_dict(folio, _omit_fields))
     finally:
         db_session.close()
示例#13
0
    def post(self, group_id):
        params = self._get_validated_object_parameters(request.form)
        group = data_engine.get_group(group_id=group_id, load_users=True)
        if group is None:
            raise DoesNotExistError(str(group_id))

        # Check permissions! The current user must have user admin to be here.
        # But if they don't also have permissions admin or superuser then we
        # must block the change if the new group would grant one of the same.
        if group.permissions.admin_permissions or group.permissions.admin_all:
            if not permissions_engine.is_permitted(
                    SystemPermissions.PERMIT_ADMIN_PERMISSIONS,
                    get_session_user()):
                raise SecurityError(
                    'You cannot add users to a group that ' +
                    'grants permissions administration, because you do not ' +
                    'have permissions administration access yourself.')

        user = data_engine.get_user(user_id=params['user_id'])
        if user is not None:
            if user not in group.users:
                group.users.append(user)
                data_engine.save_object(group)
                reset_user_sessions(user)
                permissions_engine.reset()
        return make_api_success_response()
示例#14
0
 def post(self, function_name):
     """ Launches a system task """
     # Validate function name
     if getattr(tasks, function_name, None) is None:
         raise DoesNotExistError(function_name)
     # Requires super user
     permissions_engine.ensure_permitted(SystemPermissions.PERMIT_SUPER_USER, get_session_user())
     # API parameters depend on the function
     params = self._get_validated_parameters(function_name, request.form)
     # Set remaining parameters for the task
     (description, task_params, priority, log_level, error_log_level, keep_secs) = self._get_task_data(
         function_name, params
     )
     # Queue the task
     db_task = task_engine.add_task(
         get_session_user(), description, function_name, task_params, priority, log_level, error_log_level, keep_secs
     )
     if db_task is None:
         raise AlreadyExistsError("Task is already running")
     # Decode the params before returning
     db_task.params = cPickle.loads(db_task.params)
     tdict = object_to_dict(db_task)
     if tdict.get("user") is not None:
         # Do not give out anything password related
         del tdict["user"]["password"]
     return make_api_success_response(tdict)
示例#15
0
    def delete(self, permission_id):
        db_session = data_engine.db_get_session()
        db_commit = False
        try:
            fp = data_engine.get_object(FolderPermission,
                                        permission_id,
                                        _db_session=db_session)
            if fp is None:
                raise DoesNotExistError(str(permission_id))
            try:
                data_engine.delete_folder_permission(fp,
                                                     _db_session=db_session,
                                                     _commit=False)
            except ValueError as e:
                raise ParameterError(str(e))

            db_commit = True
            return make_api_success_response()
        finally:
            if db_commit:
                db_session.commit()
                permissions_engine.reset_folder_permissions()
            else:
                db_session.rollback()
            db_session.close()
示例#16
0
def imagedetails():
    # Get/check parameters
    try:
        src = request.args.get('src', '')
        validate_string(src, 1, 1024)
    except ValueError as e:
        raise ParameterError(e)

    # v2.6.4 Don't allow this call to populate the database with unsupported files
    supported_file = (
        get_file_extension(src) in image_engine.get_image_formats(supported_only=True)
    )
    if not supported_file and path_exists(src, require_file=True):
        raise ImageError('The file is not a supported image format')

    # Get the image database entry
    db_image = auto_sync_file(src, data_engine, task_engine)
    if not db_image or db_image.status == Image.STATUS_DELETED:
        raise DoesNotExistError(src)

    # Require view permission or file admin
    permissions_engine.ensure_folder_permitted(
        db_image.folder,
        FolderPermission.ACCESS_VIEW,
        get_session_user()
    )

    return make_api_success_response(object_to_dict(
        _prep_image_object(db_image), _omit_fields
    ))
示例#17
0
 def get(self, template_id=None):
     if template_id is None:
         # List templates
         tlist = data_engine.list_objects(ImageTemplate, ImageTemplate.name)
         tdictlist = object_to_dict_list(tlist)
         for tdict in tdictlist:
             self._del_keys(tdict['template'], TemplateAPI.HIDE_FIELDS)
         return make_api_success_response(tdictlist)
     else:
         # Get single template
         template_info = data_engine.get_image_template(template_id)
         if template_info is None:
             raise DoesNotExistError(str(template_id))
         tdict = object_to_dict(template_info)
         self._del_keys(tdict['template'], TemplateAPI.HIDE_FIELDS)
         return make_api_success_response(tdict)
示例#18
0
 def delete(self, folio_id, image_id):
     db_session = data_engine.db_get_session()
     try:
         folio_image = data_engine.get_portfolio_image(
             AttrObject(id=folio_id),
             AttrObject(id=image_id),
             _db_session=db_session)
         if folio_image is None:
             raise DoesNotExistError(str(folio_id) + '/' + str(image_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio_image.portfolio, FolioPermission.ACCESS_EDIT,
             get_session_user())
         # Add history first so that we only commit once at the end
         folio = folio_image.portfolio
         data_engine.add_portfolio_history(folio,
                                           get_session_user(),
                                           FolioHistory.ACTION_IMAGE_CHANGE,
                                           '%s removed' %
                                           folio_image.image.src,
                                           _db_session=db_session,
                                           _commit=False)
         # Flag that exported zips will be out of date
         folio.last_updated = datetime.utcnow()
         # Delete the image from the portfolio and commit changes
         data_engine.delete_object(folio_image,
                                   _db_session=db_session,
                                   _commit=True)
         return make_api_success_response()
     finally:
         db_session.close()
示例#19
0
    def post(self):
        params = self._get_validated_object_parameters(request.form)
        db_session = data_engine.db_get_session()
        db_commit = False
        try:
            db_group = data_engine.get_group(params['group_id'],
                                             _db_session=db_session)
            if db_group is None:
                raise DoesNotExistError(str(params['group_id']))
            db_folder = data_engine.get_folder(params['folder_id'],
                                               _db_session=db_session)
            if db_folder is None:
                raise DoesNotExistError(str(params['folder_id']))

            # This commits (needed for refresh to get the new ID)
            fp = FolderPermission(db_folder, db_group, params['access'])
            fp = data_engine.save_object(fp,
                                         refresh=True,
                                         _db_session=db_session,
                                         _commit=True)
            db_commit = True
            return make_api_success_response(object_to_dict(fp))
        finally:
            try:
                if db_commit:
                    db_session.commit()
                    permissions_engine.reset_folder_permissions()
                else:
                    db_session.rollback()
            finally:
                db_session.close()
示例#20
0
 def get(self, folder_id=None):
     """ Gets a folder by path or ID, returning 1 level of children (sub-folders) """
     if folder_id is None:
         # Get folder from path, using auto_sync to pick up new and deleted disk folders
         path = self._get_validated_path_arg(request)
         db_folder = auto_sync_folder(path, data_engine, task_engine)
         if db_folder is None:
             raise DoesNotExistError(path)
     else:
         # Get folder from ID
         db_folder = data_engine.get_folder(folder_id)
         if db_folder is None:
             raise DoesNotExistError(str(folder_id))
     # View permission is required (ignoring view permission on parent+children)
     permissions_engine.ensure_folder_permitted(
         db_folder, FolderPermission.ACCESS_VIEW, get_session_user())
     # Get the folder again, this time with parent and children
     # (children possibly faked - see the get_folder() docs - which is why
     # we can't use db_folder mk2 normally, only serialize it and exit)
     status_filter = self._get_validated_status_arg(request)
     db_folder = data_engine.get_folder(db_folder.id,
                                        load_parent=True,
                                        load_children=True,
                                        children_status=status_filter)
     if db_folder is None:
         raise DoesNotExistError(str(folder_id))
     return make_api_success_response(object_to_dict(db_folder))
示例#21
0
    def delete(self, permission_id):
        db_session = data_engine.db_get_session()
        db_commit = False
        try:
            fp = data_engine.get_object(
                FolderPermission,
                permission_id,
                _db_session=db_session
            )
            if fp is None:
                raise DoesNotExistError(str(permission_id))
            try:
                data_engine.delete_folder_permission(
                    fp, _db_session=db_session, _commit=False
                )
            except ValueError as e:
                raise ParameterError(str(e))

            db_commit = True
            return make_api_success_response()
        finally:
            if db_commit:
                db_session.commit()
                permissions_engine.reset()
            else:
                db_session.rollback()
            db_session.close()
示例#22
0
 def put(self, permission_id):
     params = self._get_validated_object_parameters(request.form)
     fp = data_engine.get_object(FolderPermission, permission_id)
     if fp is None:
         raise DoesNotExistError(str(permission_id))
     fp.access = params['access']
     data_engine.save_object(fp)
     permissions_engine.reset_folder_permissions()
     return make_api_success_response(object_to_dict(fp))
示例#23
0
 def get(self, user_id=None):
     if user_id is None:
         # List users
         ulist = data_engine.list_users(order_field=User.username)
         # Do not give out anything password related
         udictlist = object_to_dict_list(ulist)
         for user in udictlist:
             del user['password']
         return make_api_success_response(udictlist)
     else:
         # Get single user
         user = data_engine.get_user(user_id)
         if user is None:
             raise DoesNotExistError(str(user_id))
         # Do not give out anything password related
         udict = object_to_dict(user)
         del udict['password']
         return make_api_success_response(udict)
示例#24
0
 def put(self, permission_id):
     params = self._get_validated_object_parameters(request.form)
     fp = data_engine.get_object(FolderPermission, permission_id)
     if fp is None:
         raise DoesNotExistError(str(permission_id))
     fp.access = params['access']
     data_engine.save_object(fp)
     permissions_engine.reset()
     return make_api_success_response(object_to_dict(fp))
示例#25
0
 def put(self, property_id):
     params = self._get_validated_object_parameters(request.form)
     db_prop = data_engine.get_object(Property, property_id)
     if db_prop is None:
         raise DoesNotExistError(str(property_id))
     db_prop.value = params['value']
     data_engine.save_object(db_prop)
     if property_id == Property.DEFAULT_TEMPLATE:
         image_engine.reset_templates()
     return make_api_success_response(object_to_dict(db_prop))
示例#26
0
 def get(self, image_id):
     db_img = data_engine.get_image(image_id=image_id)
     if not db_img:
         raise DoesNotExistError(str(image_id))
     else:
         # Require view permission or file admin
         permissions_engine.ensure_folder_permitted(
             db_img.folder, FolderPermission.ACCESS_VIEW,
             get_session_user())
         return make_api_success_response(
             object_to_dict(_prep_image_object(db_img)))
示例#27
0
    def put(self, image_id):
        params = self._get_validated_object_parameters(request.form)

        # Get image and update it
        db_img = data_engine.get_image(image_id=image_id)
        if not db_img:
            raise DoesNotExistError(str(image_id))

        # Require edit permission or file admin
        permissions_engine.ensure_folder_permitted(
            db_img.folder,
            FolderPermission.ACCESS_EDIT,
            get_session_user()
        )

        old_title = db_img.title
        old_description = db_img.description
        db_img.title = params['title']
        db_img.description = params['description']
        data_engine.save_object(db_img)

        # Get text changes. Max info length =
        # 100 + 200 + len('()' + '()' + 'Title: ' + ' / ' + 'Description: ') ==> 327
        title_diff = get_string_changes(old_title, params['title'], char_limit=100).strip()
        if not title_diff:
            # Try for deletions from title
            title_diff = get_string_changes(params['title'], old_title, char_limit=100).strip()
            if title_diff:
                title_diff = '(' + title_diff + ')'
        desc_diff = get_string_changes(
            old_description, params['description'], char_limit=200
        ).strip()
        if not desc_diff:
            # Try for deletions from description
            desc_diff = get_string_changes(
                params['description'], old_description, char_limit=200
            ).strip()
            if desc_diff:
                desc_diff = '(' + desc_diff + ')'
        info = ''
        if title_diff:
            info += 'Title: ' + title_diff
        if info and desc_diff:
            info += ' / '
        if desc_diff:
            info += 'Description: ' + desc_diff
        # Add change history
        data_engine.add_image_history(
            db_img,
            get_session_user(),
            ImageHistory.ACTION_EDITED,
            info
        )
        return make_api_success_response(object_to_dict(db_img))
示例#28
0
 def get(self, image_id):
     db_img = data_engine.get_image(image_id=image_id)
     if not db_img:
         raise DoesNotExistError(str(image_id))
     else:
         # Require view permission or file admin
         permissions_engine.ensure_folder_permitted(
             db_img.folder,
             FolderPermission.ACCESS_VIEW,
             get_session_user()
         )
         return make_api_success_response(object_to_dict(db_img))
示例#29
0
 def post(self):
     params = self._get_validated_object_parameters(request.form, True)
     # Do not use the password if this is an LDAP user
     if params['auth_type'] == User.AUTH_TYPE_LDAP:
         params['password'] = generate_password()
     # Create the new user
     user = User(params['first_name'], params['last_name'], params['email'],
                 params['username'], params['password'],
                 params['auth_type'], params['allow_api'],
                 User.STATUS_ACTIVE)
     data_engine.create_user(user)
     return make_api_success_response(object_to_dict(user))
示例#30
0
    def put(self, image_id):
        params = self._get_validated_object_parameters(request.form)

        # Get image and update it
        db_img = data_engine.get_image(image_id=image_id)
        if not db_img:
            raise DoesNotExistError(str(image_id))

        # Require edit permission or file admin
        permissions_engine.ensure_folder_permitted(
            db_img.folder, FolderPermission.ACCESS_EDIT, get_session_user())

        old_title = db_img.title
        old_description = db_img.description
        db_img.title = params['title']
        db_img.description = params['description']
        data_engine.save_object(db_img)

        # Get text changes. Max info length =
        # 100 + 200 + len('()' + '()' + 'Title: ' + ' / ' + 'Description: ') ==> 327
        title_diff = get_string_changes(old_title,
                                        params['title'],
                                        char_limit=100).strip()
        if not title_diff:
            # Try for deletions from title
            title_diff = get_string_changes(params['title'],
                                            old_title,
                                            char_limit=100).strip()
            if title_diff:
                title_diff = '(' + title_diff + ')'
        desc_diff = get_string_changes(old_description,
                                       params['description'],
                                       char_limit=200).strip()
        if not desc_diff:
            # Try for deletions from description
            desc_diff = get_string_changes(params['description'],
                                           old_description,
                                           char_limit=200).strip()
            if desc_diff:
                desc_diff = '(' + desc_diff + ')'
        info = ''
        if title_diff:
            info += 'Title: ' + title_diff
        if info and desc_diff:
            info += ' / '
        if desc_diff:
            info += 'Description: ' + desc_diff
        # Add change history
        data_engine.add_image_history(db_img, get_session_user(),
                                      ImageHistory.ACTION_EDITED, info)
        return make_api_success_response(
            object_to_dict(_prep_image_object(db_img)))
示例#31
0
 def get(self, task_id):
     db_task = task_engine.get_task(task_id=task_id, decode_attrs=True)
     if not db_task:
         raise DoesNotExistError(str(task_id))
     else:
         # Requires super user or task owner
         if not db_task.user or db_task.user.id != get_session_user_id():
             permissions_engine.ensure_permitted(SystemPermissions.PERMIT_SUPER_USER, get_session_user())
         tdict = object_to_dict(db_task)
         if tdict.get("user") is not None:
             # Do not give out anything password related
             del tdict["user"]["password"]
         return make_api_success_response(tdict)
示例#32
0
 def delete(self, user_id):
     user = data_engine.get_user(user_id=user_id)
     if user is None:
         raise DoesNotExistError(str(user_id))
     if user.id == 1:
         raise ParameterError('The \'admin\' user cannot be deleted')
     data_engine.delete_user(user)
     # If this is the current user, log out
     if get_session_user_id() == user_id:
         log_out()
     # Reset session caches
     reset_user_sessions(user)
     return make_api_success_response(object_to_dict(user))
示例#33
0
 def post(self):
     # Check permissions! The current user must have permissions admin to create groups.
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_ADMIN_PERMISSIONS, get_session_user())
     params = self._get_validated_object_parameters(request.form)
     if params['group_type'] == Group.GROUP_TYPE_SYSTEM:
         raise ParameterError('System groups cannot be created')
     group = Group(params['name'], params['description'],
                   params['group_type'])
     group.users = []
     self._set_permissions(group, params)
     data_engine.create_group(group)
     return make_api_success_response(object_to_dict(group))
示例#34
0
 def post(self, folio_id):
     db_session = data_engine.db_get_session()
     try:
         # Get the portfolio
         folio = data_engine.get_portfolio(folio_id, _db_session=db_session)
         if folio is None:
             raise DoesNotExistError(str(folio_id))
         # Check portfolio permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_EDIT, get_session_user())
         # Get the image by either ID or src
         params = self._get_validated_object_parameters(request.form, True)
         if 'image_id' in params:
             image = data_engine.get_image(params['image_id'],
                                           _db_session=db_session)
             if image is None:
                 raise DoesNotExistError(str(params['image_id']))
         else:
             image = auto_sync_file(params['image_src'],
                                    data_engine,
                                    task_engine,
                                    anon_history=True,
                                    burst_pdf=False,
                                    _db_session=db_session)
             if image is None or image.status == Image.STATUS_DELETED:
                 raise DoesNotExistError(params['image_src'])
         # Check image permissions
         permissions_engine.ensure_folder_permitted(
             image.folder, FolderPermission.ACCESS_VIEW, get_session_user(),
             False)
         # Add history first so that we only commit once at the end
         data_engine.add_portfolio_history(folio,
                                           get_session_user(),
                                           FolioHistory.ACTION_IMAGE_CHANGE,
                                           '%s added' % image.src,
                                           _db_session=db_session,
                                           _commit=False)
         # Flag that exported zips are now out of date
         folio.last_updated = datetime.utcnow()
         # Add the image and commit changes
         db_folio_image = data_engine.save_object(FolioImage(
             folio, image, params['image_parameters'], params['filename'],
             params['index']),
                                                  refresh=True,
                                                  _db_session=db_session,
                                                  _commit=True)
         return make_api_success_response(
             object_to_dict(_prep_folioimage_object(db_folio_image),
                            _omit_fields + ['portfolio']))
     finally:
         db_session.close()
示例#35
0
 def put(self, folio_id):
     db_session = data_engine.db_get_session()
     try:
         # Get portfolio
         folio = data_engine.get_portfolio(folio_id, _db_session=db_session)
         if folio is None:
             raise DoesNotExistError(str(folio_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_EDIT, get_session_user())
         # Update the object
         params = self._get_validated_object_parameters(request.form)
         permissions_changed = self._set_permissions(
             folio, params, db_session)
         changes = []
         if params['human_id'] != folio.human_id:
             changes.append('short URL changed')
         if params['name'] != folio.name:
             changes.append('name changed')
         if params['description'] != folio.description:
             changes.append('description changed')
         if permissions_changed:
             changes.append('permissions changed')
         folio.human_id = params['human_id'] or Folio.create_human_id()
         folio.name = params['name']
         folio.description = params['description']
         # Note: folio.last_updated is only for image changes
         #       (to know when to invalidate the exported zips)
         data_engine.add_portfolio_history(folio,
                                           get_session_user(),
                                           FolioHistory.ACTION_EDITED,
                                           ', '.join(changes).capitalize(),
                                           _db_session=db_session,
                                           _commit=False)
         data_engine.save_object(
             folio,
             _db_session=db_session,
             _commit=True  # fail here if human_id not unique
         )
         if permissions_changed:
             permissions_engine.reset_portfolio_permissions()
         # Return a clean object the same as for get(id)
         folio = data_engine.get_portfolio(folio.id,
                                           load_images=True,
                                           load_history=True)
         folio = _prep_folio_object(folio)
         return make_api_success_response(
             object_to_dict(folio, _omit_fields))
     finally:
         db_session.close()
示例#36
0
 def put(self, folder_id):
     """ Moves or renames a disk folder """
     params = self._get_validated_parameters(request.form)
     # Run this as a background task in case it takes a long time
     task = task_engine.add_task(get_session_user(),
                                 'Move disk folder %d' % folder_id,
                                 'move_folder', {
                                     'folder_id': folder_id,
                                     'path': params['path']
                                 }, Task.PRIORITY_HIGH, 'info', 'error', 10)
     if task is None:  # Task already submitted
         return make_api_success_response(task_accepted=True)
     else:
         return self._task_response(task, 30)
示例#37
0
 def delete(self, user_id):
     user = data_engine.get_user(user_id=user_id)
     if user is None:
         raise DoesNotExistError(str(user_id))
     if user.id == 1:
         raise ParameterError('The \'admin\' user cannot be deleted')
     data_engine.delete_user(user)
     # If this is the current user, log out
     if get_session_user_id() == user_id:
         log_out()
     # Do not give out anything password related
     udict = object_to_dict(user)
     del udict['password']
     return make_api_success_response(udict)
示例#38
0
 def post(self):
     """ Creates a disk folder """
     params = self._get_validated_parameters(request.form)
     try:
         db_folder = create_folder(params['path'], get_session_user(),
                                   data_engine, permissions_engine, logger)
         # Return a "fresh" object (without relationships loaded) to match PUT, DELETE
         db_folder = data_engine.get_folder(db_folder.id)
         return make_api_success_response(object_to_dict(db_folder))
     except ValueError as e:
         if type(e) is ValueError:
             raise ParameterError(str(e))
         else:
             raise  # Sub-classes of ValueError
示例#39
0
 def delete(self, template_id):
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_SUPER_USER, get_session_user())
     template_info = data_engine.get_image_template(template_id)
     if template_info is None:
         raise DoesNotExistError(str(template_id))
     db_default_template = data_engine.get_object(Property,
                                                  Property.DEFAULT_TEMPLATE)
     if template_info.name.lower() == db_default_template.value.lower():
         raise ParameterError(
             'The system default template cannot be deleted')
     data_engine.delete_object(template_info)
     image_engine.reset_templates()
     return make_api_success_response()
示例#40
0
 def put(self, folio_id, image_id):
     db_session = data_engine.db_get_session()
     try:
         folio_image = data_engine.get_portfolio_image(
             AttrObject(id=folio_id),
             AttrObject(id=image_id),
             _db_session=db_session)
         if folio_image is None:
             raise DoesNotExistError(str(folio_id) + '/' + str(image_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio_image.portfolio, FolioPermission.ACCESS_EDIT,
             get_session_user())
         # Update the object with any/all parameters that were passed in
         params = self._get_validated_object_parameters(request.form, False)
         changes = []
         affects_zips = False
         if (params['image_parameters'] is not None
                 and params['image_parameters'] != folio_image.parameters):
             folio_image.parameters = params['image_parameters']
             changes.append('image attributes changed')
             affects_zips = True
         if (params['filename'] is not None
                 and params['filename'] != folio_image.filename):
             folio_image.filename = params['filename']
             changes.append('filename changed')
             affects_zips = True
         if (params['index'] is not None
                 and params['index'] != folio_image.order_num):
             folio_image.order_num = params['index']
             changes.append('set as position %d' % (params['index'] + 1))
         if changes:
             # Flag if exported zips will be out of date
             if affects_zips:
                 folio_image.portfolio.last_updated = datetime.utcnow()
             # Add history and commit changes
             data_engine.add_portfolio_history(
                 folio_image.portfolio,
                 get_session_user(),
                 FolioHistory.ACTION_IMAGE_CHANGE,
                 '%s updated: %s' %
                 (folio_image.image.src, ', '.join(changes)),
                 _db_session=db_session,
                 _commit=True)
         return make_api_success_response(
             object_to_dict(_prep_folioimage_object(folio_image),
                            _omit_fields + ['portfolio']))
     finally:
         db_session.close()
示例#41
0
 def get(self, folio_id=None):
     # v4.1 Added support for /api/portfolios/?human_id=<human id>
     human_id = request.args.get('human_id', '')
     if not folio_id and not human_id:
         # List portfolios that the user can view
         folio_list = data_engine.list_portfolios(
             get_session_user(), FolioPermission.ACCESS_VIEW)
         folio_list = [_prep_folio_object(f) for f in folio_list]
         return make_api_success_response(
             object_to_dict_list(folio_list, _omit_fields))
     else:
         # Get single portfolio by either ID or v4.1 by human ID
         folio = data_engine.get_portfolio(folio_id,
                                           human_id,
                                           load_images=True,
                                           load_history=True)
         if folio is None:
             raise DoesNotExistError(human_id or str(folio_id))
         # Check permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_VIEW, get_session_user())
         folio = _prep_folio_object(folio)
         return make_api_success_response(
             object_to_dict(folio, _omit_fields))
示例#42
0
 def delete(self, group_id):
     # Check permissions! The current user must have permissions admin to delete groups.
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_ADMIN_PERMISSIONS, get_session_user())
     group = data_engine.get_group(group_id=group_id, load_users=True)
     if group is None:
         raise DoesNotExistError(str(group_id))
     try:
         data_engine.delete_group(group)
     except ValueError as e:
         raise ParameterError(str(e))
     # Reset permissions and session caches
     reset_user_sessions(group.users)
     permissions_engine.reset()
     return make_api_success_response()
示例#43
0
 def delete(self, group_id, user_id):
     group = data_engine.get_group(group_id=group_id, load_users=True)
     if group is None:
         raise DoesNotExistError(str(group_id))
     # Back up the object in case we need to restore it
     backup_group = copy.deepcopy(group)
     # Update group membership
     for idx, member in enumerate(group.users):
         if member.id == user_id:
             del group.users[idx]
             data_engine.save_object(group)
             permissions_engine.reset()
             _check_for_user_lockout(backup_group)
             break
     return make_api_success_response()
示例#44
0
 def delete(self, group_id):
     # Check permissions! The current user must have permissions admin to delete groups.
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_ADMIN_PERMISSIONS, get_session_user()
     )
     group = data_engine.get_group(group_id=group_id)
     if group is None:
         raise DoesNotExistError(str(group_id))
     try:
         data_engine.delete_group(group)
     except ValueError as e:
         raise ParameterError(str(e))
     # Reset permissions cache
     permissions_engine.reset()
     return make_api_success_response()
示例#45
0
 def post(self):
     # Check permissions! The current user must have permissions admin to create groups.
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_ADMIN_PERMISSIONS, get_session_user()
     )
     params = self._get_validated_object_parameters(request.form)
     if params['group_type'] == Group.GROUP_TYPE_SYSTEM:
         raise ParameterError('System groups cannot be created')
     group = Group(
         params['name'],
         params['description'],
         params['group_type']
     )
     group.users = []
     self._set_permissions(group, params)
     data_engine.create_group(group)
     return make_api_success_response(object_to_dict(group))
示例#46
0
 def post(self):
     params = self._get_validated_object_parameters(request.form, True)
     # Do not use the password if this is an LDAP user
     if params['auth_type'] == User.AUTH_TYPE_LDAP:
         params['password'] = generate_password()
     # Create the new user
     user = User(
         params['first_name'], params['last_name'],
         params['email'],
         params['username'], params['password'],
         params['auth_type'],
         params['allow_api'],
         User.STATUS_ACTIVE
     )
     data_engine.create_user(user)
     # Do not give out anything password related
     udict = object_to_dict(user)
     del udict['password']
     return make_api_success_response(udict)
示例#47
0
文件: views_api.py 项目: quru/qis
def imagedetails():
    # Get/check parameters
    try:
        src = request.args.get('src', '')
        validate_string(src, 1, 1024)
    except ValueError as e:
        raise ParameterError(e)

    # Get the image database entry
    db_image = auto_sync_file(src, data_engine, task_engine)
    if not db_image or db_image.status == Image.STATUS_DELETED:
        raise DoesNotExistError(src)

    # Require view permission or file admin
    permissions_engine.ensure_folder_permitted(
        db_image.folder,
        FolderPermission.ACCESS_VIEW,
        get_session_user()
    )

    return make_api_success_response(_image_dict(db_image))
示例#48
0
 def put(self, user_id):
     params = self._get_validated_object_parameters(request.form, False)
     user = data_engine.get_user(user_id=user_id)
     if user is None:
         raise DoesNotExistError(str(user_id))
     user.first_name = params['first_name']
     user.last_name = params['last_name']
     user.email = params['email']
     user.auth_type = params['auth_type']
     user.allow_api = params['allow_api']
     # Don't update the status field with this method
     # Update username only if non-LDAP
     if user.auth_type != User.AUTH_TYPE_LDAP:
         user.username = params['username']
     # Update password only if non-LDAP and a new one was passed in
     if user.auth_type != User.AUTH_TYPE_LDAP and params['password']:
         user.set_password(params['password'])
     data_engine.save_object(user)
     # Do not give out anything password related
     udict = object_to_dict(user)
     del udict['password']
     return make_api_success_response(udict)
示例#49
0
文件: views_api.py 项目: quru/qis
def token():
    username = None
    password = None
    # Get credentials - prefer HTTP Basic Auth
    if request.authorization:
        username = request.authorization.username
        password = request.authorization.password
    # Get credentials - but fall back to POST data
    if not username and not password:
        username = request.form.get('username', '')
        password = request.form.get('password', '')
    # Get credentials - ensure no blanks
    if not username:
        raise ParameterError('Username value cannot be blank')
    if not password:
        raise ParameterError('Password value cannot be blank')

    try:
        user = authenticate_user(username, password, data_engine, logger)
    except AuthenticationError as e:
        # Return 500 rather than 401 for authentication runtime errors
        raise Exception(unicode(e))

    if user is not None:
        if not user.allow_api:
            raise SecurityError('This account is not API enabled')
        elif user.status != User.STATUS_ACTIVE:
            raise SecurityError('This account is disabled')
        else:
            # Success
            http_auth = TimedTokenBasicAuthentication(app)
            token = http_auth.generate_auth_token({'user_id': user.id})
            return make_api_success_response({'token': token})

    # Login incorrect
    logger.warn('Incorrect API login for username ' + username)
    # Slow down scripted attacks
    sleep(1)
    raise SecurityError('Incorrect username or password')
示例#50
0
 def put(self, group_id):
     params = self._get_validated_object_parameters(request.form)
     group = data_engine.get_group(group_id=group_id, load_users=True)
     if group is None:
         raise DoesNotExistError(str(group_id))
     # Back up the object in case we need to restore it
     backup_group = copy.deepcopy(group)
     # Update group
     group.description = params['description']
     if group.group_type != Group.GROUP_TYPE_SYSTEM:
         group.group_type = params['group_type']
     if group.group_type == Group.GROUP_TYPE_LOCAL:
         group.name = params['name']
     permissions_changed = self._set_permissions(group, params)
     data_engine.save_object(group)
     # Reset permissions cache
     if permissions_changed:
         permissions_engine.reset()
         _check_for_user_lockout(backup_group)
     # Do not give out anything password related
     gdict = object_to_dict(group)
     for udict in gdict['users']:
         del udict['password']
     return make_api_success_response(gdict)
示例#51
0
 def get(self, template_name):
     try:
         template = image_engine.get_template(template_name)
         return make_api_success_response(template.to_dict())
     except KeyError:
         raise DoesNotExistError(template_name)
示例#52
0
文件: views_api.py 项目: quru/qis
def upload():
    # Get URL parameters for the upload
    file_list = request.files.getlist('files')
    path_index = request.form.get('path_index', '-1')   # Index into IMAGE_UPLOAD_DIRS or -1
    path = request.form.get('path', '')                 # Manual path when path_index is -1
    overwrite = request.form.get('overwrite')

    ret_dict = {}
    try:
        path_index = parse_int(path_index)
        overwrite = parse_boolean(overwrite)
        validate_string(path, 0, 1024)

        current_user = get_session_user()
        assert current_user is not None

        put_image_exception = None
        can_download = None
        for wkfile in file_list:
            original_filename = wkfile.filename
            if original_filename:
                db_image = None
                try:
                    # Save (also checks user-folder permissions)
                    _, db_image = image_engine.put_image(
                        current_user,
                        wkfile,
                        secure_filename(
                            original_filename,
                            app.config['ALLOW_UNICODE_FILENAMES']
                        ),
                        path_index,
                        path,
                        overwrite
                    )
                except Exception as e:
                    # Save the error to use as our overall return value
                    if put_image_exception is None:
                        put_image_exception = e
                    # This loop failure, add the error info to our return data
                    ret_dict[original_filename] = {'error': create_api_error_dict(e)}

                if db_image:
                    # Calculate download permission once (all files are going to same folder)
                    if can_download is None:
                        can_download = permissions_engine.is_folder_permitted(
                            db_image.folder,
                            FolderPermission.ACCESS_DOWNLOAD,
                            get_session_user()
                        )
                    # This loop success
                    ret_dict[original_filename] = _image_dict(db_image, can_download)

        # Loop complete. If we had an exception, raise it now.
        if put_image_exception is not None:
            raise put_image_exception

    except Exception as e:
        # put_image returns ValueError for parameter errors
        if type(e) is ValueError:
            e = ParameterError(unicode(e))
        # Attach whatever data we have to return with the error
        # Caller can then decide whether to continue if some files worked
        e.api_data = ret_dict
        raise e
    finally:
        # Store the result for the upload_complete page
        cache_engine.raw_put(
            'UPLOAD_API:' + str(current_user.id),
            ret_dict,
            expiry_secs=(60 * 60 * 24 * 7),
            integrity_check=True
        )

    # If here, all files were uploaded successfully
    return make_api_success_response(ret_dict)
示例#53
0
文件: views_api.py 项目: quru/qis
def imagelist():
    # Check parameters
    try:
        from_path = request.args.get('path', '')
        want_info = parse_boolean(request.args.get('attributes', ''))
        limit = parse_int(request.args.get('limit', '1000'))
        validate_string(from_path, 1, 1024)
    except ValueError as e:
        raise ParameterError(e)

    # Get extra parameters for image URL construction
    image_params = request.args.to_dict()
    if 'path' in image_params:
        del image_params['path']
    if 'attributes' in image_params:
        del image_params['attributes']
    if 'limit' in image_params:
        del image_params['limit']

    # Get directory listing
    directory_info = get_directory_listing(from_path, False, limit)
    if not directory_info.exists():
        raise DoesNotExistError('Invalid path')

    ret_list = []
    db_session = data_engine.db_get_session()
    db_commit = False
    try:
        # Auto-populate the folders database
        db_folder = auto_sync_folder(
            from_path, data_engine, task_engine, _db_session=db_session
        )
        db_session.commit()

        # Require view permission or file admin
        permissions_engine.ensure_folder_permitted(
            db_folder,
            FolderPermission.ACCESS_VIEW,
            get_session_user()
        )

        # Create the response
        file_list = directory_info.contents()
        img_types = image_engine.get_image_formats()
        base_folder = add_sep(directory_info.name())
        for f in file_list:
            # Filter out non-images
            if get_file_extension(f['filename']) in img_types:
                entry_path = base_folder + f['filename']
                entry = {
                    'filename': f['filename'],
                    'url': external_url_for('image', src=entry_path, **image_params)
                }
                if want_info:
                    db_entry = auto_sync_existing_file(
                        entry_path,
                        data_engine,
                        task_engine,
                        burst_pdf=False,  # Don't burst a PDF just by finding it here
                        _db_session=db_session
                    )
                    entry['id'] = db_entry.id if db_entry else 0
                    entry['folder_id'] = db_entry.folder_id if db_entry else 0
                    entry['title'] = db_entry.title if db_entry else ''
                    entry['description'] = db_entry.description if db_entry else ''
                    entry['width'] = db_entry.width if db_entry else 0
                    entry['height'] = db_entry.height if db_entry else 0
                ret_list.append(entry)

        db_commit = True
    finally:
        try:
            if db_commit:
                db_session.commit()
            else:
                db_session.rollback()
        finally:
            db_session.close()

    return make_api_success_response(ret_list)