''' Resources (sub) package, used to connect URLs to views ''' import deform from pyramid.security import Allow, Authenticated, Everyone, DENY_ALL from ordr.models.account import Token, TokenSubject from ordr.schemas.account import ( ChangePasswordSchema, RegistrationSchema, ResetPasswordSchema, SettingsSchema ) from .helpers import BaseChildResource class RegistrationTokenResource(BaseChildResource): ''' Resource for vaildating a new registered user's email :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = 'registration' def __acl__(self): ''' access controll list for the resource ''' return [(Allow, Everyone, 'register'), DENY_ALL] class RegistrationResource(BaseChildResource): ''' The resource for new user registration :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = 'registration' def __acl__(self): ''' access controll list for the resource ''' return [(Allow, Everyone, 'register'), DENY_ALL] def __getitem__(self, key): ''' returns a resource for a valid registration token ''' token = Token.retrieve(self.request, key, TokenSubject.REGISTRATION) if token is None: raise KeyError(f'Token {key} not found') return RegistrationTokenResource(name=key, parent=self, model=token) def get_registration_form(self, **kwargs): ''' returns the registration form''' settings = { 'buttons': ( deform.Button(name='create', title='Create Account'), deform.Button( title='Cancel', type='link', value=self.request.resource_url(self.request.root), css_class='btn btn-outline-secondary' ) ), } settings.update(kwargs) return self._prepare_form(RegistrationSchema, **settings) class PasswordResetTokenResource(BaseChildResource): ''' Resource for the reset password link :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = None def __acl__(self): ''' access controll list for the resource ''' return [(Allow, Everyone, 'reset'), DENY_ALL] def get_reset_form(self, **kwargs): ''' returns password reset form ''' settings = { 'buttons': ( deform.Button(name='change', title='Set New Password'), deform.Button(name='cancel', title='Cancel'), ) } settings.update(kwargs) return self._prepare_form(ResetPasswordSchema, **settings) class PasswordResetResource(BaseChildResource): ''' The resource for resetting a forgotten password :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = None def __acl__(self): ''' access controll list for the resource ''' return [(Allow, Everyone, 'reset'), DENY_ALL] def __getitem__(self, key): ''' returns a resource for a valid reset password token ''' token = Token.retrieve(self.request, key, TokenSubject.RESET_PASSWORD) if token is None: raise KeyError(f'Token {key} not found') return PasswordResetTokenResource(name=key, parent=self, model=token) class ChangeEmailTokenResource(BaseChildResource): ''' Resource for changing the email address :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = None def __acl__(self): ''' access controll list for the resource ''' return [(Allow, self.model.owner.principal, 'edit'), DENY_ALL] class AccountResource(BaseChildResource): ''' The resource for changing account settings and passwords :param pyramid.request.Request request: the current request object :param str name: the name of the resource :param parent: the parent resouce ''' nav_active = None def __init__(self, name, parent, model=None): ''' Create the resource :param str name: the name of the resource :param parent: the parent resouce :param model: optional data model for the resource If model is not set, the current user will be used ''' super().__init__(name, parent, model) self.model = model or getattr(self.request, 'user', None) def __acl__(self): ''' access controll list for the resource ''' return [ (Allow, Everyone, 'view'), (Allow, Everyone, 'login'), (Allow, Everyone, 'logout'), (Allow, Everyone, 'register'), (Allow, Everyone, 'reset'), (Allow, Authenticated, 'edit'), DENY_ALL ] def __getitem__(self, key): ''' returns a resource for child resource ''' # static child resources map = { 'register': RegistrationResource, 'forgot': PasswordResetResource, } if key in map: child_class = map[key] return child_class(name=key, parent=self) # change email verification token = Token.retrieve(self.request, key, TokenSubject.CHANGE_EMAIL) if token is None: raise KeyError(f'Token {key} not found') return ChangeEmailTokenResource(name=key, parent=self, model=token) def get_settings_form(self, **kwargs): ''' returns the account settings form ''' settings = { 'buttons': ( deform.Button(name='change', title='Change Settings'), deform.Button(name='cancel', title='Cancel'), ) } settings.update(kwargs) return self._prepare_form(SettingsSchema, **settings) def get_password_form(self, **kwargs): ''' returns the change password form ''' settings = { 'buttons': ( deform.Button(name='change', title='Change Password'), deform.Button(name='cancel', title='Cancel'), ) } settings.update(kwargs) return self._prepare_form(ChangePasswordSchema, **settings)