예제 #1
0
파일: views_data_api.py 프로젝트: quru/qis
def _check_for_user_lockout(original_object):
    """
    Only to be called when the current user is known to have PERMIT_ADMIN_USERS
    permission, checks that the current user hasn't locked themselves out from
    user administration.
    Also checks that the admin user's administration permission has not been
    accidentally revoked.
    If a lockout has occurred, the supplied original object is re-saved and a
    ParameterError is raised.
    """
    user_ids = [get_session_user_id(), 1]
    for user_id in user_ids:
        db_user = data_engine.get_user(user_id=user_id)
        if db_user:
            try:
                # Require user administration
                if not permissions_engine.is_permitted(
                    SystemPermissions.PERMIT_ADMIN_USERS,
                    db_user
                ): raise ParameterError()
                # For the admin user, also require permissions administration
                if user_id == 1 and not permissions_engine.is_permitted(
                    SystemPermissions.PERMIT_ADMIN_PERMISSIONS,
                    db_user
                ): raise ParameterError()
            except ParameterError:
                # Roll back permissions
                data_engine.save_object(original_object)
                permissions_engine.reset()
                # Raise API error
                who = 'the \'admin\' user' if user_id == 1 else 'you'
                raise ParameterError(
                    'This change would lock %s out of administration' % who
                )
예제 #2
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()
예제 #3
0
def _check_for_user_lockout(original_object):
    """
    Only to be called when the current user is known to have PERMIT_ADMIN_USERS
    permission, checks that the current user hasn't locked themselves out from
    user administration.
    Also checks that the admin user's administration permission has not been
    accidentally revoked.
    If a lockout has occurred, the supplied original object is re-saved and a
    ParameterError is raised.
    """
    user_ids = [get_session_user_id(), 1]
    for user_id in user_ids:
        db_user = data_engine.get_user(user_id=user_id)
        if db_user:
            try:
                # Require user administration
                if not permissions_engine.is_permitted(
                        SystemPermissions.PERMIT_ADMIN_USERS, db_user):
                    raise ParameterError()
                # For the admin user, also require permissions administration
                if user_id == 1 and not permissions_engine.is_permitted(
                        SystemPermissions.PERMIT_ADMIN_PERMISSIONS, db_user):
                    raise ParameterError()
            except ParameterError:
                # Roll back permissions
                data_engine.save_object(original_object)
                permissions_engine.reset()
                # Raise API error
                who = 'the \'admin\' user' if user_id == 1 else 'you'
                raise ParameterError(
                    'This change would lock %s out of administration' % who)
예제 #4
0
파일: views_data_api.py 프로젝트: quru/qis
    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()
예제 #5
0
 def test_task_server(self):
     # Create some stats
     t_now = datetime.utcnow()
     dm.save_object(SystemStats(
         1, 1, 1, 1, 1, 1, 1, 1, 1, 1, t_now - timedelta(minutes=5), t_now
     ))
     # We should now have stats
     sys_stats = dm.search_system_stats(t_now - timedelta(minutes=60), t_now)
     self.assertGreater(len(sys_stats), 0)
     # Check current task list entries
     tasks = dm.list_objects(Task, order_field=Task.id)
     task_list_len = len(tasks)
     # Post a background task to purge the stats
     KEEP_SECS = 10
     task_obj = tm.add_task(
         None,
         'Purge system statistics',
         'purge_system_stats',
         {'before_time': t_now},
         Task.PRIORITY_NORMAL,
         'info', 'error',
         KEEP_SECS
     )
     self.assertIsNotNone(task_obj)
     # Check it really got added
     tasks = dm.list_objects(Task, order_field=Task.id)
     self.assertEqual(len(tasks), task_list_len + 1)
     task_list_len = len(tasks)
     # Post it again, make sure there is no dupe added
     dupe_task_obj = tm.add_task(
         None,
         'Purge system statistics',
         'purge_system_stats',
         {'before_time': t_now},
         Task.PRIORITY_NORMAL,
         'info', 'error',
         KEEP_SECS
     )
     self.assertIsNone(dupe_task_obj)
     # Check it really didn't get re-added
     tasks = dm.list_objects(Task, order_field=Task.id)
     self.assertEqual(len(tasks), task_list_len)
     task = tasks[-1]
     self.assertEqual(task.id, task_obj.id)
     # Wait for task completion
     tm.wait_for_task(task_obj.id, 20)
     # We should now have no stats
     t_now = datetime.utcnow()
     sys_stats = dm.search_system_stats(t_now - timedelta(minutes=60), t_now)
     self.assertEqual(len(sys_stats), 0)
     # The completed task should only be removed after the delay we specified
     task = dm.get_object(Task, task_obj.id)
     self.assertIsNotNone(task)
     self.assertEqual(task.status, Task.STATUS_COMPLETE)
     # Wait for keep time + task server's poll time
     time.sleep(KEEP_SECS + 10)
     # Should now be gone
     task = dm.get_object(Task, task_obj.id)
     self.assertIsNone(task)
예제 #6
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))
예제 #7
0
파일: views_data_api.py 프로젝트: quru/qis
 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))
예제 #8
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))
예제 #9
0
파일: views_data_api.py 프로젝트: quru/qis
    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))
예제 #10
0
 def test_task_server(self):
     # Create some stats
     t_now = datetime.utcnow()
     dm.save_object(
         SystemStats(1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                     t_now - timedelta(minutes=5), t_now))
     # We should now have stats
     sys_stats = dm.search_system_stats(t_now - timedelta(minutes=60),
                                        t_now)
     self.assertGreater(len(sys_stats), 0)
     # Check current task list entries
     tasks = dm.list_objects(Task, order_field=Task.id)
     task_list_len = len(tasks)
     # Post a background task to purge the stats
     KEEP_SECS = 10
     task_obj = tm.add_task(None, 'Purge system statistics',
                            'purge_system_stats', {'before_time': t_now},
                            Task.PRIORITY_NORMAL, 'info', 'error',
                            KEEP_SECS)
     self.assertIsNotNone(task_obj)
     # Check it really got added
     tasks = dm.list_objects(Task, order_field=Task.id)
     self.assertEqual(len(tasks), task_list_len + 1)
     task_list_len = len(tasks)
     # Post it again, make sure there is no dupe added
     dupe_task_obj = tm.add_task(None, 'Purge system statistics',
                                 'purge_system_stats',
                                 {'before_time': t_now},
                                 Task.PRIORITY_NORMAL, 'info', 'error',
                                 KEEP_SECS)
     self.assertIsNone(dupe_task_obj)
     # Check it really didn't get re-added
     tasks = dm.list_objects(Task, order_field=Task.id)
     self.assertEqual(len(tasks), task_list_len)
     task = tasks[-1]
     self.assertEqual(task.id, task_obj.id)
     # Wait for task completion
     tm.wait_for_task(task_obj.id, 10)
     # We should now have no stats
     t_now = datetime.utcnow()
     sys_stats = dm.search_system_stats(t_now - timedelta(minutes=60),
                                        t_now)
     self.assertEqual(len(sys_stats), 0)
     # The completed task should only be removed after the delay we specified
     task = dm.get_object(Task, task_obj.id)
     self.assertIsNotNone(task)
     self.assertEqual(task.status, Task.STATUS_COMPLETE)
     # Wait for keep time + task server's poll time
     time.sleep(KEEP_SECS + 10)
     # Should now be gone
     task = dm.get_object(Task, task_obj.id)
     self.assertIsNone(task)
예제 #11
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)))
예제 #12
0
 def put(self, template_id):
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_SUPER_USER, get_session_user())
     params = self._get_validated_object_parameters(request.form)
     template = data_engine.get_image_template(template_id)
     if template is None:
         raise DoesNotExistError(str(template_id))
     template.name = params['name']
     template.description = params['description']
     template.template = params['template']
     data_engine.save_object(template)
     image_engine.reset_templates()
     return self.get(template.id)
예제 #13
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()
예제 #14
0
파일: user_edit.py 프로젝트: quru/qis
def apply_user(params):
    from imageserver.flask_app import data_engine
    from imageserver.models import User
    from imageserver.errors import DBError
    try:
        existing_user = data_engine.get_user(username=params.username)

        if params.mode == Parameters.MODE_ADD:
            if existing_user:
                if existing_user.status == User.STATUS_DELETED:
                    raise ValueError('A deleted user record for this username already exists')
                else:
                    raise ValueError('This username already exists')
            else:
                data_engine.create_user(User(
                    params.firstname,
                    params.lastname,
                    params.email,
                    params.username,
                    params.password,
                    User.AUTH_TYPE_PASSWORD,
                    False,
                    User.STATUS_ACTIVE
                ))
                log('User created')
        elif params.mode == Parameters.MODE_UPDATE:
            if not existing_user:
                raise ValueError('The username was not found')
            if existing_user.status == User.STATUS_DELETED:
                raise ValueError('This user record is deleted')
            existing_user.first_name = params.firstname
            existing_user.last_name = params.lastname
            existing_user.email = params.email
            existing_user.set_password(params.password)
            data_engine.save_object(existing_user)
            log('User updated')
        else:
            if not existing_user:
                raise ValueError('The username was not found')
            data_engine.delete_user(existing_user)
            log('User deleted')

        return RETURN_OK
    except ValueError as e:
        error(str(e))
        return RETURN_BAD_PARAMS
    except DBError as e:
        error(str(e))
        return RETURN_DB_ERROR
예제 #15
0
파일: views_data_api.py 프로젝트: quru/qis
 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()
예제 #16
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()
예제 #17
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)
             reset_user_sessions(member)
             permissions_engine.reset()
             _check_for_user_lockout(backup_group)
             break
     return make_api_success_response()
예제 #18
0
파일: views_data_api.py 프로젝트: quru/qis
    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()
예제 #19
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 permissions
         permissions_engine.ensure_portfolio_permitted(
             folio, FolioPermission.ACCESS_EDIT, get_session_user())
         # Block the export now if it would create an empty zip file
         if len(folio.images) == 0:
             raise ParameterError(
                 'this portfolio is empty and cannot be published')
         # Create a folio-export record and start the export as a background task
         params = self._get_validated_object_parameters(request.form)
         folio_export = FolioExport(folio, params['description'],
                                    params['originals'],
                                    params['image_parameters'],
                                    params['expiry_time'])
         data_engine.add_portfolio_history(folio,
                                           get_session_user(),
                                           FolioHistory.ACTION_PUBLISHED,
                                           folio_export.describe(True),
                                           _db_session=db_session,
                                           _commit=False)
         folio_export = data_engine.save_object(folio_export,
                                                refresh=True,
                                                _db_session=db_session,
                                                _commit=True)
         export_task = task_engine.add_task(
             get_session_user(), 'Export portfolio %d / export %d' %
             (folio.id, folio_export.id), 'export_portfolio', {
                 'export_id': folio_export.id,
                 'ignore_errors': False
             }, Task.PRIORITY_NORMAL, 'info', 'error', 60)
         # Update and return the folio-export record with the task ID
         folio_export.task_id = export_task.id
         data_engine.save_object(folio_export,
                                 _db_session=db_session,
                                 _commit=True)
         return make_api_success_response(object_to_dict(
             _prep_folioexport_object(folio, folio_export),
             _omit_fields + ['portfolio']),
                                          task_accepted=True)
     finally:
         db_session.close()
예제 #20
0
 def post(self):
     permissions_engine.ensure_permitted(
         SystemPermissions.PERMIT_SUPER_USER, get_session_user())
     params = self._get_validated_object_parameters(request.form)
     template = ImageTemplate(params['name'], params['description'],
                              params['template'])
     template = data_engine.save_object(template, refresh=True)
     image_engine.reset_templates()
     return self.get(template.id)
예제 #21
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)
     # Reset session caches
     reset_user_sessions(user)
     return make_api_success_response(object_to_dict(user))
예제 #22
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 and session caches
     if permissions_changed:
         reset_user_sessions(group.users)
         permissions_engine.reset()
         _check_for_user_lockout(backup_group)
     return make_api_success_response(object_to_dict(group))
예제 #23
0
파일: views_data_api.py 프로젝트: quru/qis
 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)
예제 #24
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()
예제 #25
0
파일: v2_upgrade.py 프로젝트: quru/qis
def create_default_template():
    from imageserver.flask_app import app, data_engine
    from imageserver.models import ImageTemplate, Property

    log('Creating default image template')

    existing_obj = data_engine.get_image_template(tempname='Default')
    if existing_obj is None:
        data_engine.save_object(ImageTemplate(
            'Default',
            'Defines the system defaults for image generation if the '
            'image does not specify a template or specific parameter value', {
                'format': {'value': app.config.get('IMAGE_FORMAT_DEFAULT', '')},
                'quality': {'value': app.config.get('IMAGE_QUALITY_DEFAULT', 80)},
                'strip': {'value': app.config.get('IMAGE_STRIP_DEFAULT', True)},
                'colorspace': {'value': app.config.get('IMAGE_COLORSPACE_DEFAULT', 'RGB')},
                'dpi_x': {'value': app.config.get('IMAGE_DPI_DEFAULT', None)},
                'dpi_y': {'value': app.config.get('IMAGE_DPI_DEFAULT', None)},
                'record_stats': {'value': True},
                'expiry_secs': {'value': app.config.get('IMAGE_EXPIRY_TIME_DEFAULT',
                                                        60 * 60 * 24 * 7)}
            }
        ))
        log(
            'Info: Default image generation settings have been moved into a '
            'new template called \'Default\'.'
        )
    else:
        log('Skipped creation of a \'Default\' template as it already exists.')

    data_engine.save_object(Property(Property.DEFAULT_TEMPLATE, 'default'))
    log(
        'If you have any of the following settings in your local_settings.py '
        'file, they can now be deleted:\n\n'
        'IMAGE_FORMAT_DEFAULT\nIMAGE_QUALITY_DEFAULT\nIMAGE_STRIP_DEFAULT\n'
        'IMAGE_COLORSPACE_DEFAULT\nIMAGE_DPI_DEFAULT\nIMAGE_EXPIRY_TIME_DEFAULT\n'
    )
예제 #26
0
파일: views_data_api.py 프로젝트: quru/qis
 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)
예제 #27
0
파일: v2_upgrade.py 프로젝트: quru/qis
def import_templates():
    from imageserver.flask_app import app, data_engine
    from imageserver.image_attrs import ImageAttrs
    from imageserver.models import ImageTemplate
    from imageserver.template_attrs import TemplateAttrs
    from imageserver.util import filepath_filename, parse_colour

    # Find *.cfg
    num_files = 0
    num_errors = 0
    num_skipped = 0
    template_dir_path = app.config.get(
        'TEMPLATES_BASE_DIR',
        os.path.join(app.config['INSTALL_DIR'], 'templates')
    )
    cfg_files = glob.glob(os.path.join(template_dir_path, '*.cfg'))
    log('Starting image templates import')

    merge_def_settings = False
    if cfg_files:
        merge_conf = input(
            '\nQIS v2 removes the system settings for default image format, '
            'quality, DPI, strip, colorspace, and expiry time. These values '
            'now need to be defined in your image templates instead. '
            'Do you want to merge these settings into your templates now? '
            'Y/N (Y recommended)\n'
        )
        merge_def_settings = (merge_conf in ['y', 'Y'])

    for cfg_file_path in cfg_files:
        num_files += 1
        (template_name, _) = os.path.splitext(filepath_filename(cfg_file_path))
        try:
            # Read config file
            cp = configparser.RawConfigParser()
            cp.read(cfg_file_path)

            # Get image values and put them in an ImageAttrs object
            section = 'ImageAttributes'
            t_image_attrs = ImageAttrs(
                template_name,
                -1,
                _config_get(cp, cp.getint, section, 'page'),
                _config_get(cp, cp.get, section, 'format', True),
                None,
                _config_get(cp, cp.getint, section, 'width'),
                _config_get(cp, cp.getint, section, 'height'),
                _config_get(cp, cp.get, section, 'halign', True),
                _config_get(cp, cp.get, section, 'valign', True),
                _config_get(cp, cp.getfloat, section, 'angle'),
                _config_get(cp, cp.get, section, 'flip'),
                _config_get(cp, cp.getfloat, section, 'top'),
                _config_get(cp, cp.getfloat, section, 'left'),
                _config_get(cp, cp.getfloat, section, 'bottom'),
                _config_get(cp, cp.getfloat, section, 'right'),
                _config_get(cp, cp.getboolean, section, 'autocropfit'),
                _config_get(cp, cp.getboolean, section, 'autosizefit'),
                parse_colour(_config_get(cp, cp.get, section, 'fill')),
                _config_get(cp, cp.getint, section, 'quality'),
                _config_get(cp, cp.getint, section, 'sharpen'),
                _config_get(cp, cp.get, section, 'overlay', False),
                _config_get(cp, cp.getfloat, section, 'ovsize'),
                _config_get(cp, cp.get, section, 'ovpos', True),
                _config_get(cp, cp.getfloat, section, 'ovopacity'),
                _config_get(cp, cp.get, section, 'icc', True),
                _config_get(cp, cp.get, section, 'intent', True),
                _config_get(cp, cp.getboolean, section, 'bpc'),
                _config_get(cp, cp.get, section, 'colorspace', True),
                _config_get(cp, cp.getboolean, section, 'strip'),
                _config_get(cp, cp.getint, section, 'dpi'),
                None
            )
            t_image_attrs.normalise_values()

            # Get misc options
            section = 'Miscellaneous'
            t_stats = _config_get(cp, cp.getboolean, section, 'stats')

            # Get handling options and create the TemplateAttrs object
            section = 'BrowserOptions'
            t_expiry = _config_get(cp, cp.getint, section, 'expiry')
            t_attach = _config_get(cp, cp.getboolean, section, 'attach')

            # Get the template as a dict
            template_dict = {
                'expiry_secs': {'value': t_expiry},
                'attachment': {'value': t_attach},
                'record_stats': {'value': t_stats}
            }
            ia_dict = t_image_attrs.to_dict()
            template_dict.update(dict(
                (k, {'value': v}) for k, v in ia_dict.items()
                if k not in ['filename', 'template']
            ))
            # Apply the obsolete default image settings to it
            if merge_def_settings:
                if not template_dict['format']['value']:
                    template_dict['format']['value'] = app.config.get('IMAGE_FORMAT_DEFAULT')
                if not template_dict['quality']['value']:
                    template_dict['quality']['value'] = app.config.get('IMAGE_QUALITY_DEFAULT')
                if template_dict['strip']['value'] is None:
                    template_dict['strip']['value'] = app.config.get('IMAGE_STRIP_DEFAULT')
                if not template_dict['colorspace']['value']:
                    template_dict['colorspace']['value'] = app.config.get('IMAGE_COLORSPACE_DEFAULT')
                if not template_dict['dpi_x']['value']:
                    template_dict['dpi_x']['value'] = app.config.get('IMAGE_DPI_DEFAULT')
                if not template_dict['dpi_y']['value']:
                    template_dict['dpi_y']['value'] = app.config.get('IMAGE_DPI_DEFAULT')
                if template_dict['expiry_secs']['value'] is None:
                    template_dict['expiry_secs']['value'] = app.config.get('IMAGE_EXPIRY_TIME_DEFAULT', 60 * 60 * 24 * 7)
            # Record stats needs to default to True in v2.2+
            if template_dict['record_stats']['value'] is None:
                template_dict['record_stats']['value'] = True
            # Create the TemplateAttrs object
            template_attrs = TemplateAttrs(template_name, template_dict)

            # Validate
            template_attrs.validate()

            # Import template if it doesn't exist already
            existing_obj = data_engine.get_image_template(tempname=template_name)
            if existing_obj is None:
                log('Importing template \'%s\'' % template_name)
                data_engine.save_object(ImageTemplate(
                    template_name,
                    'Imported template',
                    template_attrs.get_raw_dict()
                ))
            else:
                log('Skipped template \'%s\' as it already exists' % template_name)
                num_skipped += 1

        except Exception as e:
            log('Failed to import template \'%s\' due to: %s' % (template_name, str(e)))
            num_errors += 1

    log('Template import complete, %d file(s) found, '
        '%d errors, %d skipped.' % (num_files, num_errors, num_skipped))

    if not merge_def_settings:
        log('Warning: You chose not to merge your v1 default image settings '
            'into your v2 templates. Since the default image settings are '
            'now ignored, some images may be rendered differently.')

    deleted = False
    if num_errors == 0 and os.path.exists(template_dir_path):
        conf = input('\nThe old template files are no longer required. ' +
                         'Do you want to remove them now? Y/N\n')
        if conf in ['y', 'Y']:
            log('Removing directory ' + template_dir_path)
            try:
                shutil.rmtree(template_dir_path)
                log('Old templates removed OK')
                deleted = True
            except Exception as e:
                log('Warning: failed to delete directory: ' + str(e))

    if num_files > 0 and not deleted:
        log('Info: Old template files remain in ' + template_dir_path)