class WikiPageForm(Form): title = StringField(label=_l(u"Title"), filters=(strip, ), validators=[required()]) body_src = TextAreaField( label=_l("Body"), filters=(strip, clean_up), validators=[required()], widget=TextArea(rows=10, resizeable='vertical'), ) message = StringField(label=_l("Commit message")) page_id = HiddenField(filters=(int_or_none, ), validators=[flaghidden()]) last_revision_id = HiddenField(filters=(int_or_none, ), validators=[flaghidden()]) def validate_title(self, field): title = field.data if title != field.object_data and page_exists(title): raise ValidationError( _(u"A page with this name already exists. Please use another name." )) def validate_last_revision_id(self, field): val = field.data current = field.object_data if val is None or current is None: return if val != current: raise ValidationError(_(u'this page has been edited since'))
class ThreadCloseView(BaseThreadView, views.object.BaseObjectView): """Close / Re-open a thread.""" methods = ["POST"] _VALID_ACTIONS = {"close", "reopen"} CLOSED_MSG = _l("The thread is now closed for edition and new " "contributions.") REOPENED_MSG = _l("The thread is now re-opened for edition and new " "contributions.") def prepare_args(self, args, kwargs): args, kwargs = super(ThreadCloseView, self).prepare_args(args, kwargs) action = kwargs["action"] = request.form.get("action") if action not in self._VALID_ACTIONS: raise BadRequest("Unknown action: {!r}".format(action)) return args, kwargs def post(self, action=None): is_closed = action == "close" self.obj.closed = is_closed sa.orm.object_session(self.obj).commit() msg = self.CLOSED_MSG if is_closed else self.REOPENED_MSG flash(text_type(msg)) return self.redirect(url_for(self.obj))
class PostEditForm(BasePostForm): reason = StringField( label=_l("Reason"), description=_l("Description of your edit"), filters=(strip,), validators=(optional(),), )
class EventEditView(BaseEventView, views.ObjectEdit): POST_BUTTON = ButtonAction("form", "create", btn_class="primary", title=_l("Post this event")) title = _l("Edit event")
class ThreadCloseView(BaseThreadView, views.object.BaseObjectView): """Close / Re-open a thread. """ methods = ['POST'] _VALID_ACTIONS = {u'close', u'reopen'} CLOSED_MSG = _l(u'The thread is now closed for edition and new ' u'contributions.') REOPENED_MSG = _l(u'The thread is now re-opened for edition and new ' u'contributions.') def prepare_args(self, args, kwargs): args, kwargs = super(ThreadCloseView, self).prepare_args(args, kwargs) action = kwargs['action'] = request.form.get('action') if action not in self._VALID_ACTIONS: raise BadRequest(u'Unknown action: {!r}'.format(action)) return args, kwargs def post(self, action=None): is_closed = (action == u'close') self.obj.closed = is_closed sa.orm.object_session(self.obj).commit() msg = self.CLOSED_MSG if is_closed else self.REOPENED_MSG flash(text_type(msg)) return self.redirect(url_for(self.obj))
class UserCreateForm(BaseUserAdminForm): password = StringField( _l("Password"), description=_l("If empty a random password will be generated."), widget=widgets.PasswordInput(autocomplete="off"), )
def activity_time_format(time, now=None): if not time: return "" if not now: now = datetime.utcnow() time_delta = now - time month_abbreviation = format_date(time, "MMM") days, hours, minutes, seconds = ( time_delta.days, time_delta.seconds // 3600, time_delta.seconds // 60, time_delta.seconds, ) if days == 0 and hours == 0 and minutes == 0: return "{}{}".format(seconds, _l("s")) if days == 0 and hours == 0: return "{}{}".format(minutes, _l("m")) if days == 0: return "{}{}".format(hours, _l("h")) if days < 30: return "{}{}".format(days, _l("d")) if time.year == now.year: return f"{month_abbreviation} {time.day}" return "{} {}".format(month_abbreviation, str(time.year))
class GroupAdminForm(Form): name = StringField(_l(u'Name'), filters=(strip,), validators=[required()]) description = StringField(_l(u'Description'), filters=(strip,)) public = BooleanField( _l(u'Public'), widget=widgets.BooleanWidget(on_off_mode=True)) roles = fields.Select2MultipleField( _l(u'Roles'), choices=lambda: [(r.name, r.label) for r in Role.assignable_roles()],)
class AttachmentForm(Form): blob = FileField(_l(u'file'), validators=[required()], filters=[strip], multiple=False) description = StringField(_l(u'description (optional)'), filters=[strip]) class Meta: model = Attachment include_primary_keys = True assign_required = False # for 'id': allow None, for new records
class EditForm(ModelForm): label = StringField(_l(u'Label'), description=_l(u'allowed tags: %(tags)s', tags=', '.join(ALLOWED_TAGS)), filters=(strip, ), validators=[required()]) default = BooleanField(_l(u'Default'), default=False) active = BooleanField(_l(u'Active'), default=True) def validate_label(self, field): field.data = bleach.clean(field.data, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES, strip=True)
class BasePostForm(Form): message = TextAreaField(label=_l("Message"), widget=RichTextWidget(allowed_tags=WIDGET_ALLOWED), filters=(strip, ), validators=[required()]) attachments = FileField(label=_l('Attachments'), multiple=True, validators=[optional()]) def validate_message(self, field): field.data = bleach.clean(field.data, tags=ALLOWED_TAGS, attributes=ALLOWED_ATTRIBUTES, styles=ALLOWED_STYLES, strip=True)
class PageCreate(PageEdit, ObjectCreate): title = _l("Create page") _message_success = _l(u"Wiki page successfully created.") get_form_kwargs = ObjectCreate.get_form_kwargs def init_object(self, args, kwargs): args, kwargs = ObjectCreate.init_object(self, args, kwargs) self.obj.community = g.community session = sa.orm.object_session(self.obj) if session: sa.orm.session.make_transient(self.obj) for rev in self.obj.revisions: sa.orm.session.make_transient(rev) return args, kwargs
def get_actions(self): excel_actions = [] button = "default" if not self.EXCEL_EXPORT_RELATED else None endpoint = self.module.endpoint excel_actions.append( ModuleAction( self.module, "excel", "export_xls", title=_l("Export to Excel"), icon=FAIcon("align-justify"), endpoint=Endpoint(endpoint + ".export_xls"), button=button, css="datatable-export", ) ) for column_set in self.EXCEL_EXPORT_RELATED: excel_actions.append( ModuleActionGroupItem( self.module, "excel", "export_related_" + column_set.related_attr, title=column_set.export_label, icon=FAIcon("align-justify"), css="datatable-export", endpoint=Endpoint( endpoint + ".export_xls", related=column_set.related_attr ), ) ) if self.EXCEL_SUPPORT_IMPORT: pass if len(excel_actions) > 1: excel_actions = [ ModuleActionDropDown( self.module, "excel", "actions", title=_l("Excel"), button="default", items=excel_actions, ) ] return excel_actions
def init_forum_values(endpoint, values): g.current_tab = 'forum' g.breadcrumb.append( BreadcrumbItem(label=_l(u'Conversations'), url=Endpoint('forum.index', community_id=g.community.slug)))
class EventCreateView(BaseEventView, views.ObjectCreate): POST_BUTTON = ButtonAction( 'form', 'create', btn_class='primary', title=_l('Post this event')) title = _l("New event") def after_populate_obj(self): if self.obj.community is None: self.obj.community = g.community._model def get_form_buttons(self, *args, **kwargs): return [self.POST_BUTTON, views.object.CANCEL_BUTTON] @property def activity_target(self): return self.obj.community
class DashboardPanel(AdminPanel): id = 'dashboard' path = '' label = _l('Dashboard') icon = 'eye-open' def get(self): login_entries = LoginSession.query \ .order_by(LoginSession.started_at.asc()) \ .all() # .options(sa.orm.joinedload(LoginSession.user)) daily, weekly, monthly = uniquelogins(login_entries) new_logins, total_users = newlogins(login_entries) stats = { 'today': stats_since(timedelta(days=1)), 'this_week': stats_since(timedelta(days=7)), 'this_month': stats_since(timedelta(days=30)), } # let's format the data into NVD3 datastructures connections = [ { 'key': _('Daily'), 'color': '#7777ff', 'values': daily }, { 'key': _('Weekly'), 'color': '#2ca02c', 'values': weekly, 'disabled': True, }, { 'key': _('Monthly'), 'color': '#ff7f0e', 'values': monthly, 'disabled': True, }, ] new_logins = [ { 'key': _('New'), 'color': '#ff7f0e', "bar": True, 'values': new_logins, }, { 'key': _('Total'), 'color': '#2ca02c', 'values': total_users }, ] return render_template( "admin/dashboard.html", stats=stats, connections=connections, new_logins=new_logins, )
def __init__(self, *panels: Any, **kwargs: Any) -> None: self.app = None self.panels: List[AdminPanel] = [] self._panels_endpoints: Dict[str, AdminPanel] = {} self.nav_paths: Dict[str, str] = {} self.breadcrumb_items: Dict[AdminPanel, BreadcrumbItem] = {} self.setup_blueprint() def condition(context: Dict[str, bool]) -> bool: return not current_user.is_anonymous and security.has_role( # pyre-fixme[6]: Expected `Principal` for 1st param but got # `LocalProxy`. current_user, AdminRole, ) self.nav_root = NavGroup( "admin", "root", title=_l("Admin"), endpoint=None, condition=condition ) for panel in panels: self.register_panel(panel) app = kwargs.pop("app", None) if app is not None: self.init_app(app)
class ObjectCreate(ObjectEdit): """Create a new object. """ permission = CREATE activity_verb = 'post' _message_success = _l(u"Entity successfully added") #: set to `True` to show 'Save and add new' button chain_create_allowed = False def __init__(self, *args, **kwargs): chain_create_allowed = kwargs.pop('chain_create_allowed', None) if chain_create_allowed is not None: self.chain_create_allowed = bool(chain_create_allowed) ObjectEdit.__init__(self, *args, **kwargs) def prepare_args(self, args, kwargs): # we must ensure that no flush() occurs and that obj is not registered in # session (to prevent accidental insert of an incomplete object) session = current_app.db.session() with session.no_autoflush: args, kwargs = super(ObjectCreate, self).prepare_args(args, kwargs) try: session.expunge(self.obj) except sa.exc.InvalidRequestError: # obj is not in session pass return args, kwargs def init_object(self, args, kwargs): self.obj = self.Model() return args, kwargs def get_form_kwargs(self): kw = super(ObjectCreate, self).get_form_kwargs() if request.method == 'GET': # when GET allow form prefill instead of empty/current object data # FIXME: filter allowed parameters on given a field flags (could be # 'allow_from_get'?) kw['formdata'] = request.args return kw def get_form_buttons(self, *args, **kwargs): return [CREATE_BUTTON, CHAIN_CREATE_BUTTON, CANCEL_BUTTON] def breadcrumb(self): return nav.BreadcrumbItem(label=CREATE_BUTTON.title) # actions def create(self): return self.edit() chain_create = create def cancel(self): return self.redirect_to_index()
class ObjectDelete(ObjectEdit): """ Delete object. Supports DELETE verb. """ methods = ['POST'] permission = DELETE activity_verb = 'delete' _message_success = _l(u"Entity deleted") init_object = BaseObjectView.init_object def get_form_buttons(self, *args, **kwargs): return [DELETE_BUTTON, CANCEL_BUTTON] def delete(self): session = current_app.db.session() session.delete(self.obj) activity.send(self, actor=g.user, verb="delete", object=self.obj, target=self.activity_target) session.commit() flash(self.message_success(), 'success') # FIXME: for DELETE verb response in case of success should be 200, 202 # (accepted) or 204 (no content) return self.redirect_to_index()
class CommunityEdit(BaseCommunityView, views.ObjectEdit): template = "community/edit.html" title = _l("Edit community") decorators = views.ObjectEdit.decorators + (require_admin, tab("settings")) def breadcrumb(self): return BreadcrumbItem( label=_("Settings"), icon="cog", url=Endpoint("communities.settings", community_id=g.community.slug), ) def before_populate_obj(self): form = self.form name = form.name.data if name != self.obj.name: self.obj.rename(name) del form.name type = form.type.data if type != self.obj.type: self.obj.type = type self.obj.update_roles_on_folder() del form.type self.linked_group = form.linked_group.data or None if self.linked_group: self.linked_group = Group.query.get(int(self.linked_group)) del form.linked_group def after_populate_obj(self): self.obj.group = self.linked_group
def init_document_values(endpoint, values): g.current_tab = 'documents' g.breadcrumb.append( BreadcrumbItem(label=_l(u'Documents'), url=Endpoint('documents.index', community_id=g.community.slug)))
class UsersPanel(AdminPanel): """User administration panel.""" id = "users" label = _l("Users") icon = "user" def install_additional_rules(self, add_url_rule): add_url_rule("/users", view_func=views.JsonUsersList.as_view("json_list")) add_url_rule("/new", view_func=views.UserCreate.as_view("new")) add_url_rule("/<int:user_id>", view_func=views.UserEdit.as_view("user")) def get(self): # FIXME: use widgets.AjaxMainTableView instead datatable_options = { "sDom": "lfFritip", "aaSorting": [[1, "asc"]], "aoColumns": [ dict(bSortable=False), dict(asSorting=["asc", "desc"]), dict(asSorting=["asc", "desc"]), dict(bSortable=False), dict(bSortable=False), dict(bSortable=False), dict(asSorting=["asc", "desc"]), ], "bFilter": True, "oLanguage": { "sSearch": _("Filter records:"), "sPrevious": _("Previous"), "sNext": _("Next"), "sInfo": _("Showing _START_ to _END_ of _TOTAL_ entries"), "sInfoFiltered": _("(filtered from _MAX_ total entries)"), "sAddAdvancedFilter": _("Add a filter"), }, "bStateSave": False, "bPaginate": True, "sPaginationType": "bootstrap", "bLengthChange": False, "iDisplayLength": 30, "bProcessing": True, "bServerSide": True, "sAjaxSource": url_for(".users_json_list"), } return render_template("admin/users.html", next=next, datatable_options=datatable_options)
class UserProfileEdit(ObjectEdit): Model = User Form = UserProfileForm pk = "user_id" _message_success = _l("Profile edited") def init_object(self, args, kwargs): args, kwargs = super(UserProfileEdit, self).init_object(args, kwargs) self.user = self.obj return args, kwargs def view_url(self): return url_for(".user", user_id=self.user.id) def edit(self): if not can_edit(self.user): return Response(status=403) return super(UserProfileEdit, self).edit() def handle_commit_exception(self, exc): db.session.rollback() if isinstance(exc, sa.exc.IntegrityError): log_msg = "Error saving user profile" else: log_msg = "Unexpected error while saving user profile" logger.error(log_msg, exc_info=True, extra={"stack": True}) flash(_("Error occured"), "error") return self.redirect_to_view()
def __init__(self, name, label=None, assignable=True): UniqueName.__init__(self, name) if label is None: label = "permission_" + str(name) if isinstance(label, str): label = _l(label) self.label = label
def __init__(self, name, label=None, assignable=True): UniqueName.__init__(self, name) if label is None: label = u'permission_' + unicode(name) if isinstance(label, unicode): label = _l(label) self.label = label
def __init__(self, name, label=None, assignable=True): UniqueName.__init__(self, name) if label is None: label = u'permission_' + text_type(name) if isinstance(label, text_type): label = _l(label) self.label = label
class DashboardPanel(AdminPanel): id = "dashboard" path = "" label = _l("Dashboard") icon = "eye-open" def get(self) -> str: login_entries = LoginSession.query.order_by( LoginSession.started_at.asc()).all() # .options(sa.orm.joinedload(LoginSession.user)) daily, weekly, monthly = uniquelogins(login_entries) new_logins, total_users = newlogins(login_entries) stats = { "today": stats_since(timedelta(days=1)), "this_week": stats_since(timedelta(days=7)), "this_month": stats_since(timedelta(days=30)), } # let's format the data into NVD3 datastructures connections = [ { "key": _("Daily"), "color": "#7777ff", "values": daily }, { "key": _("Weekly"), "color": "#2ca02c", "values": weekly, "disabled": True, }, { "key": _("Monthly"), "color": "#ff7f0e", "values": monthly, "disabled": True, }, ] new_logins = [ { "key": _("New"), "color": "#ff7f0e", "bar": True, "values": new_logins }, { "key": _("Total"), "color": "#2ca02c", "values": total_users }, ] return render_template( "admin/dashboard.html", stats=stats, connections=connections, new_logins=new_logins, )
def __init__(self, name, label=None, assignable=True): UniqueName.__init__(self, name) if label is None: label = "role_" + text_type(name) if isinstance(label, text_type): label = _l(label) self.label = label self.assignable = assignable
def entity_tags_form(self, entity, ns=None): """Construct a form class with a field for tags in namespace `ns`.""" if ns is None: ns = self.entity_default_ns(entity) field = TagsField(label=_l("Tags"), ns=ns) cls = type("EntityNSTagsForm", (_TagsForm, ), {"tags": field}) return cls
def init_forum_values(endpoint, values): g.current_tab = "forum" g.breadcrumb.append( BreadcrumbItem( label=_l("Conversations"), url=Endpoint("forum.index", community_id=g.community.slug), ))
def entity_tags_form(self, entity, ns=None): """Construct a form class with a field for tags in namespace `ns`.""" if ns is None: ns = self.entity_default_ns(entity) field = TagsField(label=_l("Tags"), ns=ns) cls = type("EntityNSTagsForm", (_TagsForm,), {"tags": field}) return cls
def __init__(self, name, label=None, assignable=True): UniqueName.__init__(self, name) if label is None: label = u'role_' + unicode(name) if isinstance(label, unicode): label = _l(label) self.label = label self.assignable = assignable
def init_forum_values(endpoint, values): g.current_tab = "forum" g.breadcrumb.append( BreadcrumbItem( label=_l("Conversations"), url=Endpoint("forum.index", community_id=g.community.slug), ) )
def init_document_values(endpoint, values): g.current_tab = "documents" g.is_manager = is_manager() g.breadcrumb.append( BreadcrumbItem( label=_l("Documents"), url=Endpoint("documents.index", community_id=g.community.slug), ))
class UsersPanel(AdminPanel): """User administration panel.""" id = 'users' label = _l(u'Users') icon = 'user' def install_additional_rules(self, add_url_rule): add_url_rule( '/users', view_func=views.JsonUsersList.as_view('json_list'), ) add_url_rule('/new', view_func=views.UserCreate.as_view('new')) add_url_rule( '/<int:user_id>', view_func=views.UserEdit.as_view('user')) def get(self): # FIXME: use widgets.AjaxMainTableView instead datatable_options = { 'sDom': 'lfFritip', 'aaSorting': [ [1, u'asc'], ], 'aoColumns': [ dict(bSortable=False), dict(asSorting=['asc', 'desc']), dict(asSorting=['asc', 'desc']), dict(bSortable=False), dict(bSortable=False), dict(bSortable=False), dict(asSorting=['asc', 'desc']), ], 'bFilter': True, 'oLanguage': { 'sSearch': _("Filter records:"), 'sPrevious': _("Previous"), 'sNext': _("Next"), 'sInfo': _("Showing _START_ to _END_ of _TOTAL_ entries"), 'sInfoFiltered': _("(filtered from _MAX_ total entries)"), 'sAddAdvancedFilter': _("Add a filter"), }, 'bStateSave': False, 'bPaginate': True, 'sPaginationType': "bootstrap", 'bLengthChange': False, 'iDisplayLength': 30, 'bProcessing': True, 'bServerSide': True, 'sAjaxSource': url_for('.users_json_list'), } return render_template( 'admin/users.html', next=next, datatable_options=datatable_options, )
def init_wiki_values(endpoint, values): g.current_tab = "wiki" endpoint = Endpoint("wiki.index", community_id=g.community.slug) g.breadcrumb.append(BreadcrumbItem(label=_l("Wiki"), url=endpoint)) title = request.args.get("title", "").strip() if title and title != "Home": url = Endpoint("wiki.page", community_id=g.community.slug, title=title) g.breadcrumb.append(BreadcrumbItem(label=title, url=url))
def init_document_values(endpoint, values): g.current_tab = "documents" g.is_manager = is_manager() g.breadcrumb.append( BreadcrumbItem( label=_l("Documents"), url=Endpoint("documents.index", community_id=g.community.slug), ) )
def register_actions(self): ACTIONS = [ ModuleAction(self, u'entity', u'create', title=_l(u'Create New'), icon=FAIcon('plus'), endpoint=Endpoint(self.endpoint + '.entity_new'), button='default',), ] for component in self.components: ACTIONS.extend(component.get_actions()) actions.register(*ACTIONS)
def get_extra_args(self, *args, **kwargs): from ..codegen import CodeGenerator generator = CodeGenerator(data=self.data["type_args"]) year_field = IntegerField(label=_l(u"Year")) FormBase = generator.gen_form(self.generator.module) ModelField = type(self.name + "Form", (FormBase, Form), {"year": year_field}) extra_args = super(YearlyFormField, self).get_extra_args(*args, **kwargs) extra_args["unbound_field"] = awbff.FormField(ModelField, default=dict) extra_args["population_strategy"] = "update" extra_args["min_entries"] = 1 return extra_args
def register_actions(self): ACTIONS = [ ModuleAction( self, "entity", "create", title=_l("Create New"), icon=FAIcon("plus"), endpoint=Endpoint(self.endpoint + ".entity_new"), button="default", ) ] for component in self.components: ACTIONS.extend(component.get_actions()) actions.register(*ACTIONS)
def pull_community(endpoint, values): """url_value_preprocessor function.""" g.nav["active"] = "section:communities" g.breadcrumb.append( BreadcrumbItem(label=_l("Communities"), url=Endpoint("communities.index")) ) try: slug = values.pop("community_id") community = Community.query.filter(Community.slug == slug).first() if community: g.community = CommunityPresenter(community) wall_url = Endpoint("wall.index", community_id=community.slug) breadcrumb_item = BreadcrumbItem(label=community.name, url=wall_url) g.breadcrumb.append(breadcrumb_item) else: raise NotFound() except KeyError: pass
def __init__(self, *panels, **kwargs): self.app = None self.panels = [] self._panels_endpoints = {} self.nav_paths = {} self.breadcrumb_items = {} self.setup_blueprint() self.nav_root = NavGroup( 'admin', 'root', title=_l(u'Admin'), endpoint=None, condition=lambda context: (not current_user.is_anonymous() and security.has_role(current_user, AdminRole)) ) for panel in panels: self.register_panel(panel) app = kwargs.pop('app', None) if app is not None: self.init_app(app)
def __init__(self, *panels, **kwargs): self.app = None self.panels = [] self._panels_endpoints = {} self.nav_paths = {} self.breadcrumb_items = {} self.setup_blueprint() def condition(context): return not current_user.is_anonymous and security.has_role( current_user, AdminRole ) self.nav_root = NavGroup( "admin", "root", title=_l("Admin"), endpoint=None, condition=condition ) for panel in panels: self.register_panel(panel) app = kwargs.pop("app", None) if app is not None: self.init_app(app)
"img": ["src", "alt", "title"], } ALLOWED_STYLES = ["text-align"] WIDGET_ALLOWED = {} for attr in ALLOWED_TAGS: allowed = ALLOWED_ATTRIBUTES.get(attr, True) if not isinstance(allowed, bool): allowed = {tag: True for tag in allowed} WIDGET_ALLOWED[attr] = allowed # instantiate this one before PostForm fields, so that it is listed first # when Threadform is displayed _TITLE_FIELD = StringField( label=_l("Title"), filters=(strip,), validators=[required(), Length(max=150)] ) class BasePostForm(Form): message = TextAreaField( label=_l("Message"), widget=RichTextWidget(allowed_tags=WIDGET_ALLOWED), filters=(strip,), validators=[required()], ) attachments = FileField( label=_l("Attachments"), multiple=True, validators=[optional()] ) def validate_message(self, field):
def can_create(self): create_cls = self.module.create_cls permission = create_cls.permission cls_permissions = dict(self.Model.__default_permissions__) if self.permission in cls_permissions: security = current_app.services['security'] return security.has_permission(current_user, create_cls.permission, obj=self.obj, roles=cls_permissions[permission]) return False EDIT_ACTION = Action( 'module', 'object:view', title=_l(u'Edit'), button='default', condition=lambda ctx: ctx['view'].can_edit, icon=FAIcon('edit'), url=lambda ctx: url_for('.entity_edit', **{ctx['view'].pk: ctx['view'].obj.id}), ) DELETE_ACTION = Action( 'module', 'object:view', title=_l(u'Delete'), button='danger', condition=lambda ctx: ctx['view'].can_delete, icon=FAIcon('trash fa-inverse'), url=lambda ctx: url_for('.entity_delete', **{ctx['view'].pk: ctx['view'].obj.id}), ) DELETE_ACTION.template = 'widgets/frontend_action_delete_confim.html'
base_template = "admin/_base.html" def index_url(self): return url_for(".groups") def view_url(self): return url_for(".groups_group", group_id=self.obj.id) # those buttons are made to have valid edit actions, but will not be shown in # edit forms: they must be availabe only during POST ADD_USER_BUTTON = ButtonAction( "form", "add_user", condition=lambda v: request.method == "POST", title=_l("Add"), btn_class="primary", ) REMOVE_USER_BUTTON = ButtonAction( "form", "remove_user", condition=lambda v: request.method == "POST", btn_class="danger", icon=FAIcon("times"), title="", ) class GroupView(GroupBase, views.ObjectView): template = "admin/group_view.html"
roles.sort() return roles class RoleType(UniqueNameType): """ Store :class:`Role` Usage:: RoleType() """ Type = Role #: marker for role assigned to 'Anonymous' Anonymous = Role('anonymous', _l(u'role_anonymous'), assignable=False) #: marker for role assigned to 'Authenticated' Authenticated = Role('authenticated', _l(u'role_authenticated'), assignable=False) #: marker for `admin` role Admin = Role('admin', _l(u'role_administrator')) #: marker for `manager` role Manager = Role('manager', _l(u'role_manager'), assignable=False) Creator = Role('creator', assignable=False) Owner = Role('owner', assignable=False) Reader = Role('reader', assignable=False) Writer = Role('writer', assignable=False)
def url(self, context=None): event = context.get("object") return url_for( "." + self.name, community_id=g.community.slug, event_id=event.id ) def is_admin(context): security = get_service("security") return security.has_role(current_user, Admin, object=context.get("object")) _actions = [ CalendarAction( "calendar:global", "new_event", _l("Create a new event"), icon="plus" ), CalendarAction("calendar:global", "index", _l("Upcoming events"), icon="list"), EventAction("calendar:event", "event", _l("View event"), icon=FAIcon("eye")), EventAction( "calendar:event", "event_edit", _l("Edit event"), icon=FAIcon("pencil") ), ] def register_actions(state): if not actions.installed(state.app): return with state.app.app_context(): actions.register(*_actions)
from abilian.core.util import md5, unwrap from abilian.i18n import _l, render_template_i18n from abilian.web import url_for from celery import shared_task from celery.schedules import crontab from celery.utils.log import get_task_logger from flask import current_app, g from flask_babel import get_locale from flask_mail import Message from itsdangerous import Serializer from six import text_type from .forms import ALLOWED_ATTRIBUTES, ALLOWED_STYLES, ALLOWED_TAGS from .models import Post, PostAttachment, Thread MAIL_REPLY_MARKER = _l("_____Write above this line to post_____") # logger = logging.getLogger(__package__) # Celery logger logger = get_task_logger(__name__) def init_app(app): global check_maildir if app.config["INCOMING_MAIL_USE_MAILDIR"]: make_task = periodic_task(run_every=crontab(minute="*")) check_maildir = make_task(check_maildir) @shared_task() def send_post_by_email(post_id):
def redirect_to_index(self): return redirect(self.index_url()) @property def template_kwargs(self): """ provides :attr:`form` to templates """ kw = super(ObjectView, self).template_kwargs kw['form'] = self.form return kw CANCEL_BUTTON = ButtonAction( 'form', 'cancel', title=_l(u'Cancel'), btn_class='default cancel' # .cancel: if jquery.validate is used it will ) # properly skip validation EDIT_BUTTON = ButtonAction('form', 'edit', btn_class='primary', title=_l(u'Save')) class ObjectEdit(ObjectView): """ Edit objects """ template = 'default/object_edit.html' decorators = (csrf.support_graceful_failure,) permission = WRITE
) from .forms import CommentForm bp = Blueprint('comments', __name__, url_prefix='/comments') def _default_comment_view(obj, obj_type, obj_id, **kwargs): entity = obj.entity return url_for(entity, _anchor='comment-{}'.format(obj.id)) @bp.record_once def register_default_view(state): state.app.default_view.register(Comment, _default_comment_view) COMMENT_BUTTON = ButtonAction('form', 'edit', btn_class='primary', title=_l(u'Post')) class BaseCommentView(object): Model = Comment Form = CommentForm #: commented entity entity = None def init_object(self, args, kwargs): args, kwargs = super(BaseCommentView, self).init_object(args, kwargs) entity_id = kwargs.pop('entity_id', None) if entity_id is not None: self.entity = Entity.query.get(entity_id)
def validate_end(self, field): if self.start.data > self.end.data: raise ValidationError(_l("End date/time must be after start"))
Form = GroupAdminForm pk = 'group_id' base_template = 'admin/_base.html' def index_url(self): return url_for('.groups') def view_url(self): return url_for('.groups_group', group_id=self.obj.id) # those buttons are made to have valid edit actions, but will not be shown in # edit forms: they must be availabe only during POST ADD_USER_BUTTON = ButtonAction('form', 'add_user', condition=lambda v: request.method == 'POST', title=_l(u'Add'), btn_class='primary') REMOVE_USER_BUTTON = ButtonAction('form', 'remove_user', condition=lambda v: request.method == 'POST', btn_class='danger', icon=FAIcon('times'), title="", ) class GroupView(GroupBase, views.ObjectView): template = 'admin/group_view.html' def breadcrumb(self): label = render_template_string(u'<em>{{ g }}</em>', g=self.obj.name) return BreadcrumbItem(label=label, url=u'', description=self.obj.name) @property
def redirect_to_index(self): return redirect(self.index_url()) @property def template_kwargs(self): """Provides :attr:`form` to templates.""" kw = super().template_kwargs kw["form"] = self.form return kw CANCEL_BUTTON = ButtonAction( "form", "cancel", title=_l("Cancel"), # .cancel: if jquery.validate is used it will properly skip validation btn_class="default cancel", ) EDIT_BUTTON = ButtonAction("form", "edit", btn_class="primary", title=_l("Save")) ADD_ANOTHER_BUTTON = ButtonAction( "form", "create_add_another", btn_class="primary", title=_l("Create and add another"), condition=lambda ctx: getattr(ctx["view"], "add_another_button", False), )
from .forms import AttachmentForm bp = Blueprint('attachments', __name__, url_prefix='/attachments') def _default_attachment_view(obj, obj_type, obj_id, **kwargs): entity = obj.entity return url_for(entity, _anchor='attachment-{}'.format(obj.id)) @bp.record_once def register_default_view(state): state.app.default_view.register(Attachment, _default_attachment_view) UPLOAD_BUTTON = ButtonAction('form', 'edit', btn_class='primary', title=_l(u'Send')) class BaseAttachmentView(object): """ Mixin for attachment views """ Model = Attachment Form = AttachmentForm #: owning entity entity = None def init_object(self, args, kwargs): args, kwargs = super(BaseAttachmentView, self).init_object(args, kwargs) entity_id = kwargs.pop('entity_id', None)
self.linked_group = form.linked_group.data or None if self.linked_group: self.linked_group = Group.query.get(int(self.linked_group)) del form.linked_group def after_populate_obj(self): self.obj.group = self.linked_group add_url( "/<string:community_id>/settings", view_func=CommunityEdit.as_view( "settings", view_endpoint=".community", message_success=_l("Community settings saved successfully."), ), ) class CommunityCreate(views.ObjectCreate, CommunityEdit): title = _l("Create community") decorators = views.ObjectCreate.decorators + (require_admin,) template = views.ObjectCreate.template base_template = views.ObjectCreate.base_template def breadcrumb(self): return BreadcrumbItem(label=_("Create new community")) def message_success(self): return _("Community %(name)s created successfully", name=self.obj.name)
@classmethod def assignable_roles(cls): return sorted(r for r in cls.__instances__.values() if r.assignable) class RoleType(UniqueNameType): """Store :class:`Role` Usage:: RoleType() """ Type = Role #: marker for role assigned to 'Anonymous' Anonymous = Role("anonymous", _l("role_anonymous"), assignable=False) #: marker for role assigned to 'Authenticated' Authenticated = Role("authenticated", _l("role_authenticated"), assignable=False) #: marker for `admin` role Admin = Role("admin", _l("role_administrator")) #: marker for `manager` role Manager = Role("manager", _l("role_manager"), assignable=False) Creator = Role("creator", assignable=False) Owner = Role("owner", assignable=False) Reader = Role("reader", assignable=False) Writer = Role("writer", assignable=False)
from .forms import CommentForm bp = Blueprint("comments", __name__, url_prefix="/comments") def _default_comment_view(obj, obj_type, obj_id, **kwargs): entity = obj.entity return url_for(entity, _anchor=f"comment-{obj.id}") @bp.record_once def register_default_view(state): state.app.default_view.register(Comment, _default_comment_view) COMMENT_BUTTON = ButtonAction("form", "edit", btn_class="primary", title=_l("Post")) class BaseCommentView: Model = Comment Form = CommentForm #: commented entity entity = None # type: Optional[Entity] def init_object(self, args, kwargs): args, kwargs = super().init_object(args, kwargs) entity_id = kwargs.pop("entity_id", None) if entity_id is not None: self.entity = Entity.query.get(entity_id)
""" from flask import Blueprint, url_for, request, redirect, abort, g from flask.ext.login import current_user from abilian.i18n import _, _l from abilian.core.extensions import db from abilian.core import signals from abilian.web.nav import NavItem, BreadcrumbItem, Endpoint from abilian.services.auth.service import user_menu from abilian.services.base import Service, ServiceState from .models import UserPreference user_menu.items.insert( 0, NavItem('user', 'preferences', title=_l(u'Preferences'), icon='cog', url=lambda context: request.url_root + 'preferences', condition=lambda context: not current_user.is_anonymous() )) class PreferenceState(ServiceState): panels = None blueprint = None blueprint_registered = False def __init__(self, *args, **kwargs): ServiceState.__init__(self, *args, **kwargs) self.panels = [] self.breadcrumb_items = {}