class Test: id = Integer(primary_key=True) properties = Json() name = JsonRelated(json_column='properties', keys=['name'], set_adapter=str, get_adapter=int)
class Resource(Declarations.Model.FuretUI.Menu, Declarations.Mixin.FuretUIMenu, Declarations.Mixin.FuretUIMenuParent): resource = Many2One(model=Declarations.Model.FuretUI.Resource, nullable=False) default = Boolean(default=False) tags = String() order_by = String() filters = Json(default={}) def check_acl(self): return self.resource.check_acl()
class Sub: id = Integer(primary_key=True) sequence = Integer(nullable=False, default=100) label = String(nullable=False) properties = Json(default={}) login_state = Selection(selections={ 'logged': 'Logged', 'unlogged': 'Unlogged', 'both': 'Logged and Unlogged', }, nullable=False, default='both') parent = Many2One(model=Declarations.Model.FuretUI.Menu, one2many="children") @classmethod def update_query_from_authenticated_id(cls, query, authenticated_userid): if authenticated_userid: query = query.filter(cls.login_state.in_(['logged', 'both'])) else: query = query.filter(cls.login_state.in_(['unlogged', 'both'])) return query @classmethod def get_for(cls, parent, authenticated_userid): # TODO raise if MENU_TYPE is None query = cls.query() query = query.filter(cls.parent == parent) query = cls.update_query_from_authenticated_id(query, authenticated_userid) query = query.order_by(cls.sequence) return [x.format_menu(authenticated_userid) for x in query] def format_menu(self, authenticated_userid): menu = {} if self.properties: menu.update(self.properties) menu.update({ 'name': self.id, 'label': self.label, }) return menu
class Test: id = Integer(primary_key=True) properties = Json() name = JsonRelated(json_column='properties', keys=['name'], set_adapter='fromint', get_adapter='toint') def fromint(self, value): if value: return str(value) return value def toint(self, value): if value: return int(value) return value
class Message(Declarations.Mixin.DramatiqMessageStatus): """Message model for dramatiq""" id = UUID(primary_key=True, nullable=False) updated_at = DateTime() message = Json(nullable=False) def __str__(self): return '<Message (id={self.id}, status={self.status.label})>'.format( self=self) @classmethod def insert(cls, *args, **kwargs): """Over write the insert to add the first history line""" self = super(Message, cls).insert(*args, **kwargs) self.updated_at = datetime.now() self.registry.Dramatiq.Message.History.insert( status=self.status, created_at=self.updated_at, message=self) return self @classmethod def get_instance_of(cls, message): """Called by the middleware to get the model instance of the message""" return cls.query().filter(cls.id == message.message_id).one_or_none() def update_status(self, status, error=None): """Called by the middleware to change the status and history""" logger.info("Update message %s status => %s", self, dict(self.STATUSES).get(status)) self.status = status self.updated_at = datetime.now() self.registry.Dramatiq.Message.History.insert( status=status, created_at=self.updated_at, message=self, error=error)
class Parameter: """Applications parameters. This Model is provided by ``anyblok-core`` to give applications a uniform way of specifying in-database configuration. It is a simple key/value representation, where values can be of any type that can be encoded as JSON. A simple access API is provided with the :meth:`get`, :meth:`set`, :meth:`is_exist` and further methods. """ key = String(primary_key=True) value = Json(nullable=False) multi = Boolean(default=False) @classmethod def set(cls, key, value): """ Insert or update parameter value for a key. .. note:: if the key already exists, the value will be updated :param str key: key to save :param value: value to save """ multi = False if not isinstance(value, dict): value = {'value': value} else: multi = True if cls.is_exist(key): param = cls.from_primary_keys(key=key) param.update(value=value, multi=multi) else: cls.insert(key=key, value=value, multi=multi) @classmethod def is_exist(cls, key): """ Check if one parameter exist for the key :param key: key to check :rtype: bool """ query = cls.query().filter(cls.key == key) return True if query.count() else False @classmethod def get(cls, key, default=NOT_PROVIDED): """ Return the value of the key :param key: key whose value to retrieve :param default: default value if key does not exists :return: associated value :rtype: anything JSON encodable :raises ParameterException: if the key doesn't exist and default is not set. """ if not cls.is_exist(key): if default is NOT_PROVIDED: raise ParameterException( "unexisting key %r" % key) return default param = cls.from_primary_keys(key=key) if param.multi: return param.value return param.value['value'] @classmethod def pop(cls, key): """Remove the given key and return the associated value. :param str key: the key to remove :return: the value before removal :rtype: any JSON encodable type :raises ParameterException: if the key wasn't present """ if not cls.is_exist(key): raise ParameterException( "unexisting key %r" % key) param = cls.from_primary_keys(key=key) if param.multi: res = param.value else: res = param.value['value'] param.delete() return res
class Document: DOCUMENT_TYPE = None uuid = UUID(primary_key=True, binary=False, nullable=False) version_number = Integer(primary_key=True, nullable=False) version = Function(fget="get_version") created_at = DateTime(default=datetime.now, nullable=False) historied_at = DateTime() data = Json(default=dict) file_added_at = DateTime() filename = String(size=256) contenttype = String() filesize = Integer() file = LargeBinary() hash = String(size=256) type = Selection(selections={ 'latest': 'Latest', 'history': 'History' }, nullable=False) previous_doc_uuid = UUID() previous_doc_version_number = Integer() previous_version = Function(fget="get_previous_version") next_version = Function(fget="get_next_version") previous_versions = Function(fget="get_previous_versions") @classmethod def get_file_fields(cls): return [ 'file', 'file_added_at', 'contenttype', 'filename', 'hash', 'filesize' ] def get_file(self): return self.to_dict(*self.get_file_fields()) def set_file(self, file_): self.file = file_ def get_version(self): return "V-%06d" % self.version_number def get_previous_version(self): Doc = self.anyblok.Attachment.Document query = Doc.query() query = query.filter(Doc.uuid == self.previous_doc_uuid) query = query.filter( Doc.version_number == self.previous_doc_version_number) return query.one_or_none() def get_next_version(self): Doc = self.anyblok.Attachment.Document query = Doc.query() query = query.filter(Doc.previous_doc_uuid == self.uuid) query = query.filter( Doc.previous_doc_version_number == self.version_number) return query.one_or_none() def get_previous_versions(self): res = [] current = self while current.previous_version: current = current.previous_version res.append(current) return res @classmethod def define_mapper_args(cls): mapper_args = super(Document, cls).define_mapper_args() if cls.__registry_name__ == 'Model.Attachment.Document': mapper_args.update({'polymorphic_on': cls.type}) mapper_args.update({'polymorphic_identity': cls.DOCUMENT_TYPE}) return mapper_args @classmethod def insert(cls, *args, **kwargs): if cls.__registry_name__ == 'Model.Attachment.Document': return cls.anyblok.Attachment.Document.Latest.insert( *args, **kwargs) return super(Document, cls).insert(*args, **kwargs) @classmethod def query(cls, *args, **kwargs): query = super(Document, cls).query(*args, **kwargs) if cls.__registry_name__ != 'Model.Attachment.Document': query = query.filter(cls.type == cls.DOCUMENT_TYPE) return query def has_file(self): if self.file: return True return False @classmethod def filter_has_not_file(cls): return cls.file == None # noqa
class Test: id = Integer(primary_key=True) properties = Json() name = JsonRelated(json_column='properties')
class Test: id = Integer(primary_key=True) properties = Json() name = JsonRelated(keys=['name'])
class Mapping: key = String(primary_key=True) model = String(primary_key=True, foreign_key=Model.System.Model.use('name')) primary_key = Json(nullable=False) blokname = String(label="Blok name", foreign_key=Model.System.Blok.use('name')) @hybrid_method def filter_by_model_and_key(self, model, key): """ SQLAlechemy hybrid method to filter by model and key :param model: model of the mapping :param key: external key of the mapping """ return (self.model == model) & (self.key == key) @hybrid_method def filter_by_model_and_keys(self, model, *keys): """ SQLAlechemy hybrid method to filter by model and key :param model: model of the mapping :param key: external key of the mapping """ return (self.model == model) & self.key.in_(keys) def remove_element(self, byquery=False): val = self.registry.get(self.model).from_primary_keys( **self.primary_key) logger.info("Remove entity for %r.%r: %r" % ( self.model, self.key, val)) val.delete(byquery=byquery, remove_mapping=False) @classmethod def multi_delete(cls, model, *keys, **kwargs): """ Delete all the keys for this model :param model: model of the mapping :param \*keys: list of the key :rtype: Boolean True if the mappings are removed """ mapping_only = kwargs.get('mapping_only', True) byquery = kwargs.get('byquery', False) query = cls.query() query = query.filter(cls.filter_by_model_and_keys(model, *keys)) count = query.count() if count: if not mapping_only: query.all().remove_element(byquery=byquery) query.delete(synchronize_session='fetch', remove_mapping=False) cls.registry.expire_all() return count return 0 @classmethod def delete(cls, model, key, mapping_only=True, byquery=False): """ Delete the key for this model :param model: model of the mapping :param key: string of the key :rtype: Boolean True if the mapping is removed """ query = cls.query() query = query.filter(cls.filter_by_model_and_key(model, key)) count = query.count() if count: if not mapping_only: query.one().remove_element(byquery=byquery) query.delete(remove_mapping=False) return count return 0 @classmethod def get_mapping_primary_keys(cls, model, key): """ return primary key for a model and an external key :param model: model of the mapping :param key: string of the key :rtype: dict primary key: value or None """ query = cls.query() query = query.filter(cls.filter_by_model_and_key(model, key)) if query.count(): pks = query.first().primary_key cls.check_primary_keys(model, *pks.keys()) return pks return None @classmethod def check_primary_keys(cls, model, *pks): """ check if the all the primary keys match with primary keys of the model :param model: model to check :param pks: list of the primary keys to check :exception: IOMappingCheckException """ for pk in cls.get_model(model).get_primary_keys(): if pk not in pks: raise IOMappingCheckException( "No primary key %r found in %r for model %r" % ( pk, pks, model)) @classmethod def set_primary_keys(cls, model, key, pks, raiseifexist=True, blokname=None): """ Add or update a mmping with a model and a external key :param model: model to check :param key: string of the key :param pks: dict of the primary key to save :param raiseifexist: boolean (True by default), if True and the entry exist then an exception is raised :param blokname: name of the blok where come from the mapping :exception: IOMappingSetException """ if cls.get_mapping_primary_keys(model, key): if raiseifexist: raise IOMappingSetException( "One value found for model %r and key %r" % (model, key)) cls.delete(model, key) if not pks: raise IOMappingSetException( "No value to save %r for model %r and key %r" % ( pks, model, key)) cls.check_primary_keys(model, *pks.keys()) vals = dict(model=model, key=key, primary_key=pks) if blokname is not None: vals['blokname'] = blokname return cls.insert(**vals) @classmethod def set(cls, key, instance, raiseifexist=True, blokname=None): """ Add or update a mmping with a model and a external key :param model: model to check :param key: string of the key :param instance: instance of the model to save :param raiseifexist: boolean (True by default), if True and the entry exist then an exception is raised :param blokname: name of the blok where come from the mapping :exception: IOMappingSetException """ pks = instance.to_primary_keys() return cls.set_primary_keys(instance.__registry_name__, key, pks, blokname=blokname, raiseifexist=raiseifexist) @classmethod def get(cls, model, key): """ return instance of the model with this external key :param model: model of the mapping :param key: string of the key :rtype: instance of the model """ pks = cls.get_mapping_primary_keys(model, key) if pks is None: return None return cls.get_model(model).from_primary_keys(**pks) @classmethod def get_from_model_and_primary_keys(cls, model, pks): query = cls.query().filter(cls.model == model) for mapping in query.all(): if mapping.primary_key == pks: return mapping return None @classmethod def get_from_entry(cls, entry): return cls.get_from_model_and_primary_keys( entry.__registry_name__, entry.to_primary_keys()) @classmethod def __get_models(cls, models): """Return models name if models is not: return all the existing model if models is a list of instance model, convert them :params models: list of model """ if models is None: models = cls.registry.System.Model.query().all().name elif not isinstance(models, (list, tuple)): models = [models] return [m.__registry_name__ if hasattr(m, '__registry_name__') else m for m in models] @classmethod def clean(cls, bloknames=None, models=None): """Clean all mapping with removed object linked:: Mapping.clean(bloknames=['My blok']) .. warning:: For filter only the no blokname:: Mapping.clean(bloknames=[None]) :params bloknames: filter by blok, keep the order to remove the mapping :params models: filter by model, keep the order to remove the mapping """ if bloknames is None: bloknames = cls.registry.System.Blok.query().all().name + [None] elif not isinstance(bloknames, (list, tuple)): bloknames = [bloknames] models = cls.__get_models(models) removed = 0 for blokname in bloknames: for model in models: query = cls.query().filter_by(blokname=blokname, model=model) for key in query.all().key: if cls.get(model, key) is None: cls.delete(model, key) removed += 1 return removed @classmethod def delete_for_blokname(cls, blokname, models=None, byquery=False): """Clean all mapping with removed object linked:: Mapping.clean('My blok') .. warning:: For filter only the no blokname:: Mapping.clean(None) :params blokname: filter by blok :params models: filter by model, keep the order to remove the mapping """ models = cls.__get_models(models) removed = 0 for model in models: query = cls.query().filter_by(blokname=blokname, model=model) for key in query.all().key: if cls.get(model, key): cls.delete(model, key, mapping_only=False, byquery=byquery) cls.registry.flush() removed += 1 return removed
class Authorization: """A model to store autorization rules (permissions for users against an Anyblok model or a Pyramid resource)""" id = Integer(primary_key=True) order = Integer(default=100, nullable=False) resource = String() model = String( foreign_key=Declarations.Model.System.Model.use('name').options( ondelete="cascade")) primary_keys = Json(default={}) filter = Json(default={}) # next step role = Many2One(model=User.Role, foreign_key_options={'ondelete': 'cascade'}) login = String(foreign_key=User.use('login').options(ondelete="cascade")) user = Many2One(model=User) perms = Json(default={}) perm_create = JsonRelated(json_column='perms', keys=['create']) perm_read = JsonRelated(json_column='perms', keys=['read']) perm_update = JsonRelated(json_column='perms', keys=['update']) perm_delete = JsonRelated(json_column='perms', keys=['delete']) @classmethod def get_acl_filter_model(cls): """Return the Model to use to check the permission""" return { 'User': cls.registry.User, 'Role': cls.registry.User.Role, } @classmethod def get_acl(cls, login, resource, params=None): """Return the Pyramid ACL in function of the resource and user :param login: str, login of the user :param resource: str, name of the resource """ # cache the method User = cls.registry.User Role = cls.registry.User.Role query = cls.query() query = query.filter( or_(cls.resource == resource, cls.model == resource)) query = query.order_by(cls.order) Q1 = query.filter(cls.login == login) Q2 = query.join(cls.role).filter(Role.name.in_(User.get_roles(login))) res = [] for query in (Q1, Q2): for self in query.all(): allow_perms = [] deny_perms = [] perms = list((self.perms or {}).keys()) perms.sort() for perm in perms: p = self.perms[perm] query = User.query() query = query.filter(User.login == login) query = query.join(User.roles) if self.filter: query = query.condition_filter( self.filter, cls.get_acl_filter_model()) if 'condition' in p: query = query.condition_filter( p['condition'], cls.get_acl_filter_model()) ismatched = True if query.count() else False if p.get('matched' if ismatched else 'unmatched') is True: allow_perms.append(perm) elif (p.get('matched' if ismatched else 'unmatched') is False): deny_perms.append(perm) if len(allow_perms): res.append((Allow, login, allow_perms)) if len(deny_perms): res.append((Deny, login, deny_perms)) res.append((Deny, login, ALL_PERMISSIONS)) return res @classmethod def before_insert_orm_event(cls, mapper, connection, target): target.check_validity() @classmethod def before_update_orm_event(cls, mapper, connection, target): target.check_validity() def check_validity(self): """When creating or updating a User.Authorization, check that all rules objects exists or return an AuthorizationValidationException :exception: AuthorizationValidationException """ if not (self.role or self.login or self.user or self.role_name): raise AuthorizationValidationException( "No role and login to apply in the authorization (%s)" % self) if not (self.resource or self.model): raise AuthorizationValidationException( "No resource and model to apply in the authorization (%s)" % self) if not self.model and self.primary_keys: raise AuthorizationValidationException( "Primary keys without model to apply in the authorization " "(%s)" % self)
class Authorization: """A model to store autorization rules (permissions for users against an Anyblok model or a Pyramid resource)""" id = Integer(primary_key=True) code = String(nullable=True, unique=True, size=256) order = Integer(default=100, nullable=False) resource = String() model = String( foreign_key=Declarations.Model.System.Model.use('name').options( ondelete="cascade"), size=256, ) primary_keys = Json(default={}) filter = Json(default={}) # next step role = Many2One( model=Pyramid.Role, foreign_key_options={'ondelete': 'cascade'}) login = String( foreign_key=Pyramid.User.use('login').options(ondelete="cascade")) user = Many2One(model=Pyramid.User) perms = Json(default={}) perm_create = JsonRelated(json_column='perms', keys=['create']) perm_read = JsonRelated(json_column='perms', keys=['read']) perm_update = JsonRelated(json_column='perms', keys=['update']) perm_delete = JsonRelated(json_column='perms', keys=['delete']) @classmethod def get_acl_filter_model(cls): """Return the Model to use to check the permission""" return { 'User': cls.anyblok.Pyramid.User, 'Role': cls.anyblok.Pyramid.Role, } @classmethod def get_acl(cls, login, resource, params=None): """Return the Pyramid ACL in function of the resource and user :param login: str, login of the user :param resource: str, name of the resource """ # cache the method User = cls.anyblok.Pyramid.User Role = cls.anyblok.Pyramid.Role query = cls.query() query = query.filter( or_(cls.resource == resource, cls.model == resource)) query = query.order_by(cls.order) Q1 = query.filter(cls.login == login) Q2 = query.join(cls.role).filter(Role.name.in_(User.get_roles(login))) res = [] for query in (Q1, Q2): for self in query.all(): allow_perms = [] deny_perms = [] perms = list((self.perms or {}).keys()) perms.sort() for perm in perms: p = self.perms[perm] query = User.query() query = query.filter(User.login == login) query = query.join(User.roles) if self.filter: query = query.condition_filter( self.filter, cls.get_acl_filter_model() ) if 'condition' in p: query = query.condition_filter( p['condition'], cls.get_acl_filter_model() ) ismatched = True if query.count() else False if p.get('matched' if ismatched else 'unmatched') is True: allow_perms.append(perm) elif ( p.get('matched' if ismatched else 'unmatched') is False ): deny_perms.append(perm) if len(allow_perms): res.append((Allow, login, allow_perms)) if len(deny_perms): res.append((Deny, login, deny_perms)) res.append((Deny, login, ALL_PERMISSIONS)) return res @classmethod def check_acl(cls, login, resource, type_): """Return the Pyramid ACL in function of the resource and user :param login: str, login of the user :param resource: str, name of the resource :param type: str, name of the action """ # cache the method User = cls.anyblok.Pyramid.User Role = cls.anyblok.Pyramid.Role query = cls.query() query = query.filter( or_(cls.resource == resource, cls.model == resource)) query = query.order_by(cls.order) Q1 = query.filter(cls.login == login) Q2 = query.join(cls.role).filter(Role.name.in_(User.get_roles(login))) for query in (Q1, Q2): for self in query.all(): perms = list((self.perms or {}).keys()) if type_ not in perms: continue p = self.perms[type_] query = User.query() query = query.filter(User.login == login) query = query.join(User.roles, isouter=True) if self.filter: query = query.condition_filter( self.filter, cls.get_acl_filter_model() ) if 'condition' in p: query = query.condition_filter( p['condition'], cls.get_acl_filter_model() ) ismatched = True if query.count() else False if p.get('matched' if ismatched else 'unmatched') is True: return True elif ( p.get('matched' if ismatched else 'unmatched') is False ): return False return False @classmethod def before_insert_orm_event(cls, mapper, connection, target): target.check_validity() @classmethod def before_update_orm_event(cls, mapper, connection, target): target.check_validity() def check_validity(self): """When creating or updating a User.Authorization, check that all rules objects exists or return an AuthorizationValidationException :exception: AuthorizationValidationException """ if not (self.role or self.login or self.user or self.role_name): raise AuthorizationValidationException( "No role and login to apply in the authorization (%s)" % self) if not (self.resource or self.model): raise AuthorizationValidationException( "No resource and model to apply in the authorization (%s)" % self) if not self.model and self.primary_keys: raise AuthorizationValidationException( "Primary keys without model to apply in the authorization " "(%s)" % self) @classmethod def ensure_exists( cls, code, **kwargs ): """Ensure role's authorization is present :param code: String, authorization code. :param kwargs: authorization fields """ if not kwargs: kwargs = {} # pragma: no cover # pv: at some point adding index on this criteria may boost things # while setting authorizations authz = ( cls.anyblok.Pyramid.Authorization.query() .filter_by( code=code, ) .one_or_none() ) if not authz: authz = cls.anyblok.Pyramid.Authorization.insert( code=code, **kwargs ) else: authz.update(**kwargs) jsonfields = {"perms", "primary_keys", "filter"} perms_related = { "perm_create", "perm_read", "perm_update", "perm_delete" } modified = (jsonfields | perms_related) & set(kwargs.keys()) if modified: if perms_related & modified: modified = modified | {"perms"} authz.flag_modified(*(jsonfields & modified)) return authz
class Job: """The job is an execution of an instance of task""" STATUS_NEW = "new" STATUS_WAITING = "waiting" STATUS_RUNNING = "running" STATUS_FAILED = "failed" STATUS_DONE = "done" STATUSES = [ (STATUS_NEW, "New"), (STATUS_WAITING, "Waiting"), (STATUS_RUNNING, "Running"), (STATUS_FAILED, "Failed"), (STATUS_DONE, "Done"), ] uuid = UUID(primary_key=True, nullable=False, default=uuid1, binary=False) create_at = DateTime(default=datetime.now, nullable=False) update_at = DateTime(default=datetime.now, nullable=False, auto_update=True) run_at = DateTime() data = Json(nullable=False) status = Selection(selections=STATUSES, default=STATUS_NEW, nullable=False) task = Many2One(model=Declarations.Model.Dramatiq.Task, nullable=False) main_job = Many2One(model='Model.Dramatiq.Job', one2many="sub_jobs") error = Text() @actor_send() def run(cls, job_uuid=None): """dramatiq actor to execute a specific task""" autocommit = EnvironmentManager.get('job_autocommit', True) try: job = cls.query().filter(cls.uuid == job_uuid).one() job.status = cls.STATUS_RUNNING if autocommit: cls.registry.commit() # use to save the state job.task.run(job) if autocommit: cls.registry.commit() # use to save the state except Exception as e: logger.error(str(e)) cls.registry.rollback() job.status = cls.STATUS_FAILED job.error = str(e) if autocommit: cls.registry.commit() # use to save the state raise e def lock(self): """lock the job to be sure that only one thread execute the run_next""" Job = self.__class__ while True: try: Job.query().with_for_update(nowait=True).filter( Job.uuid == self.uuid).one() break except OperationalError: sleep(1) def call_main_job(self): """Call the main job if exist to do the next action of the main job""" if self.main_job: self.main_job.lock() self.main_job.task.run_next(self.main_job)
class Menu: MENU_TYPE = None id = Integer(primary_key=True) sequence = Integer(nullable=False, default=100) label = String(nullable=False) component = String() properties = Json(default={}) login_state = Selection(selections={ 'logged': 'Logged', 'unlogged': 'Unlogged', 'both': 'Logged and Unlogged', }, nullable=False) label_is_props = String() type = Selection(selections={ 'user': '******', 'spaces': 'Space', 'spaceiMenus': 'Space menus' }, nullable=False) @classmethod def define_mapper_args(cls): mapper_args = super(Menu, cls).define_mapper_args() if cls.__registry_name__ == 'Model.FuretUI.Menu': mapper_args.update({'polymorphic_on': cls.type}) mapper_args.update({'polymorphic_identity': cls.MENU_TYPE}) return mapper_args @classmethod def query(cls, *args, **kwargs): query = super(Menu, cls).query(*args, **kwargs) if cls.__registry_name__ != 'Model.FuretUI.Menu': query = query.filter(cls.type == cls.MENU_TYPE) return query @classmethod def update_query_from_authenticated_id(cls, query, authenticated_userid): query = query.order_by(cls.sequence) if authenticated_userid: query = query.filter(cls.login_state.in_(['logged', 'both'])) else: query = query.filter(cls.login_state.in_(['unlogged', 'both'])) return query @classmethod def get_for(cls, authenticated_userid): # TODO raise if MENU_TYPE is None query = cls.query() query = cls.update_query_from_authenticated_id(query, authenticated_userid) return [x.format_menu(authenticated_userid) for x in query] def format_menu(self, authenticated_userid): menu = {} if self.properties: menu.update(self.properties) menu.update({ 'name': self.id, 'label': self.label, }) if self.component: menu['component'] = self.component if self.label_is_props: if 'props' not in menu: menu['props'] = {} menu['props'][self.label_is_props] = self.label children = self.registry.FuretUI.Menu.Sub.get_for( self, authenticated_userid) if children: menu['props']['children'] = children return menu
class Jinja(Mixin.WkHtml2Pdf, Attachment.Template): """Jinja templating""" TYPE = TYPE uuid = UUID(primary_key=True, nullable=False, binary=False, foreign_key=Attachment.Template.use('uuid').options( ondelete='cascade')) jinja_paths = Text(nullable=False) contenttype = Selection(selections={ 'text/html': 'HTML', 'application/pdf': 'PDF', }, default='application/pdf', nullable=False) options = Json(default={}, nullable=False) wkhtml2pdf_configuration = Many2One( model=Declarations.Model.Attachment.WkHtml2Pdf, nullable=True) def check_flush_validity(self): super(Jinja, self).check_flush_validity() if self.contenttype == 'application/pdf': if not self.wkhtml2pdf_configuration: raise TemplateJinjaException( "No WkHtml2Pdf configuration for %r" % self) def update_document(self, document, file_, data): super(Jinja, self).update_document(document, file_, data) document.contenttype = self.contenttype def render(self, data): if self.contenttype == 'text/html': return self.render_html(data) return self.render_pdf(data) def render_html(self, data): jinja_paths = [] if self.jinja_paths: for jinja_path in self.jinja_paths.split(','): jinja_path = format_path(jinja_path.strip()) if not os.path.isdir(jinja_path): raise TemplateJinjaException("%r must be a folder" % jinja_path) jinja_paths.append(jinja_path) jinja_env = SandboxedEnvironment( loader=jinja2.FileSystemLoader(jinja_paths), undefined=jinja2.StrictUndefined, ) parser = self.get_parser() if not hasattr(parser, 'serialize_jinja_options'): raise TemplateJinjaException( ("The parser %r must declare a method " "'serialize_jinja_options' for %r") % (parser, self)) options = self.get_parser().serialize_jinja_options(self.options) return jinja_env.from_string(self.get_template()).render( data=data, str=str, **options).encode('utf-8') def render_pdf(self, data): html_content = self.render_html(data) return self.wkhtml2pdf(html_content)
class Parameter: """System Parameter""" key = String(primary_key=True) value = Json(nullable=False) multi = Boolean(default=False) @classmethod def set(cls, key, value): """ Insert or Update parameter for the key :param key: key to save :param value: value to save """ multi = False if not isinstance(value, dict): value = {'value': value} else: multi = True if cls.is_exist(key): param = cls.from_primary_keys(key=key) param.update(value=value, multi=multi) else: cls.insert(key=key, value=value, multi=multi) @classmethod def is_exist(cls, key): """ Check if one parameter exist for the key :param key: key to check :rtype: Boolean, True if exist """ query = cls.query().filter(cls.key == key) return True if query.count() else False @classmethod def get(cls, key): """ Return the value of the key :param key: key to check :rtype: return value :exception: ExceptionParameter """ if not cls.is_exist(key): raise ParameterException("unexisting key %r" % key) param = cls.from_primary_keys(key=key) if param.multi: return param.value return param.value['value'] @classmethod def pop(cls, key): """Remove return the value of the key :param key: key to check :rtype: return value :exception: ExceptionParameter """ if not cls.is_exist(key): raise ParameterException("unexisting key %r" % key) param = cls.from_primary_keys(key=key) if param.multi: res = param.value else: res = param.value['value'] param.delete() return res