def new(self, **kw): require_access(c.app, 'write') self.rate_limit(BM.BlogPost, 'Create/edit', c.app.config.url()) post = dict( state='published') c.form = W.new_post_form return dict(post=post)
def register(self, project_unixname=None, project_description=None, project_name=None, neighborhood=None, private_project=None, tools=None, **kw): require_access(self.neighborhood, 'register') if private_project: require_access(self.neighborhood, 'admin') neighborhood = M.Neighborhood.query.get(name=neighborhood) project_description = h.really_unicode(project_description or '').encode('utf-8') project_name = h.really_unicode(project_name or '').encode('utf-8') project_unixname = h.really_unicode(project_unixname or '').encode('utf-8').lower() try: c.project = neighborhood.register_project(project_unixname, project_name=project_name, private_project=private_project) except exceptions.ProjectOverlimitError: flash("You have exceeded the maximum number of projects you are allowed to create", 'error') redirect('add_project') except exceptions.ProjectRatelimitError: flash("Project creation rate limit exceeded. Please try again later.", 'error') redirect('add_project') if project_description: c.project.short_description = project_description offset = c.project.next_mount_point(include_hidden=True) if tools and not neighborhood.project_template: for i, tool in enumerate(tools): c.project.install_app(tool, ordinal=i + offset) flash('Welcome to the SourceForge Project System! ' 'To get started, fill out some information about your project.') redirect(c.project.script_name + 'admin/overview')
def add_trove_js(self, type, new_trove, **kw): require_access(c.project, 'update') trove_obj, error_msg = self._add_trove(type, new_trove) return dict( trove_full_path=trove_obj.fullpath, trove_cat_id=trove_obj.trove_cat_id, error_msg=error_msg)
def delete_item(self, activity_id, **kwargs): require_access(c.project.neighborhood, 'admin') activity = Activity.query.get(_id=ObjectId(activity_id)) if not activity: raise exc.HTTPGone # find other copies of this activity on other user/projects timelines # but only within a small time window, so we can do efficient searching activity_ts = activity._id.generation_time time_window = timedelta(hours=1) all_copies = Activity.query.find({ '_id': { '$gt': ObjectId.from_datetime(activity_ts - time_window), '$lt': ObjectId.from_datetime(activity_ts + time_window), }, 'obj': activity.obj, 'target': activity.target, 'actor': activity.actor, 'verb': activity.verb, 'tags': activity.tags, }).all() log.info('Deleting %s copies of activity record: %s %s %s', len(all_copies), activity.actor.activity_url, activity.verb, activity.obj.activity_url) for activity in all_copies: activity.query.delete() return {'success': True}
def moderate(self, **kw): require_access(self.post.thread, 'moderate') if self.thread.discussion.deleted and not has_access(c.app, 'configure')(): redirect(self.thread.discussion.url() + 'deleted') tasks.calc_thread_stats.post(self.post.thread._id) tasks.calc_forum_stats(self.post.discussion.shortname) super(ForumPostController, self).moderate(**kw)
def add_trove(self, type, new_trove, **kw): require_access(c.project, 'update') trove_obj, error_msg = self._add_trove(type, new_trove) M.AuditLog.log('add trove %s: %s', type, trove_obj.fullpath) if error_msg: flash(error_msg,'error') redirect('trove')
def index(self, **kw): if request.method == "POST": return self._update_post(**kw) else: if self.post.state == "draft": require_access(self.post, "write") return self.post.__json__(posts_limit=10)
def index(self, **kw): if request.method == 'POST': return self._update_post(**kw) else: if self.post.state == 'draft': require_access(self.post, 'write') return self.post.__json__(posts_limit=10)
def add_trove(self, type, new_trove, **kw): require_access(c.project, "update") trove_obj, error_msg = self._add_trove(type, new_trove) M.AuditLog.log("add trove %s: %s", type, trove_obj.fullpath) if error_msg: flash(error_msg, "error") redirect("trove")
def do_request_merge_edit(self, **kw): require_access(self.req, 'write') try: kw = self.mr_widget_edit.to_python(kw) except formencode.Invalid: # trigger error_handler directly return self.edit(**kw) changes = OrderedDict() if self.req.summary != kw['summary']: changes['Summary'] = [self.req.summary, kw['summary']] self.req.summary = kw['summary'] if self.req.target_branch != kw['target_branch']: changes['Target branch'] = [self.req.target_branch, kw['target_branch']] self.req.target_branch = kw['target_branch'] if self.req.source_branch != kw['source_branch']: changes['Source branch'] = [self.req.source_branch, kw['source_branch']] self.req.source_branch = kw['source_branch'] if self.req.description != kw['description']: changes['Description'] = h.unidiff(self.req.description, kw['description']) self.req.description = kw['description'] if changes: self.req.add_meta_post(changes=changes) g.director.create_activity(c.user, 'updated', self.req, related_nodes=[c.project], tags=['merge-request']) self.refresh()
def save(self, **kw): require_access(c.app, 'write') rate_limit() post = BM.BlogPost.new(**kw) g.spam_checker.check(kw['title'] + u'\n' + kw['text'], artifact=post, user=c.user, content_type='blog-post') redirect(h.really_unicode(post.url()).encode('utf-8'))
def new(self, **kw): require_access(c.app, 'write') rate_limit() post = dict( state='published') c.form = W.new_post_form return dict(post=post)
def new(self, **kw): require_access(c.app, 'write') now = datetime.utcnow() post = dict( state='published') c.form = W.new_post_form return dict(post=post)
def edit(self, **kw): require_access(self.post, 'write') c.form = W.edit_post_form c.attachment_add = W.attachment_add c.attachment_list = W.attachment_list c.label_edit = W.label_edit return dict(post=self.post)
def clone(self, repo_type=None, source_url=None, mount_point=None, mount_label=None, **kw): require_access(c.project, 'admin') if repo_type is None: return ( '<form method="get">' '<input name="repo_type" value="Git">' '<input name="source_url">' '<input type="submit">' '</form>') for ep in pkg_resources.iter_entry_points('allura', repo_type): break if ep is None or source_url is None: raise exc.HTTPNotFound h.log_action(log, 'install tool').info( 'clone repo from %s', source_url, meta=dict(tool_type=repo_type, mount_point=mount_point, mount_label=mount_label)) c.project.install_app( repo_type, mount_point=mount_point, mount_label=mount_label, init_from_url=source_url) M.AuditLog.log('Create repo as clone') redirect('tools')
def delete_screenshot(self, id=None, **kw): require_access(c.project, 'update') if id is not None and id != '': M.AuditLog.log('remove screenshot') M.ProjectFile.query.remove(dict(project_id=c.project._id, _id=ObjectId(id))) g.post_event('project_updated') redirect('screenshots')
def delete(self): require_access(self.page, 'delete') M.Shortlink.query.remove(dict(ref_id=self.page.index_id())) self.page.deleted = True suffix = " {dt.hour}:{dt.minute}:{dt.second} {dt.day}-{dt.month}-{dt.year}".format(dt=datetime.utcnow()) self.page.title += suffix return dict(location='../'+self.page.title+'/?deleted=True')
def attach(self, file_info=None): if not self.page: raise exc.HTTPNotFound require_access(self.page, 'edit') if hasattr(file_info, 'file'): self.page.attach(file_info.filename, file_info.file, content_type=file_info.type) redirect(request.referer)
def index(self, **kw): require_access(self.neighborhood, 'admin') set_nav(self.neighborhood) if self.award is not None: return dict(award=self.award, neighborhood=self.neighborhood) else: redirect('not_found')
def update_configuration(self, divs=None, layout_class=None, new_div=None, **kw): require_access(c.project, 'update') config = M.PortalConfig.current() config.layout_class = layout_class # Handle updated and deleted divs if divs is None: divs = [] new_divs = [] for div in divs: log.info('Got div update:%s', pformat(div)) if div.get('del'): continue new_divs.append(div) # Handle new divs if new_div: new_divs.append(dict(name=h.nonce(), content=[])) config.layout = [] for div in new_divs: content = [] for w in div.get('content', []): if w.get('del'): continue mp,wn = w['widget'].split('/') content.append(dict(mount_point=mp, widget_name=wn)) if div.get('new_widget'): content.append(dict(mount_point='profile', widget_name='welcome')) config.layout.append(dict( name=div['name'], content=content)) redirect('configuration')
def update_label(self, mount_label): """Handles POST to update the Application's ``mount_label``. """ require_access(self.app, 'configure') self.app.config.options['mount_label'] = mount_label redirect(request.referer)
def configure(self, **kw): """Handle POST to delete the Application or update its ``config.options``. """ with h.push_config(c, app=self.app): require_access(self.app, 'configure') is_admin = self.app.config.tool_name == 'admin' if kw.pop('delete', False): if is_admin: flash('Cannot delete the admin tool, sorry....') redirect('.') c.project.uninstall_app(self.app.config.options.mount_point) redirect('..') for opt in self.app.config_options: if opt in Application.config_options: # skip base options (mount_point, mount_label, ordinal) continue val = kw.get(opt.name, '') if opt.ming_type == bool: val = asbool(val or False) elif opt.ming_type == int: val = asint(val or 0) self.app.config.options[opt.name] = val if is_admin: # possibly moving admin mount point redirect('/' + c.project._id + self.app.config.options.mount_point + '/' + self.app.config.options.mount_point + '/') else: redirect(request.referer)
def edit_screenshot(self, id=None, caption=None, **kw): require_access(c.project, 'update') if id is not None and id != '': M.ProjectFile.query.get( project_id=c.project._id, _id=ObjectId(id)).caption = caption g.post_event('project_updated') redirect('screenshots')
def post(self, text, message_id=None, parent_id=None, timestamp=None, ignore_security=False, is_meta=False, **kw): if not ignore_security: require_access(self, 'post') if self.ref_id and self.artifact: self.artifact.subscribe() if message_id is None: message_id = h.gen_message_id() parent = parent_id and self.post_class().query.get(_id=parent_id) slug, full_slug = self.post_class().make_slugs(parent, timestamp) kwargs = dict( discussion_id=self.discussion_id, full_slug=full_slug, slug=slug, thread_id=self._id, parent_id=parent_id, text=text, status='pending', is_meta=is_meta) if timestamp is not None: kwargs['timestamp'] = timestamp if message_id is not None: kwargs['_id'] = message_id post = self.post_class()(**kwargs) if ignore_security or not self.is_spam(post) and has_access(self, 'unmoderated_post')(): log.info('Auto-approving message from %s', c.user.username) file_info = kw.get('file_info', None) post.approve(file_info, notify=kw.get('notify', True)) else: self.notify_moderators(post) return post
def do_request_merge_edit(self, **kw): require_access(self.req, 'write') kw = self.mr_widget_edit.to_python(kw) changes = OrderedDict() if self.req.summary != kw['summary']: changes['Summary'] = [self.req.summary, kw['summary']] self.req.summary = kw['summary'] if self.req.target_branch != kw['target_branch']: changes['Target branch'] = [self.req.target_branch, kw['target_branch']] self.req.target_branch = kw['target_branch'] if self.req.source_branch != kw['source_branch']: changes['Source branch'] = [self.req.source_branch, kw['source_branch']] self.req.source_branch = kw['source_branch'] if self.req.description != kw['description']: changes['Description'] = h.unidiff(self.req.description, kw['description']) self.req.description = kw['description'] with self.req.push_downstream_context(): self.req.downstream['commit_id'] = c.app.repo.commit(kw['source_branch'])._id message = self.tmpl.render(changes=changes) self.req.discussion_thread.add_post(text=message, is_meta=True) redirect(self.req.url())
def save(self, status=None, **kw): require_access(self.req, 'write') if self.req.status != status: message = self.tmpl.render(changes={'Status': [self.req.status, status]}) self.req.discussion_thread.add_post(text=message, is_meta=True) self.req.status = status redirect('.')
def add_project(self, **form_data): c.project = self.neighborhood.neighborhood_project require_access(self.neighborhood, 'register') c.add_project = W.add_project form_data.setdefault('tools', [u'Wiki',u'Git',u'Tickets',u'Discussion']) form_data['neighborhood'] = self.neighborhood.name return dict(neighborhood=self.neighborhood, form_data=form_data)
def delete_screenshot(self, id=None, **kw): require_access(c.project, "update") if id is not None and id != "": M.AuditLog.log("remove screenshot") M.ProjectFile.query.remove(dict(project_id=c.project._id, _id=ObjectId(id))) g.post_event("project_updated") redirect("screenshots")
def register(self, project_unixname=None, project_description=None, project_name=None, neighborhood=None, private_project=None, tools=None, **kw): require_access(self.neighborhood, 'register') if private_project: require_access(self.neighborhood, 'admin') neighborhood = M.Neighborhood.query.get(name=neighborhood) project_description = h.really_unicode(project_description or '').encode('utf-8') project_name = h.really_unicode(project_name or '').encode('utf-8') project_unixname = h.really_unicode(project_unixname or '').encode('utf-8').lower() try: c.project = neighborhood.register_project(project_unixname, project_name=project_name, private_project=private_project) except exceptions.ProjectOverlimitError: flash("You have exceeded the maximum number of projects you are allowed to create", 'error') redirect('add_project') except exceptions.ProjectRatelimitError: flash("Project creation rate limit exceeded. Please try again later.", 'error') redirect('add_project') except Exception as e: log.error('error registering project: %s', project_unixname, exc_info=True) flash('Internal Error. Please try again later.', 'error') redirect('add_project') if project_description: c.project.short_description = project_description offset = c.project.next_mount_point(include_hidden=True) if tools and not neighborhood.project_template: anchored_tools = neighborhood.get_anchored_tools() for i, tool in enumerate(tools): if (tool.lower() not in anchored_tools.keys()) and (c.project.app_instance(tool) is None): c.project.install_app(tool, ordinal=i + offset) flash('Welcome to the %s Project System! ' 'To get started, fill out some information about your project.' % config['site_name']) redirect(c.project.script_name + 'admin/overview')
def revert(self, version, **kw): require_access(self.post, 'write') orig = self._get_version(version) if orig: self.post.text = orig.text self.post.commit() redirect('.')
def grants(self, **kw): require_access(self.neighborhood, 'admin') grants = M.AwardGrant.query.find( dict(granted_by_neighborhood_id=self.neighborhood._id)) count = grants.count() return dict(grants=grants or [], count=count)
def index(self, **kw): require_access(self.neighborhood, 'admin') awards = M.Award.query.find( dict(created_by_neighborhood_id=self.neighborhood._id)).all() return dict(awards=awards or [], count=len(awards))
def _check_security(self): require_access(self.neighborhood, 'read')
def help(self, **kw): require_access(self.neighborhood, 'admin') set_nav(self.neighborhood) return dict(neighborhood=self.neighborhood, )
def needs_artifact_access_ok(self): require_access(self.page, 'read') return ''
def reply(self, file_info=None, **kw): require_access(self.thread, 'post') kw = self.W.edit_post.to_python(kw, None) p = self.thread.add_post(parent_id=self.post._id, **kw) p.add_multiple_attachments(file_info) redirect(request.referer)
def _check_security(self): require_access(self.app, 'admin')
def reply(self, **kw): require_access(self.thread, 'post') kw = self.W.edit_post.to_python(kw, None) post = self.thread.post(parent_id=self.post._id, **kw) self.thread.num_replies += 1 redirect(post.slug.split('/')[-1] + '/')
def _check_security(self): require_access(self.discussion, 'moderate')
def attach(self, file_info=None): require_access(self.post, 'moderate') self.post.add_multiple_attachments(file_info) redirect(request.referer)
def flag_as_spam(self, **kw): require_access(self.thread, 'moderate') self.thread.spam() flash('Thread flagged as spam.') redirect(self.discussion.url())
def _check_security(self): require_access(self.post, 'read')
def _check_security(self): require_access(self.thread, 'read') if self.thread.ref: require_access(self.thread.ref.artifact, 'read')
def tag(self, labels, **kw): require_access(self.thread, 'post') if self.thread.ref: require_access(self.thread.ref.artifact, 'post') self.thread.labels = labels.split(',') redirect(request.referer)
def new(self, **kw): require_access(self.thread, 'post') kw = self.W.edit_post.to_python(kw, None) # could raise Invalid, but doesn't seem like it ever does p = self.thread.add_post(**kw) redirect(p.slug + '/')
def update_label(self, mount_label): require_access(self.app, 'configure') self.app.config.options['mount_label'] = mount_label redirect(request.referer)
def index(self, url='', **kw): if (request.method == 'POST') and (url != ''): require_access(self.app, 'configure') self.app.config.options.url = url return self.link_json()
def reply(self, **kw): require_access(self.thread, 'post') kw = self.W.edit_post.to_python(kw, None) # could raise Invalid, but doesn't seem like it ever does post = self.thread.post(parent_id=self.post._id, **kw) self.thread.num_replies += 1 redirect(post.slug.split('/')[-1] + '/')
def _check_security(self): require_access(c.project, 'admin')
def _check_security(self): require_access(c.app, 'read')
def add_trove(self, type, new_trove, **kw): require_access(c.project, 'update') trove_obj, error_msg = self._add_trove(type, new_trove) if error_msg: flash(error_msg, 'error') redirect('trove')
def _update_mounts(self, subproject=None, tool=None, new=None, **kw): ''' Returns the new App or Subproject, if one was installed. Returns None otherwise. ''' if subproject is None: subproject = [] if tool is None: tool = [] new_app = None for sp in subproject: p = M.Project.query.get(shortname=sp['shortname'], neighborhood_id=c.project.neighborhood_id) if sp.get('delete'): require_access(c.project, 'admin') M.AuditLog.log('delete subproject %s', sp['shortname']) p.removal = 'deleted' plugin.ProjectRegistrationProvider.get().delete_project( p, c.user) elif not new: M.AuditLog.log('update subproject %s', sp['shortname']) p.name = sp['name'] p.ordinal = int(sp['ordinal']) for p in tool: if p.get('delete'): require_access(c.project, 'admin') M.AuditLog.log('uninstall tool %s', p['mount_point']) c.project.uninstall_app(p['mount_point']) elif not new: M.AuditLog.log('update tool %s', p['mount_point']) options = c.project.app_config(p['mount_point']).options options.mount_label = p['mount_label'] options.ordinal = int(p['ordinal']) if new and new.get('install'): ep_name = new.get('ep_name', None) if not ep_name: require_access(c.project, 'create') mount_point = new['mount_point'].lower() or h.nonce() M.AuditLog.log('create subproject %s', mount_point) sp = c.project.new_subproject(mount_point) sp.name = new['mount_label'] if 'ordinal' in new: sp.ordinal = int(new['ordinal']) else: sp.ordinal = c.project.last_ordinal_value() + 1 new_app = sp else: require_access(c.project, 'admin') installable_tools = AdminApp.installable_tools_for(c.project) if not ep_name.lower() in [t['name'].lower() for t in installable_tools]: flash('Installation limit exceeded.', 'error') return mount_point = new['mount_point'] or ep_name M.AuditLog.log('install tool %s', mount_point) App = g.entry_points['tool'][ep_name] # pass only options which app expects config_on_install = { k: v for (k, v) in six.iteritems(kw) if k in [o.name for o in App.options_on_install()] } new_app = c.project.install_app( ep_name, mount_point, mount_label=new['mount_label'], ordinal=int(new['ordinal']) if 'ordinal' in new else None, **config_on_install) g.post_event('project_updated') g.post_event('project_menu_updated') return new_app
def update(self, name=None, short_description=None, summary='', icon=None, category=None, external_homepage='', video_url='', support_page='', support_page_url='', twitter_handle='', facebook_page='', removal='', moved_to_url='', tracking_id='', features=None, **kw): require_access(c.project, 'update') if removal != c.project.removal: M.AuditLog.log('change project removal status to %s', removal) c.project.removal = removal c.project.removal_changed_date = datetime.utcnow() if 'delete_icon' in kw: M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon'))) c.project.set_tool_data('allura', icon_original_size=None) M.AuditLog.log('remove project icon') g.post_event('project_updated') redirect('overview') elif 'delete' in kw: allow_project_delete = asbool( config.get('allow_project_delete', True)) if allow_project_delete or not c.project.is_root: M.AuditLog.log('delete project') plugin.ProjectRegistrationProvider.get().delete_project( c.project, c.user) redirect('overview') elif 'undelete' in kw: M.AuditLog.log('undelete project') plugin.ProjectRegistrationProvider.get().undelete_project( c.project, c.user) redirect('overview') if name and name != c.project.name: M.AuditLog.log('change project name to %s', name) c.project.name = name if short_description != c.project.short_description: M.AuditLog.log('change short description to %s', short_description) c.project.short_description = short_description if summary != c.project.summary: M.AuditLog.log('change summary to %s', summary) c.project.summary = summary category = category and ObjectId(category) or None if category != c.project.category_id: M.AuditLog.log('change category to %s', category) c.project.category_id = category if external_homepage != c.project.external_homepage: M.AuditLog.log('change external home page to %s', external_homepage) c.project.external_homepage = external_homepage if video_url != c.project.video_url: M.AuditLog.log('change video url to %s', video_url) c.project.video_url = video_url if support_page != c.project.support_page: M.AuditLog.log('change project support page to %s', support_page) c.project.support_page = support_page old_twitter = c.project.social_account('Twitter') if not old_twitter or twitter_handle != old_twitter.accounturl: M.AuditLog.log('change project twitter handle to %s', twitter_handle) c.project.set_social_account('Twitter', twitter_handle) old_facebook = c.project.social_account('Facebook') if not old_facebook or facebook_page != old_facebook.accounturl: if not facebook_page or 'facebook.com' in urlparse(facebook_page).netloc: M.AuditLog.log( 'change project facebook page to %s', facebook_page) c.project.set_social_account('Facebook', facebook_page) if support_page_url != c.project.support_page_url: M.AuditLog.log('change project support page url to %s', support_page_url) c.project.support_page_url = support_page_url if moved_to_url != c.project.moved_to_url: M.AuditLog.log('change project moved to url to %s', moved_to_url) c.project.moved_to_url = moved_to_url if tracking_id != c.project.tracking_id: M.AuditLog.log('change project tracking ID to %s', tracking_id) c.project.tracking_id = tracking_id features = [f['feature'].strip() for f in features or [] if f.get('feature', '').strip()] if features != c.project.features: M.AuditLog.log('change project features to %s', features) c.project.features = features if icon is not None and icon != '': if c.project.icon: M.ProjectFile.query.remove(dict(project_id=c.project._id, category=re.compile(r'^icon'))) M.AuditLog.log('update project icon') c.project.save_icon(icon.filename, icon.file, content_type=icon.type) g.post_event('project_updated') flash('Saved', 'success') redirect('overview')
def add_trove_js(self, type, new_trove, **kw): require_access(c.project, 'update') trove_obj, error_msg = self._add_trove(type, new_trove) return dict(trove_full_path=trove_obj.fullpath_within_type, trove_cat_id=trove_obj.trove_cat_id, error_msg=error_msg)
def index(self, **kw): require_access(self.neighborhood, 'admin') if self.grant is not None: return dict(grant=self.grant) else: redirect('not_found')
def update_labels(self, labels=None, **kw): require_access(c.project, 'admin') c.project.labels = labels.split(',') M.AuditLog.log('updated labels') redirect('trove')
def revoke(self): require_access(self.neighborhood, 'admin') self.grant.delete() with h.push_context(self.project._id): g.post_event('project_updated') redirect(request.referer or '/')
def _check_security(self): require_access(c.project, 'read')
def new(self, **kw): require_access(self.thread, 'post') kw = self.W.edit_post.to_python(kw, None) p = self.thread.add_post(**kw) redirect(p.slug + '/')
def needs_artifact_access_fail(self): require_access(self.page, 'no_such_permission') return ''