def process_user_data(self, data): id = data[self.user_data_id_field] email = data.get(self.user_data_email_field) user = ( User.get_instance(**{self.user_identifier: id}) or ( email and User.get_instance(email = email) ) ) if user is None: user = User() if not user.get(self.user_identifier): user.set(self.user_identifier, id) if not user.email: user.email = email first_login = True else: first_login = False self.user_authenticated( user = user, data = data, first_login = first_login ) user.insert() return user
def test_delete(self): from datetime import datetime from woost.models import (Item, User, ChangeSet, changeset_context) author = User() author.insert() item = Item() item.insert() with changeset_context(author) as changeset: item.delete() assert list(ChangeSet.select()) == [changeset] assert changeset.author is author assert isinstance(changeset.date, datetime) assert changeset.changes.keys() == [item.id] change = changeset.changes[item.id] assert change.target is item assert change.action == "delete" assert change.changeset is changeset assert item.changes == [change] assert not item.id in Item.index
def test_permission_acquisition(self): from woost.models import (User, Role, ReadPermission) R = lambda **kwargs: Role(permissions=[ReadPermission()], **kwargs) r1 = R() r2 = R() r3 = R() r4 = R(base_roles=[r3]) r5 = R(base_roles=[r2, r4]) self.everybody_role.permissions.append(ReadPermission()) self.authenticated_role.permissions.append(ReadPermission()) user = User() user.roles = [r1, r5] print list(user.iter_permissions()) assert list(user.iter_permissions()) == [ r1.permissions[0], r5.permissions[0], r2.permissions[0], r4.permissions[0], r3.permissions[0], self.authenticated_role.permissions[0], self.everybody_role.permissions[0] ]
def _load(self): from woost.controllers.notifications import notify_user from woost.controllers.backoffice.basebackofficecontroller import \ BaseBackOfficeController from woost.controllers.backoffice.itemcontroller import \ ItemController from woost.extensions.mailer import ( sendemailaction, createmailingaction, strings ) from woost.extensions.mailer.mailing import Mailing, \ RunningMailingError from woost.extensions.mailer.sendemailcontroller import \ SendEmailController ItemController.send_email = SendEmailController Template.add_member( schema.Boolean( "per_user_customizable", default = False, listed_by_default = False ) ) Template.members_order.append("per_user_customizable") User.add_member( schema.Collection( "mailingLists", items = "woost.extensions.mailer.mailinglist.MailingList", bidirectional = True, listed_by_default = False ) ) @when(BaseBackOfficeController.exception_raised) def handle_exception_raised(event): if isinstance( event.exception, RunningMailingError ): notify_user(translations(event.exception), "error") raise cherrypy.HTTPRedirect(event.source.contextual_uri()) # Disable interactive features from rendered pages when rendering # static content from woost.controllers.cmscontroller import CMSController @when(CMSController.producing_output) def disable_user_controls(event): if context.get("sending_email", False): event.output["show_user_controls"] = False
def user_parser(value): try: try: id = int(value) except ValueError: return User.require_instance(email=value) else: return User.require_instance(id) except: pass raise ArgumentTypeError(f"{id} is not a valid user ID or email")
class BaseTestCase(TempStorageMixin, TestCase): def setUp(self): from woost import app from woost.models import Configuration, User, Role from woost.models.trigger import get_triggers_enabled, set_triggers_enabled from woost.controllers.installer import Installer self.__prev_installation_id = app.installation_id self.__prev_triggers_enabled = get_triggers_enabled() app.installation_id = "TEST" set_triggers_enabled(False) TempStorageMixin.setUp(self) app.root = os.path.join(self._temp_dir, "test_project") installer = Installer() installer.create_project({"project_path": app.root}) # Configuration self.config = Configuration(qname = "woost.configuration") self.config.insert() # Roles and users self.anonymous_role = Role(qname = "woost.anonymous") self.anonymous_role.insert() self.anonymous_user = User(qname = "woost.anonymous_user") self.anonymous_user.roles.append(self.anonymous_role) self.anonymous_user.insert() self.everybody_role = Role(qname = "woost.everybody") self.everybody_role.insert() self.authenticated_role = Role(qname = "woost.authenticated") self.authenticated_role.insert() set_triggers_enabled(True) def tearDown(self): from woost import app from woost.models import staticpublication from woost.models.trigger import set_triggers_enabled app.installation_id = self.__prev_installation_id set_triggers_enabled(self.__prev_triggers_enabled) TempStorageMixin.tearDown(self)
def test_modify(self): from time import sleep from datetime import datetime from woost.models import (Document, User, ChangeSet, changeset_context) author = User() author.insert() with changeset_context(author) as creation: item = Document() item.set("title", u"Foo!", "en") item.resource_type = u"text/foo" item.hidden = True item.insert() # Make sure creation_time and last_update_time don't match sleep(0.1) with changeset_context(author) as modification: item.set("title", u"Bar!", "en") item.resource_type = u"text/bar" item.hidden = True assert list(ChangeSet.select()) == [creation, modification] assert modification.author is author assert isinstance(modification.date, datetime) assert modification.changes.keys() == [item.id] change = modification.changes[item.id] assert change.target is item assert change.action == "modify" assert change.changeset is modification assert change.changed_members == set(["title", "resource_type"]) assert item.changes == [creation.changes[item.id], change] for key in "id", "changes", "creation_time", "last_update_time": assert not key in change.item_state assert change.item_state["title"] == {"en": u"Bar!"} assert change.item_state["resource_type"] == u"text/bar" assert change.item_state["hidden"] == True assert change.item_state["translation_enabled"] == \ {"en": item.get("translation_enabled", "en")} assert item.author is author assert item.creation_time assert item.last_update_time assert not item.creation_time == item.last_update_time
def test_user(self): from woost.models import ContentTrigger, Item, Role, User r1 = Role() r2 = Role() r3 = Role(base_roles=[r2]) u1 = User(roles=[r1]) u2 = User(roles=[r2]) u3 = User(roles=[r3]) self.assert_match(ContentTrigger(matching_roles=[r2]), (Item(), u2, {}, True), (Item(), u3, {}, True), (Item(), None, {}, False), (Item(), u1, {}, False))
def setUp(self): from cocktail.persistence import datastore from woost.models import (triggerresponse, TriggerResponse, User, set_current_user) BaseTestCase.setUp(self) class TestTriggerResponse(TriggerResponse): def __init__(self, response_log, *args, **kwargs): TriggerResponse.__init__(self, *args, **kwargs) self.response_log = response_log def execute(self, items, user, batch=False, **context): self.response_log.append({ "trigger": self.trigger, "items": items, "user": user, "batch": batch, "context": context }) self.TestTriggerResponse = TestTriggerResponse # ZODB requires classes to be accessible, so TestTriggerResponse is # added to the same module of its base class: triggerresponse.TestTriggerResponse = TestTriggerResponse TestTriggerResponse.__module__ = TriggerResponse.__module__ self.user = User() set_current_user(self.user) datastore.commit()
def import_woost2_data(e): from woost.models import Configuration, User config = Configuration.instance try: providers = config._identity_providers except AttributeError: pass else: del config._identity_providers for provider in providers: del provider._Configuration_identity_providers config.x_identity_providers = list(providers) for user in User.select(): for provider in "facebook", "google": key = provider + "_user_id" old_key = "_" + key new_key = "x_identity_" + key try: value = getattr(user, old_key) except AttributeError: pass else: delattr(user, old_key) setattr(user, new_key, value)
def submit(self): mailing = self.context["cms_item"] if self.mailer_action == "test": # Send a test email mailing._v_template_values = { "cms": self.context["cms"], "base_url": unicode(Location.get_current_host()).rstrip("/") } test_email = self.params.read(schema.String("test_email")) # Create a fake user receiver = User(email = test_email) set_language(mailing.language) mailing.send_message(self.smtp_server, receiver) elif self.mailer_action == "send": # Send the mailing self.task_id = mailing.id template_values = { "cms": self.context["cms"], "base_url": unicode(Location.get_current_host()).rstrip("/") } mailing.send(self.smtp_server, template_values, self.context.copy()) else: EditController.submit(self)
def login(self, identifier, password): """Attempts to establish a new user session, using the given user credentials. @param identifier: An identifier matching a single user in the database. Matches are made against the field indicated by the L{identifier_field>} attribute. @type identifier: str @param password: The unencrypted password for the user. @type: str @return: The authenticated user. @rtype: L{User<woost.models.user.User>} @raise L{AuthenticationFailedError}: Raised if the provided user credentials are invalid. """ identifier = identifier.strip() if identifier and password: params = {self.identifier_field.name: identifier} user = User.get_instance(**params) if user and user.enabled and user.test_password(password): self.set_user_session(user) return user raise AuthenticationFailedError(identifier)
def test_permission_expression(self): from woost.models import (Item, Publishable, User, ReadPermission, PermissionExpression) self.everybody_role.permissions.append( ReadPermission(matching_items={ "type": "woost.models.publishable.Publishable" }, authorized=True)) i1 = Item() i2 = Item() d1 = Publishable() d2 = Publishable() i1.insert() i2.insert() d1.insert() d2.insert() results = set( Item.select( filters=[PermissionExpression(User(), ReadPermission)])) assert results == set([d1, d2])
def _create_ecommerceorder_completed_trigger(self): from woost.extensions.ecommerce.ecommerceordercompletedtrigger import \ ECommerceOrderCompletedTrigger trigger = ECommerceOrderCompletedTrigger( ) trigger.qname = \ "woost.extensions.ecommerce.ecommerceorder_completed_trigger" self.__translate_field(trigger, "title") Configuration.instance.triggers.append(trigger) trigger.condition = "target.customer and not target.customer.anonymous and target.customer.email" trigger.matching_items = {'type': u'woost.extensions.ecommerce.ecommerceorder.ECommerceOrder'} # EmailTemplate template = EmailTemplate() template.qname = \ "woost.extensions.ecommerce.ecommerceorder_completed_emailtemplate" self.__translate_field(template, "title") template.sender = '"%s"' % User.require_instance( qname = "woost.administrator" ).email template.receivers = '[items[0].customer.email]' template.embeded_images = """ from woost.models import Configuration logo = Configuration.instance.get_setting("logo") if logo: images["logo"] = logo """ template.template_engine = "cocktail" for language in translations: with language_context(language): template.subject = template.title template.body = """ <% from cocktail.controllers import Location from cocktail.html import templates order = items[0] order_summary = templates.new("woost.extensions.ecommerce.OrderConfirmationMessage") order_summary.order = order %> <html> <head> <base href="@{unicode(Location.get_current_host())}"/> </head> <body> ${order_summary.render()} </body> </html> """ # Response response = SendEmailTriggerResponse() response.qname = \ "woost.extensions.ecommerce.ecommerceorder_completed_response" response.email_template = template trigger.responses = [response] return trigger
def transform_hashes(e): from woost.models import File, User to_hex_string = lambda s: "".join(("%x" % ord(c)).zfill(2) for c in s) for file in File.select(): file._file_hash = to_hex_string(file.file_hash) for user in User.select(): if user.password: user._password = to_hex_string(user.password)
def test_insert(self): from datetime import datetime from woost.models import (Document, User, ChangeSet, changeset_context) author = User() author.insert() with changeset_context(author) as changeset: item = Document() item.set("title", u"Foo!", "en") item.resource_type = u"text/foo" item.hidden = True assert not changeset.changes item.insert() assert list(ChangeSet.select()) == [changeset] assert changeset.author is author assert isinstance(changeset.date, datetime) assert changeset.changes.keys() == [item.id] change = changeset.changes[item.id] assert change.target is item assert change.action == "create" assert change.changeset is changeset assert item.changes == [change] for key in "id", "changes", "creation_time", "last_update_time": assert not key in change.item_state print change.item_state assert change.item_state["title"] == {"en": u"Foo!"} assert change.item_state["resource_type"] == u"text/foo" assert change.item_state["hidden"] == True assert change.item_state["translation_enabled"] == \ {"en": item.get("translation_enabled", "en")} assert item.author is author assert item.creation_time assert item.last_update_time assert item.creation_time == item.last_update_time
def _load(self): from woost.models import User from woost.extensions.signup import ( signuppage, signupcontroller, strings ) # Extend User model if not hasattr(User, "confirmed_email"): User.add_member( schema.Boolean( "confirmed_email", default = False, Required = True ) ) self.install()
def process_header_based_authentication(self): user_header = cherrypy.request.headers.get("X-Woost-User") password_header = cherrypy.request.headers.get("X-Woost-Password") if user_header and password_header: params = {self.identifier_field.name: user_header} user = User.get_instance(**params) if user is None or not user.password == password_header: raise AuthenticationFailedError(user_header) else: set_current_user(user)
def submit(self): if self.email or self.hash: # Checking hash code if generate_confirmation_hash(self.email) == self.hash: instance = User.get_instance(email=self.email) if instance: # Confirming and enabling user instance instance.set("confirmed_email", True) instance.set("enabled", True) self.confirmed = True datastore.commit() # Autologin after confirmation if self.autologin: self.context["cms"].authentication.set_user_session( instance)
def _create_incoming_order_trigger(self): from woost.extensions.ecommerce.incomingordertrigger import \ IncomingOrderTrigger trigger = IncomingOrderTrigger( ) trigger.qname = "woost.extensions.ecommerce.incoming_order.trigger" self.__translate_field(trigger, "title") Configuration.instance.triggers.append(trigger) trigger.matching_items = {'type': u'woost.extensions.ecommerce.ecommerceorder.ECommerceOrder'} # EmailTemplate template = EmailTemplate() template.qname = \ "woost.extensions.ecommerce.incoming_order.email_template" self.__translate_field(template, "title") admin = User.require_instance(qname = "woost.administrator") template.sender = repr(admin.email) template.receivers = repr([admin.email]) template.template_engine = "cocktail" for language in translations: with language_context(language): template.subject = template.title template.body = """ <% from cocktail.translations import translations from woost.models import Publishable order = items[0] bo = Publishable.require_instance(qname = "woost.backoffice") edit_url = bo.get_uri(host = ".", path = ["content", str(order.id)]) %> <html> <body> <a href="${edit_url}">${translations('woost.extensions.ecommerce.incoming_order.edit_link')} </a> </body> </html> """ # Response response = SendEmailTriggerResponse() response.email_template = template trigger.responses = [response] return trigger
def test_member_permissions(self): from woost.models import (Item, Publishable, User, Role, Permission, ReadMemberPermission, ModifyMemberPermission) class TestPermission(Permission): pass prefix = "woost.models.publishable.Publishable." m1 = Publishable.resource_type m2 = Publishable.parent m3 = Publishable.controller for permission_type in [ReadMemberPermission, ModifyMemberPermission]: role = Role() user = User(roles=[role]) # No permissions by default self.assert_not_authorized(user, permission_type, member=m1) self.assert_not_authorized(user, permission_type, member=m2) self.assert_not_authorized(user, permission_type, member=m3) # Positive permission role.permissions.append( permission_type( matching_members=[prefix + m1.name, prefix + m2.name], authorized=True)) self.assert_authorized(user, permission_type, member=m1) self.assert_authorized(user, permission_type, member=m2) self.assert_not_authorized(user, permission_type, member=m3) # Permission denied (wrong permission type) self.assert_not_authorized(user, TestPermission) # Negative permission role.permissions.insert( 0, permission_type(matching_members=[prefix + m1.name], authorized=False)) self.assert_not_authorized(user, permission_type, member=m1) self.assert_authorized(user, permission_type, member=m2) self.assert_not_authorized(user, permission_type, member=m3)
def test_translation_permissions(self): from woost.models import (Item, Publishable, User, Role, Permission, CreateTranslationPermission, ReadTranslationPermission, ModifyTranslationPermission, DeleteTranslationPermission) class TestPermission(Permission): pass l1 = "en" l2 = "fr" l3 = "ru" for permission_type in [ CreateTranslationPermission, ReadTranslationPermission, ModifyTranslationPermission, DeleteTranslationPermission ]: role = Role() user = User(roles=[role]) # No permissions by default self.assert_not_authorized(user, permission_type, language=l1) self.assert_not_authorized(user, permission_type, language=l2) self.assert_not_authorized(user, permission_type, language=l3) # Permission granted role.permissions.append( permission_type(matching_languages=[l1, l2], authorized=True)) self.assert_authorized(user, permission_type, language=l1) self.assert_authorized(user, permission_type, language=l2) self.assert_not_authorized(user, permission_type, language=l3) # Permission denied (wrong permission type) self.assert_not_authorized(user, TestPermission) # Negative permission role.permissions.insert( 0, permission_type(matching_languages=[l1], authorized=False)) self.assert_not_authorized(user, permission_type, language=l1) self.assert_authorized(user, permission_type, language=l2) self.assert_not_authorized(user, permission_type, language=l3)
def test_content_permissions(self): from woost.models import (Item, Publishable, User, Role, Permission, CreatePermission, ReadPermission, ModifyPermission, DeletePermission) class TestPermission(Permission): pass item = Item() doc = Publishable() for permission_type in [ CreatePermission, ReadPermission, ModifyPermission, DeletePermission ]: role = Role() user = User(roles=[role]) # Permission denied (no permissions defined) self.assert_not_authorized(user, permission_type, target=doc) # Permission granted role.permissions.append( permission_type(matching_items={ "type": "woost.models.publishable.Publishable" }, authorized=True)) self.assert_authorized(user, permission_type, target=doc) # Permission denied (wrong target) self.assert_not_authorized(user, permission_type, target=item) # Permission denied (wrong permission type) self.assert_not_authorized(user, TestPermission) # Permission denied (prevailing negative permission) role.permissions.insert( 0, permission_type( matching_items={"type": "woost.models.item.Item"}, authorized=False)) self.assert_not_authorized(user, permission_type, target=doc)
def _create_symlink(file, dest): """Create a symbolic link for static publication of an encoded file.""" if not hasattr(os, "symlink"): return # Only create static publication links for public content anonymous = User.require_instance(qname="woost.anonymous_user") if not anonymous.has_permission(ReadPermission, target=file): return static_folder = app.path("static", "audio", str(file.id)) static_link = os.path.join(static_folder, os.path.basename(dest)) if not os.path.lexists(static_link): # Make sure the containing folder exists if not os.path.exists(static_folder): os.mkdir(static_folder) os.symlink(dest, static_link)
def test_target(self): from woost.models import (ContentTrigger, Item, Publishable, StandardPage, User, set_current_user) self.assert_match( ContentTrigger(matching_items={ "type": "woost.models.publishable.Publishable" }), (Publishable(), None, {}, True), (StandardPage(), None, {}, True), (Item(), None, {}, False), (ContentTrigger(), None, {}, False)) user = User() set_current_user(user) self.assert_match( ContentTrigger( matching_items={ "type": "woost.models.publishable.Publishable", "filter": "member-qname", "filter_operator0": "eq", "filter_value0": "foobar" }), (Publishable(), user, {}, False), (Publishable(qname="foobar"), user, {}, True))
def setUp(self): from woost.models import User BaseTestCase.setUp(self) set_language("en") self.user = User() self.user.insert()
class IsAccessibleExpressionTestCase(BaseTestCase): def setUp(self): from woost.models import User BaseTestCase.setUp(self) set_language("en") self.user = User() self.user.insert() def accessible_items(self): from woost.models import Publishable, IsAccessibleExpression return set(Publishable.select(IsAccessibleExpression(self.user))) def test_enabled(self): from woost.models import Publishable, ReadPermission self.everybody_role.permissions.append( ReadPermission(matching_items={ "type": "woost.models.publishable.Publishable" })) a = Publishable() a.enabled = True a.insert() b = Publishable() b.enabled = False b.insert() c = Publishable() c.enabled = True c.insert() d = Publishable() d.enabled = False d.insert() assert self.accessible_items() == set([a, c]) def test_translation_enabled(self): from cocktail.translations import language_context from woost.models import (Publishable, ReadPermission, ReadTranslationPermission) self.everybody_role.permissions.append( ReadPermission(matching_items={ "type": "woost.models.publishable.Publishable" })) self.everybody_role.permissions.append(ReadTranslationPermission()) self.config.languages = ["en"] self.config.published_languages = [] with language_context("en"): a = Publishable() a.per_language_publication = True a.translation_enabled = True a.insert() b = Publishable() b.per_language_publication = True b.translation_enabled = False b.insert() c = Publishable() c.per_language_publication = True c.translation_enabled = True c.insert() d = Publishable() d.per_language_publication = True d.set("translation_enabled", True, "de") d.insert() e = Publishable() e.per_language_publication = False e.enabled = True e.insert() accessible = self.accessible_items() print a in accessible print b in accessible print c in accessible print d in accessible print e in accessible assert self.accessible_items() == set([a, c, e]) self.config.published_languages = ["en"] assert self.accessible_items() == set([a, c, e]) with language_context("de"): self.config.published_languages = ["de"] assert self.accessible_items() == set([d, e]) def test_translation_permitted(self): from cocktail.translations import language_context from woost.models import (Publishable, ReadPermission, ReadTranslationPermission, set_current_user) set_current_user(self.user) self.everybody_role.permissions.append( ReadPermission(matching_items={ "type": "woost.models.publishable.Publishable" })) self.everybody_role.permissions.append( ReadTranslationPermission(matching_languages=["ca", "es"])) self.everybody_role.permissions.append( ReadTranslationPermission(matching_languages=["en"], authorized=False)) self.config.languages = ["ca", "es", "en"] self.config.published_languages = [] a = Publishable() a.per_language_publication = True a.insert() b = Publishable() b.per_language_publication = False b.insert() with language_context("ca"): a.translation_enabled = True assert a.is_accessible() assert b.is_accessible() assert self.accessible_items() == set([a, b]) for language in "es", "en", "de": with language_context(language): assert not a.is_accessible() assert b.is_accessible() assert self.accessible_items() == set([b]) def test_current(self): from woost.models import Publishable, ReadPermission from datetime import datetime, timedelta self.everybody_role.permissions.append( ReadPermission(matching_items={ "type": "woost.models.publishable.Publishable" })) now = datetime.now() a = Publishable() a.enabled = True a.insert() b = Publishable() b.enabled = True b.start_date = now b.end_date = now + timedelta(days=1) b.insert() c = Publishable() c.enabled = True c.start_date = now + timedelta(days=1) c.insert() d = Publishable() d.enabled = True d.end_date = now - timedelta(days=1) d.insert() assert self.accessible_items() == set([a, b]) def test_allowed(self): from woost.models import Publishable, ReadPermission a = Publishable() a.enabled = True a.insert() b = Publishable() b.enabled = True b.insert() self.everybody_role.permissions.append( ReadPermission( matching_items={ "type": "woost.models.publishable.Publishable", "filter": "member-id", "filter_operator0": "ne", "filter_value0": str(b.id) })) assert self.accessible_items() == set([a])
#-*- coding: utf-8 -*- """ .. moduleauthor:: Pepe Osca <*****@*****.**> """ from cocktail.translations import translations from cocktail import schema from woost.models import User translations.load_bundle("woost.extensions.identity.google.user") User.add_member( schema.String("x_identity_google_user_id", indexed=True, unique=True, editable=schema.NOT_EDITABLE, listed_by_default=False, member_group="administration"))
def get_user_from_session(self): session_user_id = session.get(self.SESSION_KEY) if session_user_id: return User.get_instance(session_user_id)
def anonymous_user(self): return User.get_instance(qname = "woost.anonymous_user")