class ConfigGroups(OrderedFolder): class_id = 'config-groups' class_title = MSG(u'User Groups') class_description = MSG(u'Manage user groups.') class_icon48 = '/ui/ikaaro/icons/48x48/groups.png' # Configuration config_name = 'groups' config_group = 'access' property_name = 'groups' # Views class_views = ['browse_content', 'add_group', 'edit', 'commit_log'] browse_content = BrowseGroups() add_group = NewResource_Local(title=MSG(u'Add group')) default_groups = [('admins', { 'en': u'Admins' }), ('reviewers', { 'en': u'Reviewers' }), ('members', { 'en': u'Members' })] def init_resource(self, **kw): super(ConfigGroups, self).init_resource(**kw) # Add default groups for name, title in self.default_groups: self.make_resource(name, Group, title=title) def get_document_types(self): return [Group]
class ConfigModels(Folder): class_id = 'config-models' class_title = MSG(u'Content models') class_description = MSG(u'Define new types of content resources.') # Configuration config_name = 'models' config_group = 'content' # Views class_views = ['browse_content', 'add_model', 'edit', 'commit_log'] browse_content = ConfigModels_Browse add_model = NewResource_Local(title=MSG(u'Add model')) def get_document_types(self): return [Model]
class ModelField_Choices(OrderedFolder, ModelField_Base): class_id = 'model-field-choices' class_title = MSG(u'Choices field') # Fields choices_widget = ChoicesWidget_Field(title=MSG(u'Widget to use'), required=True) def get_document_types(self): return [Choice] # API def build_field(self): options = [{ 'name': x.name, 'value': x.get_title() } for x in self.get_resources_in_order()] field = Select_Field(widget=self.get_widget()) field_kw = self.get_field_kw(field) return field(options=options, **field_kw) def get_widget(self): if self.get_value('choices_widget') == 'radio-checkbox': if self.get_value('multiple'): return CheckboxWidget return RadioWidget return SelectWidget # Views class_views = ['browse_content', 'add_choice', 'edit', 'commit_log'] browse_content = ModelField_Choices_Browse add_choice = NewResource_Local(title=MSG(u'Add choice')) _fields = ModelField_Base._fields + ['choices_widget'] new_instance = ModelField_Base.new_instance(fields=_fields) edit = AutoEdit(fields=_fields)
class Model(OrderedFolder): class_id = '-model' class_title = MSG(u'Base model') class_description = MSG(u'...') # Fields title = Folder.title(required=True) # Views class_views = ['browse_content', 'add_field', 'edit', 'commit_log'] browse_content = Model_Browse new_instance = Model_NewInstance add_field = NewResource_Local(title=MSG(u'Add field')) # Order configuration allow_to_unorder_items = True def get_document_types(self): return [ModelField_Standard, ModelField_Choices] @property def __fixed_handlers__(self): return [] # XXX To allow ordering, resources should not be fixed handlers #return [ x.name for x in self.get_resources() # if isinstance(x, ModelField_Inherited) ] def get_model_fields(self): """Return the resources that represent a field. """ return [ x for x in self.get_resources_in_order() if isinstance(x, ModelField_Base) ] def build_resource_class(self): # bases base_class = self.base_class bases = (base_class, ) # dict title = self.get_value('title') class_dict = { 'class_id': str(self.abspath), 'class_title': MSG(title) if title else base_class.class_title, 'fields_soft': True, # dynamic classes are fragile } fields = [] for field_name in base_class.fields: field = base_class.get_field(field_name) if field and field.readonly: fields.append(field_name) for resource in self.get_model_fields(): field_name = resource.name if not isinstance(resource, ModelField_Inherited): class_dict[field_name] = resource.build_field() fields.append(field_name) class_dict['fields'] = fields return type(self.name, bases, class_dict) def set_value(self, name, value, language=None): has_changed = super(Model, self).set_value(name, value, language) if has_changed: class_id = str(self.abspath) self.database._resources_registry.pop(class_id, None) return has_changed
class ConfigAccess(Folder): class_id = 'config-access' class_version = '20110606' class_title = MSG(u'Access Control') class_description = MSG(u'Choose the security policy.') class_icon48 = 'icons/48x48/lock.png' # Configuration config_name = 'access' config_group = 'access' # Initialization _everything = freeze({'path': '/', 'path_depth': '*'}) default_rules = [ # Everybody can see the theme ('everybody', 'view', { 'path': '/config/theme', 'path_depth': '*' }), # Authenticated users can see any content ('authenticated', 'view', _everything), # Members can add new content and edit private content ('/config/groups/members', 'add', _everything), ('/config/groups/members', 'edit', _everything), # Reviewers can add new content, edit any content and publish ('/config/groups/reviewers', 'add', _everything), ('/config/groups/reviewers', 'edit', _everything), ('/config/groups/reviewers', 'share', _everything) ] def init_resource(self, **kw): super(ConfigAccess, self).init_resource(**kw) # Access rules rules = self.default_rules for group, permission, kw in rules: rule = self.make_resource(None, AccessRule, group=group) rule.set_value('permission', permission) for key in kw: rule.set_value('search_%s' % key, kw[key]) # API def _get_user_groups(self, user): user_groups = set(['everybody']) if user: user_groups.add('authenticated') user_groups.update(user.get_value('groups')) return user_groups, '/config/groups/admins' in user_groups def get_search_query(self, user, permission, class_id=None): # Special case: admins can see everything user_groups, is_admin = self._get_user_groups(user) if is_admin: return AllQuery() # 1. Back-office access rules rules_query = OrQuery() for rule in self.get_resources(): if rule.get_value('permission') != permission: continue if rule.get_value('group') not in user_groups: continue if permission == 'add': r_format = rule.get_value('search_format') if class_id and r_format and class_id != r_format: continue rules_query.append(rule.get_search_query()) # Case: anonymous if not user: return AndQuery(rules_query, PhraseQuery('share', 'everybody')) # Case: authenticated share_query = OrQuery(*[PhraseQuery('share', x) for x in user_groups]) share_query.append(PhraseQuery('share', str(user.abspath))) query = AndQuery(rules_query, share_query) if permission != 'share': return OrQuery(PhraseQuery('owner', str(user.abspath)), query) return query def has_permission(self, user, permission, resource, class_id=None): # The query query = AndQuery(self.get_search_query(user, permission, class_id), PhraseQuery('abspath', str(resource.abspath))) # Search results = get_context().search(query) return len(results) > 0 def get_document_types(self): return [AccessRule] # Views class_views = ['browse_content', 'add_rule', 'edit', 'commit_log'] browse_content = ConfigAccess_Browse add_rule = NewResource_Local(title=MSG(u'Add rule'))