def put(self, oid): """Update a single item in the DB. :arg self: The class of the object to be updated :arg integer oid: the ID of the object in the DB :returns: An HTTP status code based on the output of the action. More info about HTTP status codes for this action `here <http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6>`_. """ try: self.valid_args() cls_name = self.__class__.__name__ repo = repos[cls_name]['repo'] query_func = repos[cls_name]['get'] existing = getattr(repo, query_func)(oid) if existing is None: raise NotFound ensure_authorized_to('update', existing) data = self._file_upload(request) inst = self._update_instance(existing, repo, repos, new_upload=data) self.refresh_cache(cls_name, oid) return Response(json.dumps(inst.dictize()), 200, mimetype='application/json') except Exception as e: return error.format_exception( e, target=self.__class__.__name__.lower(), action='PUT')
def categories(): """List Categories.""" try: if request.method == 'GET': ensure_authorized_to('read', Category) form = CategoryForm() if request.method == 'POST': ensure_authorized_to('create', Category) form = CategoryForm(request.form) del form.id if form.validate(): slug = form.name.data.lower().replace(" ", "") category = Category(name=form.name.data, short_name=slug, description=form.description.data) project_repo.save_category(category) cached_cat.reset() msg = gettext("Category added") flash(msg, 'success') else: flash(gettext('Please correct the errors'), 'error') categories = cached_cat.get_all() n_projects_per_category = dict() for c in categories: n_projects_per_category[c.short_name] = \ cached_projects.n_count(c.short_name) return render_template('admin/categories.html', title=gettext('Categories'), categories=categories, n_projects_per_category=n_projects_per_category, form=form) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def new_announcement(): """Create new announcement.""" def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Write a new post"), form=form) return handle_content_type(response) form = AnnouncementForm() del form.id # project_sanitized, owner_sanitized = sanitize_project_owner(project, owner, current_user) if request.method != 'POST': ensure_authorized_to('create', Announcement()) return respond() if not form.validate(): flash(gettext('Please correct the errors'), 'error') return respond() announcement = Announcement(title=form.title.data, body=form.body.data, published=form.published.data, media_url=form.media_url.data, user_id=current_user.id) ensure_authorized_to('create', announcement) announcement_repo.save(announcement) msg_1 = gettext('Annnouncement created!') markup = Markup('<i class="icon-ok"></i> {}') flash(markup.format(msg_1), 'success') return redirect_content_type(url_for('admin.announcement'))
def del_category(id): """Delete a category.""" try: category = project_repo.get_category(id) if category: if len(cached_cat.get_all()) > 1: ensure_authorized_to('delete', category) if request.method == 'GET': return render_template('admin/del_category.html', title=gettext('Delete Category'), category=category) if request.method == 'POST': project_repo.delete_category(category) msg = gettext("Category deleted") flash(msg, 'success') cached_cat.reset() return redirect(url_for(".categories")) else: msg = gettext('Sorry, it is not possible to delete the only' ' available category. You can modify it, ' ' click the edit button') flash(msg, 'warning') return redirect(url_for('.categories')) else: abort(404) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def _create_instance_from_request(self, data): data = self.hateoas.remove_links(data) inst = self.__class__(**data) self._update_object(inst) ensure_authorized_to('create', inst) self._validate_instance(inst) return inst
def _create_json_response(self, query_result, oid): if len(query_result) == 1 and query_result[0] is None: raise abort(404) items = [] for result in query_result: # This is for n_favs orderby case if not isinstance(result, DomainObject): if 'n_favs' in result.keys(): result = result[0] try: if (result.__class__ != self.__class__): (item, headline, rank) = result else: item = result headline = None rank = None datum = self._create_dict_from_model(item) if headline: datum['headline'] = headline if rank: datum['rank'] = rank ensure_authorized_to('read', item) items.append(datum) except (Forbidden, Unauthorized): # Remove last added item, as it is 401 or 403 if len(items) > 0: items.pop() except Exception: # pragma: no cover raise if oid is not None: ensure_authorized_to('read', query_result[0]) items = items[0] return json.dumps(items)
def _file_delete(self, request, obj): """Delete file object.""" cls_name = self.__class__.__name__.lower() if cls_name in self.allowed_classes_upload: keys = obj.info.keys() if 'file_name' in keys and 'container' in keys: ensure_authorized_to('delete', obj) uploader.delete_file(obj.info['file_name'], obj.info['container'])
def _create_instance_from_request(self, data): data = self.hateoas.remove_links(data) inst = self.__class__(**data) self._update_object(inst) instance_name = inst.__class__.__name__ if instance_name != 'UserScore': ensure_authorized_to('create', inst) self._validate_instance(inst) return inst
def update_profile(name): """ Update user's profile. Returns Jinja2 template. """ user = user_repo.get_by_name(name) if not user: return abort(404) ensure_authorized_to('update', user) if not user.admin : if is_amnesty_sso_enable(): return redirect(amnesty_url_for('/<name>/')) show_passwd_form = True if user.twitter_user_id or user.google_user_id or user.facebook_user_id: show_passwd_form = False usr = cached_users.get_user_summary(name) # Extend the values user.rank = usr.get('rank') user.score = usr.get('score') # Creation of forms update_form = UpdateProfileForm(obj=user) update_form.set_locales(current_app.config['LOCALES']) avatar_form = AvatarUploadForm() password_form = ChangePasswordForm() if request.method == 'POST': # Update user avatar if request.form.get('btn') == 'Upload': _handle_avatar_update(user, avatar_form) # Update user profile elif request.form.get('btn') == 'Profile': _handle_profile_update(user, update_form) # Update user password elif request.form.get('btn') == 'Password': _handle_password_update(user, password_form) # Update user external services elif request.form.get('btn') == 'External': _handle_external_services_update(user, update_form) # Otherwise return 415 else: return abort(415) return redirect(url_for('.update_profile', name=user.name)) title_msg = "Update your profile: %s" % user.fullname return render_template('/account/update.html', form=update_form, upload_form=avatar_form, password_form=password_form, title=title_msg, show_passwd_form=show_passwd_form)
def delete_announcement(id): announcement = announcement_repo.get_by(id=id) if announcement is None: raise abort(404) ensure_authorized_to('delete', announcement) announcement_repo.delete(announcement) msg_1 = gettext('Announcement deleted!') markup = Markup('<i class="icon-ok"></i> {}') flash(markup.format(msg_1), 'success') return redirect_content_type(url_for('admin.announcement'))
def _delete_instance(self, oid): repo = repos[self.__class__.__name__]['repo'] query_func = repos[self.__class__.__name__]['get'] inst = getattr(repo, query_func)(oid) if inst is None: raise NotFound ensure_authorized_to('delete', inst) self._log_changes(inst, None) delete_func = repos[self.__class__.__name__]['delete'] getattr(repo, delete_func)(inst) return inst
def set_gravatar(name): """Set gravatar for a user.""" user = user_repo.get_by(name=name) if not user: abort(404) ensure_authorized_to('update', user) gravatar.set(user) flash(gettext('Your avatar has been updated! It may \ take some minutes to refresh...'), 'success') return redirect(url_for('account.update_profile', name=user.name))
def get(self, token): try: ensure_authorized_to('read', self._resource_name, token=token) user_tokens = self._get_all_tokens() if token: response = self._get_token(token, user_tokens) else: response = user_tokens return Response(json.dumps(response), mimetype='application/json') except Exception as e: return error.format_exception( e, target=self._resource_name, action='GET')
def sync(short_name): """Sync a project with a GitHub repo.""" project = project_repo.get_by_shortname(short_name) if not project: # pragma: no cover abort(404) ensure_authorized_to('update', project) form = GitHubURLForm(request.form) if request.method == 'POST' and form.validate(): github_url = form.github_url.data return redirect(url_for('.import_repo', github_url=github_url, short_name=project.short_name)) elif request.method == 'POST': # pragma: no cover flash(gettext('Please correct the errors'), 'error') return render_template('projects/github/sync.html', form=form, project=project)
def add_admin(user_id=None): """Add admin flag for user_id.""" try: if user_id: user = user_repo.get(user_id) if user: ensure_authorized_to('update', user) user.admin = True user_repo.update(user) return redirect(url_for(".users")) else: msg = "User not found" return format_error(msg, 404) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def reset_api_key(name): """ Reset API-KEY for user. Returns a Jinja2 template. """ user = user_repo.get_by_name(name) if not user: return abort(404) ensure_authorized_to('update', user) user.api_key = model.make_uuid() user_repo.update(user) cached_users.delete_user_summary(user.name) msg = gettext('New API-KEY generated') flash(msg, 'success') return redirect(url_for('account.profile', name=name))
def _create_json_response(self, query_result, oid): if len(query_result) == 1 and query_result[0] is None: raise abort(404) items = [] for item in query_result: try: items.append(self._create_dict_from_model(item)) ensure_authorized_to('read', item) except (Forbidden, Unauthorized): # Remove last added item, as it is 401 or 403 items.pop() except Exception: # pragma: no cover raise if oid is not None: ensure_authorized_to('read', query_result[0]) items = items[0] return json.dumps(items)
def featured(project_id=None): """List featured projects of PYBOSSA.""" try: if request.method == 'GET': categories = cached_cat.get_all() projects = {} for c in categories: n_projects = cached_projects.n_count(category=c.short_name) projects[c.short_name] = cached_projects.get( category=c.short_name, page=1, per_page=n_projects) response = dict(template = '/admin/projects.html', projects=projects, categories=categories, form=dict(csrf=generate_csrf())) return handle_content_type(response) else: project = project_repo.get(project_id) if project: ensure_authorized_to('update', project) if request.method == 'POST': if project.featured is True: msg = "Project.id %s already featured" % project_id return format_error(msg, 415) cached_projects.reset() project.featured = True project_repo.update(project) return json.dumps(project.dictize()) if request.method == 'DELETE': if project.featured is False: msg = 'Project.id %s is not featured' % project_id return format_error(msg, 415) cached_projects.reset() project.featured = False project_repo.update(project) return json.dumps(project.dictize()) else: msg = 'Project.id %s not found' % project_id return format_error(msg, 404) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def start_export(name): """ Starts a export of all user data according to EU GDPR Data will be available on GET /export after it is processed """ user = user_repo.get_by_name(name) if not user: return abort(404) if user.id != current_user.id: return abort(403) ensure_authorized_to('update', user) export_queue.enqueue(export_userdata, user_id=user.id) msg = gettext('GDPR export started') flash(msg, 'success') return redirect_content_type(url_for('account.profile', name=name))
def _file_upload(self, data): """Method that must be overriden by the class to allow file uploads for only a few classes.""" cls_name = self.__class__.__name__.lower() content_type = 'multipart/form-data' if (content_type in request.headers.get('Content-Type') and cls_name in self.allowed_classes_upload): tmp = dict() for key in request.form.keys(): tmp[key] = request.form[key] if isinstance(self, announcement.Announcement): # don't check project id for announcements ensure_authorized_to('create', self) upload_method = current_app.config.get('UPLOAD_METHOD') if request.files.get('file') is None: raise AttributeError _file = request.files['file'] container = "user_%s" % current_user.id else: ensure_authorized_to('create', self.__class__, project_id=tmp['project_id']) project = project_repo.get(tmp['project_id']) upload_method = current_app.config.get('UPLOAD_METHOD') if request.files.get('file') is None: raise AttributeError _file = request.files['file'] if current_user.admin: container = "user_%s" % project.owner.id else: container = "user_%s" % current_user.id uploader.upload_file(_file, container=container) file_url = get_avatar_url(upload_method, _file.filename, container) tmp['media_url'] = file_url if tmp.get('info') is None: tmp['info'] = dict() tmp['info']['container'] = container tmp['info']['file_name'] = _file.filename return tmp else: return None
def del_admin(user_id=None): """Del admin flag for user_id.""" try: if user_id: user = user_repo.get(user_id) if user: ensure_authorized_to('update', user) user.admin = False user_repo.update(user) return redirect(url_for('.users')) else: msg = "User.id not found" return format_error(msg, 404) else: # pragma: no cover msg = "User.id is missing for method del_admin" return format_error(msg, 415) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def update_category(id): """Update a category.""" try: category = project_repo.get_category(id) if category: ensure_authorized_to('update', category) form = CategoryForm(obj=category) form.populate_obj(category) if request.method == 'GET': response = dict(template='admin/update_category.html', title=gettext('Update Category'), category=category, form=form) return handle_content_type(response) if request.method == 'POST': form = CategoryForm(request.body) if form.validate(): slug = form.name.data.lower().replace(" ", "") new_category = Category(id=form.id.data, name=form.name.data, short_name=slug) project_repo.update_category(new_category) cached_cat.reset() msg = gettext("Category updated") flash(msg, 'success') return redirect_content_type(url_for(".categories")) else: msg = gettext("Please correct the errors") flash(msg, 'success') response = dict(template='admin/update_category.html', title=gettext('Update Category'), category=category, form=form) return handle_content_type(response) else: abort(404) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def _update_instance(self, oid): repo = repos[self.__class__.__name__]['repo'] query_func = repos[self.__class__.__name__]['get'] existing = getattr(repo, query_func)(oid) if existing is None: raise NotFound ensure_authorized_to('update', existing) data = json.loads(request.data) # Remove hateoas links data = self.hateoas.remove_links(data) # may be missing the id as we allow partial updates data['id'] = oid self.__class__(**data) old = self.__class__(**existing.dictize()) for key in data: setattr(existing, key, data[key]) update_func = repos[self.__class__.__name__]['update'] self._validate_instance(existing) getattr(repo, update_func)(existing) self._log_changes(old, existing) return existing
def test_auth_owner_can_update_results(self): """Test auth owner can update results of a specific project""" result = self.create_result() result.info = dict(new='value') assert ensure_authorized_to('update', result) updated_result = self.result_repo.get_by(id=result.id) err_msg = "The result has not been updated" assert updated_result.info['new'] == 'value', err_msg
def get(self, oid): """Get an object. Returns an item from the DB with the request.data JSON object or all the items if oid == None :arg self: The class of the object to be retrieved :arg integer oid: the ID of the object in the DB :returns: The JSON item/s stored in the DB """ try: ensure_authorized_to('read', self.__class__) query = self._db_query(oid) json_response = self._create_json_response(query, oid) return Response(json_response, mimetype='application/json') except Exception as e: return error.format_exception( e, target=self.__class__.__name__.lower(), action='GET')
def reset_api_key(name): """ Reset API-KEY for user. Returns a Jinja2 template. """ if request.method == 'POST': user = user_repo.get_by_name(name) if not user: return abort(404) ensure_authorized_to('update', user) user.api_key = model.make_uuid() user_repo.update(user) cached_users.delete_user_summary(user.name) msg = gettext('New API-KEY generated') flash(msg, 'success') return redirect_content_type(url_for('account.profile', name=name)) else: csrf = dict(form=dict(csrf=generate_csrf())) return jsonify(csrf)
def featured(project_id=None): """List featured projects of PyBossa.""" try: if request.method == 'GET': categories = cached_cat.get_all() projects = {} for c in categories: n_projects = cached_projects.n_count(category=c.short_name) projects[c.short_name] = cached_projects.get( category=c.short_name, page=1, per_page=n_projects) return render_template('/admin/projects.html', projects=projects, categories=categories) else: project = project_repo.get(project_id) if project: ensure_authorized_to('update', project) if request.method == 'POST': if project.featured is True: msg = "Project.id %s already featured" % project_id return format_error(msg, 415) cached_projects.reset() project.featured = True project_repo.update(project) return json.dumps(project.dictize()) if request.method == 'DELETE': if project.featured is False: msg = 'Project.id %s is not featured' % project_id return format_error(msg, 415) cached_projects.reset() project.featured = False project_repo.update(project) return json.dumps(project.dictize()) else: msg = 'Project.id %s not found' % project_id return format_error(msg, 404) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def reset_api_key(name): """ Reset API-KEY for user. Returns a Jinja2 template. """ user = user_repo.get_by_name(name) if not user: return abort(404) ensure_authorized_to('update', user) if not user.admin : if is_amnesty_sso_enable(): return redirect(amnesty_url_for('/<name>/')) user.api_key = model.make_uuid() user_repo.update(user) cached_users.delete_user_summary(user.name) msg = gettext('New API-KEY generated') flash(msg, 'success') return redirect(url_for('account.profile', name=name))
def get(self, oid): """Get all completed tasks. Need admin access""" try: ensure_authorized_to('read', self.__class__) # check admin access if 'api_key' in request.args.keys(): apikey = request.args['api_key'] user = user_repo.get_by(api_key=apikey) if not user or user.admin is False: raise BadRequest("Insufficient privilege to the request") else: raise BadRequest("Insufficient privilege to the request") # set filter from args # add 'state'='completed' if missing filters = {} filters['state'] = 'completed' for k in request.args.keys(): if k not in ['limit', 'offset', 'api_key']: # 'exported' column belongs to Task class # ignore it for attr check in TaskRun class # but add it to filter so that its checked # against Task class in filter_completed_task_runs_by if k not in ['exported']: # Raise an error if the k arg is not a column getattr(self.__class__, k) filters[k] = request.args[k] # set limit, offset limit, offset = self._set_limit_and_offset() # query database to obtain the requested data query = task_repo.filter_tasks_by(limit=limit, offset=offset, **filters) json_response = self._create_json_response(query, oid) return Response(json_response, mimetype='application/json') except Exception as e: return error.format_exception( e, target=self.__class__.__name__.lower(), action='GET')
def update_announcement(id): announcement = announcement_repo.get_by(id=id) if announcement is None: raise abort(404) def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Edit a post"), levelOptions=json.dumps( current_app.config['ANNOUNCEMENT_LEVEL_OPTIONS']), form=form) return handle_content_type(response) form = AnnouncementForm() if request.method != 'POST': ensure_authorized_to('update', announcement) form = AnnouncementForm(obj=announcement) return respond() if not form.validate(): flash(gettext('Please correct the errors'), 'error') return respond() ensure_authorized_to('update', announcement) announcement = Announcement(id=form.id.data, title=form.title.data, body=form.body.data, info=json.loads(form.info.data), published=form.published.data, media_url=form.media_url.data, user_id=current_user.id) announcement_repo.update(announcement) msg_1 = gettext('Announcement updated!') markup = Markup('<i class="icon-ok"></i> {}') flash(markup.format(msg_1), 'success') return redirect_content_type(url_for('admin.announcement'))
def update_category(id): """Update a category.""" try: category = project_repo.get_category(id) if category: ensure_authorized_to('update', category) form = CategoryForm(obj=category) form.populate_obj(category) if request.method == 'GET': return render_template('admin/update_category.html', title=gettext('Update Category'), category=category, form=form) if request.method == 'POST': form = CategoryForm(request.form) if form.validate(): slug = form.name.data.lower().replace(" ", "") new_category = Category(id=form.id.data, name=form.name.data, short_name=slug) project_repo.update_category(new_category) cached_cat.reset() msg = gettext("Category updated") flash(msg, 'success') return redirect(url_for(".categories")) else: msg = gettext("Please correct the errors") flash(msg, 'success') return render_template('admin/update_category.html', title=gettext('Update Category'), category=category, form=form) else: abort(404) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def _create_instance_from_request(self, data): # Remove facebook_user_id key and retrieve the respective user fb_user = None if "facebook_user_id" in data.keys(): fb_api = UserFbAPI() fb_user_id = data["facebook_user_id"] fb_user = fb_api.get_user_by_fb_id(fb_user_id) del data["facebook_user_id"] data = self.hateoas.remove_links(data) inst = self.__class__(**data) if fb_user == None: self._update_object(inst) else: inst.user_id = fb_user.id getattr(require, self.__class__.__name__.lower()).create(inst) self._update_object(inst) ensure_authorized_to('create', inst) self._validate_instance(inst) return inst
def _create_json_response(self, query_result, oid): if len(query_result) == 1 and query_result[0] is None: raise abort(404) items = [] for result in query_result: # This is for n_favs orderby case if not isinstance(result, DomainObject): if 'n_favs' in result.keys(): result = result[0] try: if (result.__class__ != self.__class__): (item, headline, rank) = result else: item = result headline = None rank = None if not self._verify_auth(item): continue datum = self._create_dict_from_model(item) if headline: datum['headline'] = headline if rank: datum['rank'] = rank ensure_authorized_to('read', item) items.append(datum) except (Forbidden, Unauthorized): # Remove last added item, as it is 401 or 403 if len(items) > 0: items.pop() except Exception: # pragma: no cover raise if oid is not None: if not items: raise Forbidden('Forbidden') ensure_authorized_to('read', query_result[0]) self._sign_item(items[0]) items = items[0] return json.dumps(items)
def add_admin(user_id=None): """Add admin flag for user_id.""" try: if user_id: user = user_repo.get(user_id) if not user: return format_error('User not found', 404) if not user.enabled: markup = Markup('<strong>{}</strong> {} <strong>{}</strong>') flash(markup.format(gettext('User account '), user.fullname, gettext(' is disabled'))) return redirect_content_type(url_for(".users")) if not can_have_super_user_access(user): markup = Markup('<strong>{} {}</strong> {} {}') flash(markup.format(gettext('Denied admin privileges to'), user.fullname, user.email_addr, 'disqualify for admin access.')) return redirect_content_type(url_for(".users")) ensure_authorized_to('update', user) admins_emails = [u.email_addr for u in user_repo.filter_by(admin=True)] admins_msg = generate_notification_email_for_admins(user, admins_emails, "Admin") mail_queue.enqueue(send_mail, admins_msg) user.admin = True user_repo.update(user) msg = generate_invitation_email_for_admins_subadmins(user, "Admin") mail_queue.enqueue(send_mail, msg) return redirect_content_type(url_for(".users")) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def categories(): """List Categories.""" try: if request.method == 'GET': ensure_authorized_to('read', Category) form = CategoryForm() if request.method == 'POST': ensure_authorized_to('create', Category) form = CategoryForm(request.body) del form.id if form.validate(): slug = form.name.data.lower().replace(" ", "") category = Category(name=form.name.data, short_name=slug, description=form.description.data) project_repo.save_category(category) cached_cat.reset() msg = gettext("Category added") flash(msg, 'success') else: flash(gettext('Please correct the errors'), 'error') categories = cached_cat.get_all() categories = sorted(categories, key=lambda category: category.name) n_projects_per_category = dict() for c in categories: n_projects_per_category[c.short_name] = \ cached_projects.n_count(c.short_name) response = dict(template='admin/categories.html', title=gettext('Categories'), categories=categories, n_projects_per_category=n_projects_per_category, form=form) return handle_content_type(response) except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def del_category(id): """Delete a category.""" try: category = project_repo.get_category(id) if category: if len(cached_cat.get_all()) > 1: ensure_authorized_to('delete', category) if request.method == 'GET': response = dict(template='admin/del_category.html', title=gettext('Delete Category'), category=category, form=dict(csrf=generate_csrf())) return handle_content_type(response) if request.method == 'POST': project_repo.delete_category(category) msg = gettext("Category deleted") flash(msg, 'success') cached_cat.reset() return redirect_content_type(url_for(".categories")) else: msg = gettext('Sorry, it is not possible to delete the only' ' available category. You can modify it, ' ' click the edit button') flash(msg, 'warning') return redirect_content_type(url_for('.categories')) else: abort(404) except IntegrityError: msg = gettext('Sorry, it is not possible to delete a category' ' if there are projects assigned to it.') flash(msg, 'error') return redirect_content_type(url_for('.categories')) except HTTPException: raise except Exception as e: # pragma: no cover current_app.logger.error(e) return abort(500)
def new_announcement(): """Create new announcement.""" def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Write a new post"), levelOptions=json.dumps( current_app.config['ANNOUNCEMENT_LEVEL_OPTIONS']), form=form) return handle_content_type(response) form = AnnouncementForm() del form.id # project_sanitized, owner_sanitized = sanitize_project_owner(project, owner, current_user) if request.method != 'POST': ensure_authorized_to('create', Announcement()) return respond() if not form.validate(): flash(gettext('Please correct the errors'), 'error') return respond() announcement = Announcement(title=form.title.data, body=form.body.data, info=json.loads(form.info.data), published=form.published.data, media_url=form.media_url.data, user_id=current_user.id) ensure_authorized_to('create', announcement) announcement_repo.save(announcement) msg_1 = gettext('Annnouncement created!') markup = Markup('<i class="icon-ok"></i> {}') flash(markup.format(msg_1), 'success') return redirect_content_type(url_for('admin.announcement'))
def update_announcement(id): announcement = announcement_repo.get_by(id=id) if announcement is None: raise abort(404) def respond(): response = dict(template='admin/new_announcement.html', title=gettext("Edit a post"), form=form) return handle_content_type(response) form = AnnouncementForm() if request.method != 'POST': ensure_authorized_to('update', announcement) form = AnnouncementForm(obj=announcement) return respond() if not form.validate(): flash(gettext('Please correct the errors'), 'error') return respond() ensure_authorized_to('update', announcement) announcement = Announcement(id=form.id.data, title=form.title.data, body=form.body.data, published=form.published.data, media_url=form.media_url.data, user_id=current_user.id) announcement_repo.update(announcement) msg_1 = gettext('Announcement updated!') markup = Markup('<i class="icon-ok"></i> {}') flash(markup.format(msg_1), 'success') return redirect_content_type(url_for('admin.announcement'))
def visualize(short_name, task_id): """Return a file with all the TaskRuns for a given Task""" # Check if it a supported geotagx project whose schema we know if 'GEOTAGX_SUPPORTED_PROJECTS_SCHEMA' in current_app.config.keys() \ and short_name in current_app.config['GEOTAGX_SUPPORTED_PROJECTS_SCHEMA'].keys(): # Check if the project exists (project, owner, n_tasks, n_task_runs, overall_progress, last_activity) = projects_view.project_by_shortname(short_name) ensure_authorized_to('read', project) redirect_to_password = projects_view._check_if_redirect_to_password(project) if redirect_to_password: return redirect_to_password # Check if the task belongs to the project and exists task = task_repo.get_task_by(project_id=project.id, id=task_id) if task: taskruns = task_repo.filter_task_runs_by(task_id=task_id, project_id=project.id) results = [tr.dictize() for tr in taskruns] return render_template('geotagx/projects/task_runs_visualize.html', project=project, owner=owner, n_tasks=n_tasks, n_task_runs=n_task_runs, overall_progress=overall_progress, last_activity=last_activity, n_completed_tasks=cached_projects.n_completed_tasks(project.id), n_volunteers=cached_projects.n_volunteers(project.id), task_info = task.info, task_runs_json = results, geotagx_project_template_schema = \ current_app.config['GEOTAGX_SUPPORTED_PROJECTS_SCHEMA'][short_name]) else: return abort(404) else: return abort(404)
def users(user_id=None): """Manage users of PyBossa.""" form = SearchForm(request.form) users = [user for user in user_repo.filter_by(admin=True) if user.id != current_user.id] if request.method == 'POST' and form.user.data: query = form.user.data found = [user for user in user_repo.search_by_name(query) if user.id != current_user.id] [ensure_authorized_to('update', found_user) for found_user in found] if not found: flash("<strong>Ooops!</strong> We didn't find a user " "matching your query: <strong>%s</strong>" % form.user.data) return render_template('/admin/users.html', found=found, users=users, title=gettext("Manage Admin Users"), form=form) return render_template('/admin/users.html', found=[], users=users, title=gettext("Manage Admin Users"), form=form)
def users(user_id=None): """Manage users of PYBOSSA.""" form = SearchForm(request.body) users = [ user for user in user_repo.filter_by(admin=True) if user.id != current_user.id ] if request.method == 'POST' and form.user.data: query = form.user.data filters = {'admin': True, 'enabled': True} found = [ user for user in user_repo.search_by_name_orfilters(query, **filters) if user.id != current_user.id ] [ensure_authorized_to('update', found_user) for found_user in found] if not found: markup = Markup('<strong>{}</strong> {} <strong>{}</strong>') flash( markup.format( gettext("Ooops!"), gettext( "We didn't find any enabled user matching your query:" ), form.user.data)) response = dict(template='/admin/users.html', found=found, users=users, title=gettext("Manage Admin Users"), form=form) return handle_content_type(response) response = dict(template='/admin/users.html', found=[], users=users, title=gettext("Manage Admin Users"), form=form) return handle_content_type(response)
def subadminusers(): """Manage subadminusers of PyBossa.""" form = SearchForm(request.form) users = [ user for user in user_repo.filter_by(subadmin=True) if user.id != current_user.id ] if request.method == 'POST' and form.user.data: query = form.user.data filters = {'subadmin': True, 'enabled': True} found = [ user for user in user_repo.search_by_name_orfilters(query, **filters) if user.id != current_user.id ] [ensure_authorized_to('update', found_user) for found_user in found] if not found: markup = Markup('<strong>{}</strong> {} <strong>{}</strong>') flash( markup.format( gettext('Ooops!'), gettext( "We didn't find any enabled user matching your query:" ), form.user.data)) return render_template('/admin/subadminusers.html', found=found, users=users, title=gettext("Manage Subadmin Users"), form=form) return render_template('/admin/subadminusers.html', found=[], users=users, title=gettext("Manage Subadmin Users"), form=form)
def test_admin_user_can_save_results(self): """Test admin users cannot save results of a specific project""" result = Result() assert ensure_authorized_to('create', result)
def update_profile(name): """ Update user's profile. Returns Jinja2 template. """ user = user_repo.get_by_name(name) if not user: return abort(404) if current_user.name != name: return abort(403) ensure_authorized_to('update', user) show_passwd_form = True if user.twitter_user_id or user.google_user_id or user.facebook_user_id: show_passwd_form = False usr = cached_users.get_user_summary(name) # Extend the values user.rank = usr.get('rank') user.score = usr.get('score') btn = request.body.get('btn', 'None').capitalize() if btn != 'Profile': update_form = UpdateProfileForm(formdata=None, obj=user) else: update_form = UpdateProfileForm(obj=user) update_form.set_locales(current_app.config['LOCALES']) avatar_form = AvatarUploadForm() password_form = ChangePasswordForm() title_msg = "Update your profile: %s" % user.fullname if request.method == 'POST': # Update user avatar succeed = False btn = request.body.get('btn', 'None').capitalize() if btn == 'Upload': succeed = _handle_avatar_update(user, avatar_form) # Update user profile elif btn == 'Profile': succeed = _handle_profile_update(user, update_form) # Update user password elif btn == 'Password': succeed = _handle_password_update(user, password_form) # Update user external services elif btn == 'External': succeed = _handle_external_services_update(user, update_form) # Otherwise return 415 else: return abort(415) if succeed: cached_users.delete_user_summary(user.name) return redirect_content_type(url_for('.update_profile', name=user.name), status=SUCCESS) else: data = dict(template='/account/update.html', form=update_form, upload_form=avatar_form, password_form=password_form, title=title_msg, show_passwd_form=show_passwd_form) return handle_content_type(data) data = dict(template='/account/update.html', form=update_form, upload_form=avatar_form, password_form=password_form, title=title_msg, show_passwd_form=show_passwd_form) return handle_content_type(data)
def update_volume(short_name, volume_id): """Update a volume.""" category = project_repo.get_category_by(short_name=short_name) if not category: # pragma: no cover abort(404) ensure_authorized_to('update', category) volumes = category.info.get('volumes', []) try: volume = [v for v in volumes if v['id'] == volume_id][0] except IndexError: abort(404) form = VolumeForm(**volume) form.category_id.data = category.id all_importers = importer.get_all_importer_names() form.importer.choices = [(name, name) for name in all_importers] upload_form = AvatarUploadForm() import_form = GenericBulkTaskImportForm()(volume['importer'], **volume.get('data', {})) def update(): """Helper function to update the current volume.""" try: idx = [ i for i, _vol in enumerate(volumes) if _vol['id'] == volume_id ][0] except IndexError: # pragma: no cover abort(404) volumes[idx] = volume category.info['volumes'] = volumes project_repo.update_category(category) cat_projects = project_repo.filter_by(category_id=category.id) has_projects = len( [p for p in cat_projects if p.info.get('volume_id') == volume_id]) > 0 if request.method == 'POST': # Process task import form if (request.form.get('btn') == 'Import' or request.body.get('btn') == 'Import'): import_form = GenericBulkTaskImportForm()(volume['importer'], request.body) if import_form.validate(): if has_projects: flash('Update failed as projects have already been built', 'error') else: volume['data'] = import_form.get_import_data() import_data = import_form.get_import_data() try: importer.count_tasks_to_import(**import_data) update() flash('Volume updated', 'success') except BulkImportException as err: flash(err.message, 'error') else: flash('Please correct the errors', 'error') # Process volume details form elif request.form.get('btn') != 'Upload': form = VolumeForm(request.body) all_importers = importer.get_all_importer_names() form.importer.choices = [(name, name) for name in all_importers] if form.validate(): if has_projects: flash('Update failed as projects have already been built', 'error') else: volume['name'] = form.name.data volume['short_name'] = form.short_name.data volume['importer'] = form.importer.data update() flash('Volume updated', 'success') else: flash('Please correct the errors', 'error') # Process thumbnail upload form else: if upload_form.validate_on_submit(): _file = request.files['avatar'] coordinates = (upload_form.x1.data, upload_form.y1.data, upload_form.x2.data, upload_form.y2.data) suffix = time.time() _file.filename = "volume_{0}_{1}.png".format( volume['id'], suffix) container = "category_{}".format(category.id) uploader.upload_file(_file, container=container, coordinates=coordinates) # Delete previous thumbnail from storage if volume.get('thumbnail'): uploader.delete_file(volume['thumbnail'], container) volume['thumbnail'] = _file.filename volume['container'] = container upload_method = current_app.config.get('UPLOAD_METHOD') thumbnail_url = get_avatar_url(upload_method, _file.filename, container) volume['thumbnail_url'] = thumbnail_url update() project_repo.save_category(category) flash('Thumbnail updated', 'success') url = url_for('.get_volumes', short_name=category.short_name) return redirect_content_type(url) else: flash('You must provide a file', 'error') response = dict(form=form, all_importers=all_importers, upload_form=upload_form, import_form=import_form, volume=volume, has_projects=has_projects) return handle_content_type(response)
def test_admin_user_can_read_result(self): """Test admin users can read results""" result = self.create_result() assert ensure_authorized_to('read', result)