Beispiel #1
0
class Product_SendToFriend(AutoForm):

    access = True
    title = MSG(u'Send to a friend')
    submit_value = MSG(u'Send to my friend')

    meta = [('robots', 'noindex, follow', None)]

    schema = {
        'widget': String, # XXX not used
        'my_email': Email(mandatory=True),
        'my_name': Unicode(mandatory=True),
        'email': Email(mandatory=True),
        'message': Unicode}

    widgets = [MiniProductWidget('widget', title=MSG(u"Product")),
               TextWidget('my_email', title=MSG(u"Your email")),
               TextWidget('my_name', title=MSG(u"Your name")),
               TextWidget('email', title=MSG(u"Email of your friend")),
               MultilineWidget('message',
                title=MSG(u"You can write a message for your friend"))]

    mail_subject = MSG(u"{my_name} advice you this product: {product_title}")
    mail_body = MSG(u"Your friend {my_name} advice you this product: \n\n"
                    u" {product_title}\n\n"
                    u"All details are here:\n\n"
                    u" {product_uri}\n\n"
                    u" {message}\n\n")


    def get_value(self, resource, context, name, datatype):
        if context.user:
            if name == 'my_email':
                return context.user.get_property('email')
            elif name == 'my_name':
                return context.user.get_title()
        return AutoForm.get_value(self, resource, context, name,
                 datatype)



    def action(self, resource, context, form):
        kw = {'product_uri': context.uri.resolve('./'),
              'product_title': resource.get_title(),
              'message': form['message'],
              'my_name': form['my_name']}
        subject = self.mail_subject.gettext(**kw)
        body = self.mail_body.gettext(**kw)
        context.root.send_email(form['email'], subject,
              from_addr=form['my_email'], text=body)

        msg = u'An email has been send to your friend'
        return context.come_back(MSG(msg), goto='./')
Beispiel #2
0
class ServerConfig(ConfigFile):

    schema = {
        'modules': Tokens,
        'listen-address': String(default=''),
        'listen-port': Integer(default=None),
        # Mailing
        'smtp-host': String(default=''),
        'smtp-from': String(default=''),
        'smtp-login': String(default=''),
        'smtp-password': String(default=''),
        # Logging
        'log-level': String(default='warning'),
        'log-email': Email(default=''),
        # Time events
        'cron-interval': Integer(default=0),
        # Security
        'session-timeout': ExpireValue(default=timedelta(0)),
        # Tuning
        'database-size': String(default='19500:20500'),
        'database-readonly': Boolean(default=False),
        'index-text': Boolean(default=True),
        'max-width': Integer(default=None),
        'max-height': Integer(default=None),
    }
Beispiel #3
0
    def action(self, resource, context, form):
        # Get the user
        email = form['username'].strip()
        user = context.root.get_user_from_login(email)
        if form['no_password']:
            if not Email.is_valid(email):
                message = u'The given username is not an email address.'
                context.message = ERROR(message)
                return
            # Case 1: Register
            # check captcha first
            captcha = form['captcha'].strip()
            crypted = crypt_captcha(captcha)
            crypt_imgtext = form['crypt_imgtext'].strip()
            decrypt =  Password.decode('%s' % crypt_imgtext)
            if crypted != decrypt:
                error = u"You typed an incorrect captcha string."
                context.message = ERROR(error)
                return
            # does the user exists?
            if user is None:
                if context.site_root.is_allowed_to_register():
                    return self._register(resource, context, email)
                    # FIXME This message does not protect privacy
                    error = u"You don't have an account, contact the site admin."
                    context.message = ERROR(error)
                    return
            # Case 2: Forgotten password
            email = user.get_property('email')
            user.send_forgotten_password(context, email)
            path = '/ui/website/forgotten_password.xml'
            handler = resource.get_resource(path)
            return stl(handler)
        
        # Case 3: Login
        password = form['password']
        if user is None or not user.authenticate(password, clear=True):
            context.message = ERROR(u'The email or the password is incorrect.')
            return
        # Set cookie & context
        user.set_auth_cookie(context, password)
        context.user = user

        # Come back
        referrer = context.get_referrer()
        if referrer is None:
            goto = get_reference('./')
        else:
            path = get_uri_path(referrer)
            if path.endswith(';login'):
                goto = get_reference('./')
            else:
                goto = referrer
        return context.come_back(INFO(u"Welcome to the Phoenix Project!"), goto)
Beispiel #4
0
    def get_schema(self, resource, context):
        to = ContactOptions(resource=resource, mandatory=True)
        if len(to.get_options()) == 1:
            to = String(mandatory=True)

        return {
            'to': to,
            'from': Email(mandatory=True),
            'subject': Unicode(mandatory=True),
            'message_body': Unicode(mandatory=True),
            'captcha': CaptchaDatatype}
Beispiel #5
0
class Shop_UserSendConfirmation(ImproveAutoForm):

    access = True
    title = MSG(u'Request your registration key')

    actions = [Button(access='is_allowed_to_edit',
                      name='send_registration_key',
                      title=MSG(u'Receive your key'))]
    schema = {'email': Email(mandatory=True)}
    widgets = [TextWidget('email', title=MSG(u'Your email address'))]

    def _get_user(self, resource, context, email):
        results = context.root.search(username=email)
        if len(results) == 0:
            return None
        user = results.get_documents()[0]
        user = resource.get_resource('/users/%s' % user.name)
        return user


    def get_namespace(self, resource, context):
        proxy = super(Shop_UserSendConfirmation, self)
        namespace = proxy.get_namespace(resource, context)

        confirm_msg = MSG(u"""Fill this form to receive a mail with the link
                              to activate your account""")
        namespace['required_msg'] = (list(XMLParser(confirm_msg.gettext().encode('utf8'))) +
                                     list(XMLParser('<br/>')) +
                                     list(namespace['required_msg']))
        return namespace


    def action_send_registration_key(self, resource, context, form):
        email = form['email']
        # Get the user with the given login name
        user = self._get_user(resource, context, email)
        if user is None:
            message = ERROR(u'There is no user identified as "{username}"',
                      username=email)
            return context.come_back(message,
                                     goto='./;confirm_registration')

        # Resend confirmation
        must_confirm = user.get_property('user_must_confirm')
        if not must_confirm:
            # Already confirmed
            message = ERROR(u'Your account has already been confirmed')
            return context.come_back(message, goto='/')

        # Ok
        user.send_confirmation(context, email)
        message = MSG(u'Your activation key has been sent to your mailbox')
        return context.come_back(message,
                                 goto='./;confirm_registration')
Beispiel #6
0
    def action_mass_subscribe(self, resource, context, form):
        root = context.root

        already = []
        unallowed = []
        invited = []
        invalid = []
        subscribed_users = resource.get_subscribed_users()
        for email in form['emails']:
            email = email.strip()
            if not email:
                continue
            # Check if email is valid
            if not Email.is_valid(email):
                invalid.append(email)
                continue

            # Checks
            user = root.get_user_from_login(email)
            if user:
                if user.name in subscribed_users:
                    already.append(user)
                    continue
                if not resource.is_subscription_allowed(user.name):
                    unallowed.append(user)
                    continue

            # Subscribe
            user = resource.subscribe_user(email=email, user=user)
            key = resource.set_register_key(user.name)
            # Send invitation
            subject = resource.invitation_subject.gettext()
            confirm_url = context.uri.resolve(';accept_invitation')
            confirm_url.query = {'key': key, 'email': email}
            text = resource.invitation_text.gettext(uri=confirm_url)
            root.send_email(email, subject, text=text)
            invited.append(user)

        # Ok
        context.message = []
        add_subscribed_message(MSG_ALREADY, already, context)
        add_subscribed_message(MSG_INVALID,
                               invalid,
                               context,
                               users_is_resources=False)
        add_subscribed_message(MSG_INVITED, invited, context)
        add_subscribed_message(MSG_UNALLOWED, unallowed, context)
Beispiel #7
0
    def action_mass_subscribe(self, resource, context, form):
        root = context.root

        already = []
        unallowed = []
        invited = []
        invalid = []
        subscribed_users = resource.get_subscribed_users()
        for email in form['emails']:
            email = email.strip()
            if not email:
                continue
            # Check if email is valid
            if not Email.is_valid(email):
                invalid.append(email)
                continue

            # Checks
            user = root.get_user_from_login(email)
            if user:
                if user.name in subscribed_users:
                    already.append(user)
                    continue
                if not resource.is_subscription_allowed(user.name):
                    unallowed.append(user)
                    continue

            # Subscribe
            user = resource.subscribe_user(email=email, user=user)
            key = resource.set_register_key(user.name)
            # Send invitation
            subject = resource.invitation_subject.gettext()
            confirm_url = context.uri.resolve(';accept_invitation')
            confirm_url.query = {'key': key, 'email': email}
            text = resource.invitation_text.gettext(uri=confirm_url)
            root.send_email(email, subject, text=text)
            invited.append(user)

        # Ok
        context.message = []
        add_subscribed_message(MSG_ALREADY, already, context)
        add_subscribed_message(MSG_INVALID, invalid, context,
                               users_is_resources=False)
        add_subscribed_message(MSG_INVITED, invited, context)
        add_subscribed_message(MSG_UNALLOWED, unallowed, context)
Beispiel #8
0
 def get_metadata_schema(cls):
     schema = ShopFolder.get_metadata_schema()
     schema['shop_uri'] = String
     schema['shop_backoffice_uri'] = String
     schema['order_notification_mails'] = Email(multiple=True)
     schema['shop_default_zone'] = CountriesZonesEnumerate(default=0)
     schema['shop_sort_by'] = SortBy_Enumerate
     schema['shop_sort_reverse'] = Boolean
     schema['categories_batch_size'] = Integer(default=20)
     schema['devise'] = Devises(default='978')
     schema['bill_logo'] = ImagePathDataType
     schema['pdf_signature'] = Unicode
     schema['barcode_format'] = BarcodesFormat
     schema['show_sub_categories'] = Boolean
     schema['hide_not_buyable_products'] = Boolean
     schema['product_cover_is_mandatory'] = Boolean
     schema['log_authentification'] = Boolean
     schema['registration_need_email_validation'] = Boolean
     return schema
Beispiel #9
0
class ShopForm(OrderedTable):

    class_id = 'shop-form'
    class_title = MSG(u'Shop form')
    class_version = '20090609'
    class_handler = ShopFormTable
    class_views = ['display', 'edit', 'view', 'add_record']

    display = ShopForm_Display()
    view = OrderedTable_View(search_template=None, access='is_admin')
    edit = AutomaticEditView()

    add_product = AddProduct_View()

    form = [
        TextWidget('name', title=MSG(u'Name')),
        TextWidget('title', title=MSG(u'Title')),
        BooleanCheckBox('mandatory', title=MSG(u'Mandatory')),
        BooleanCheckBox('multiple', title=MSG(u'Multiple')),
        SelectWidget('datatype', title=MSG(u'Data Type')),
        SelectWidget('widget', title=MSG(u'Widget')),
    ]

    edit_widgets = [
        TextWidget('submit_value', title=MSG(u'Submit value')),
        TextWidget('to_addr', title=MSG(u'To addr')),
        RTEWidget('introduction', title=MSG(u'Introduction')),
        RTEWidget('final_message', title=MSG(u'Final message')),
        BooleanRadio('must_be_authentificated',
                     title=MSG(u'Must be authentificated to see form'))
    ]

    edit_schema = {
        'submit_value': Unicode(multilingual=True, mandatory=True),
        'to_addr': Email(mandatory=True),
        'introduction': XHTMLBody(multilingual=True),
        'final_message': XHTMLBody(multilingual=True),
        'must_be_authentificated': Boolean
    }

    @classmethod
    def get_metadata_schema(cls):
        return merge_dicts(OrderedTable.get_metadata_schema(), cls.edit_schema)
Beispiel #10
0
class ConfirmSubscription(AutoForm):

    access = 'is_allowed_to_view'
    title = MSG(u"Subscribe")
    description = MSG(
        u'By confirming your subscription to this resource you will'
        u' receive an email every time this resource is modified.')

    schema = freeze({
        'key': String(mandatory=True),
        'email': Email(mandatory=True)
    })
    widgets = freeze([HiddenWidget('key'), ReadOnlyWidget('email')])
    actions = [Button(access=True, title=MSG(u'Confirm subscription'))]

    key_status = 'S'
    msg_already = MSG_USER_ALREADY_SUBSCRIBED

    def get_value(self, resource, context, name, datatype):
        if name in ('key', 'email'):
            return context.get_query_value(name)
        proxy = super(ConfirmSubscription, self)
        return proxy.get_value(resource, context, name, datatype)

    def get_username(self, resource, context, key):
        # 1. Get the user
        email = context.get_form_value('email')
        user = context.root.get_user_from_login(email)
        if user is None:
            return None, MSG(u'Bad email')

        # 2. Get the user key
        username = user.name
        user_key = resource.get_register_key(username, self.key_status)
        if user_key is None:
            return username, self.msg_already

        # 3. Check the key
        if user_key != key:
            return username, MSG_BAD_KEY

        # 4. Ok
        return username, None

    def get_namespace(self, resource, context):
        key = context.get_form_value('key')
        username, error = self.get_username(resource, context, key)
        if error:
            return context.come_back(error, goto='./')

        proxy = super(ConfirmSubscription, self)
        return proxy.get_namespace(resource, context)

    def action(self, resource, context, form):
        username, error = self.get_username(resource, context, form['key'])
        if error:
            context.message = error
            return

        # Ok
        resource.reset_register_key(username)
        resource.after_register(username)
        return context.come_back(MSG_USER_SUBSCRIBED, goto='./')
Beispiel #11
0
class Shop_Register(RegisterForm):

    access = True
    meta = [('robots', 'noindex, follow', None)]

    query_schema = {'goto': String}

    base_schema = {
        'goto': String,
        'email': Email(mandatory=True),
        'lastname': Unicode(mandatory=True),
        'firstname': Unicode(mandatory=True),
        'gender': Civilite(mandatory=True),
        'password': String(mandatory=True),
        'password_check': String(mandatory=True),
        'phone1': String(mandatory=True),
        'phone2': String
    }

    address_schema = {
        'address_1': Unicode(mandatory=True),
        'address_2': Unicode,
        'zipcode': String(mandatory=True),
        'town': Unicode(mandatory=True),
        'country': CountriesEnumerate(mandatory=True)
    }

    base_widgets = [
        HiddenWidget('goto', title=None),
        TextWidget('email', title=MSG(u"Email")),
        SelectRadio('gender', title=MSG(u"Civility"), has_empty_option=False),
        TextWidget('lastname', title=MSG(u"Lastname")),
        TextWidget('firstname', title=MSG(u"Firstname")),
        TextWidget('phone1', title=MSG(u"Phone number")),
        TextWidget('phone2', title=MSG(u"Mobile")),
        PasswordWidget('password', title=MSG(u"Password")),
        PasswordWidget('password_check', title=MSG(u"Repeat password"))
    ]

    address_widgets = [
        TextWidget('address_1', title=MSG(u"Address")),
        TextWidget('address_2', title=MSG(u"Address")),
        TextWidget('zipcode', title=MSG(u"Zip code")),
        TextWidget('town', title=MSG(u"Town")),
        SelectWidget('country', title=MSG(u"Pays"))
    ]

    def GET(self, resource, context):
        # If a user is connected redirect on his account
        if context.user is not None:
            link = context.get_link(context.user)
            return context.uri.resolve(link)
        # RegisterForm
        return RegisterForm.GET(self, resource, context)

    def get_value(self, resource, context, name, datatype):
        proxy = super(Shop_Register, self)
        if name == 'goto' and context.method == 'GET':
            return context.query['goto']
        value = proxy.get_value(resource, context, name, datatype)
        return value

    def get_title(self, context):
        group = self.get_group(context)
        return group.get_property('register_title') or MSG(u'Register')

    def get_schema(self, resource, context):
        group = self.get_group(context)
        base_schema = deepcopy(self.base_schema)
        # Inject address schema ?
        address_schema = {}
        if group.get_property('hide_address_on_registration') is False:
            address_schema = self.address_schema
        # Lastname mandatory ?
        l_mandatory = group.get_property(
            'lastname_is_mandatory_on_registration')
        base_schema['lastname'] = Unicode(mandatory=l_mandatory)
        # Phone mandatory ?
        p_mandatory = group.get_property('phone_is_mandatory_on_registration')
        base_schema['phone1'] = String(mandatory=p_mandatory)

        # Return schema
        return merge_dicts(base_schema, group.get_dynamic_schema(),
                           address_schema)

    def get_widgets(self, resource, context):
        widgets = self.base_widgets[:]
        # Group widgets
        group = self.get_group(context)
        widgets.extend(group.get_dynamic_widgets())
        # Address widget
        address_widgets = []
        if group.get_property('hide_address_on_registration') is False:
            address_widgets = self.address_widgets
        widgets.extend(address_widgets)
        return widgets

    def get_group(self, context):
        root = context.root
        query = [
            PhraseQuery('format', 'user-group'),
            PhraseQuery('name', 'default')
        ]
        search = root.search(AndQuery(*query))
        documents = search.get_documents()
        group = documents[0]
        return root.get_resource(group.abspath)

    def get_namespace(self, resource, context):
        namespace = RegisterForm.get_namespace(self, resource, context)
        # Add register body
        group = self.get_group(context)
        register_body = group.get_property('register_body')
        if register_body is not None:
            namespace['required_msg'] = (register_body +
                                         list(XMLParser('<br/><br/>')) +
                                         list(namespace['required_msg']))
        return namespace

    def action(self, resource, context, form):
        shop = get_shop(resource)
        root = context.root
        site_root = resource.get_site_root()

        # Check the new password matches
        password = form['password'].strip()
        if password != form['password_check']:
            context.message = ERROR(u"The two passwords are different.")
            return
        if shop.get_property('registration_need_email_validation') is False:
            msg = MSG(u'Your inscription has been validaded.')
        else:
            msg = MSG(u'Your inscription has been validaded, '
                      u'you will receive an email to confirm it.')

        # Do we already have a user with that email?
        email = form['email'].strip()
        user = root.get_user_from_login(email)
        if user is not None:
            context.message = ERROR(u'This email address is already used.')
            return

        # Add the user
        users = root.get_resource('users')
        user = users.set_user(email, password)

        # Set user group (do it befor save_form for dynanic schema)
        group = self.get_group(context)
        user.set_property('user_group', str(group.get_abspath()))

        # Save properties
        user.save_form(self.get_schema(resource, context), form)

        # Save address in addresses table
        if group.get_property('hide_address_on_registration') is False:
            kw = {'user': user.name}
            addresses = shop.get_resource('addresses')
            for key in [
                    'gender', 'lastname', 'firstname', 'address_1',
                    'address_2', 'zipcode', 'town', 'country'
            ]:
                kw[key] = form[key]
            kw['title'] = MSG(u'Your address').gettext()
            addresses.handler.add_record(kw)

        # Clean cart, if another user already login before
        cart = ProductCart(context)
        cart.clean()

        # Set the role
        site_root.set_user_role(user.name, 'guests')

        # We log authentification
        shop = get_shop(resource)
        logs = shop.get_resource('customers/authentification_logs')
        logs.log_authentification(user.name)
        user.set_property('last_time', datetime.now())

        # Send confirmation email
        need_email_validation = shop.get_property(
            'registration_need_email_validation')
        user.send_register_confirmation(context, need_email_validation)

        # User is enabled ?
        user_is_enabled = group.get_property('user_is_enabled_when_register')
        user.set_property('is_enabled', user_is_enabled)

        # Create modules if needed
        search = context.root.search(is_shop_user_module=True)
        for brain in search.get_documents():
            shop_user_module = root.get_resource(brain.abspath)
            shop_user_module.initialize(user)

        # If user not enabled, send mail to webmaster to validate user
        if user_is_enabled is False:
            subject = MSG(
                u'A customer must be validated in your shop').gettext()
            shop_backoffice_uri = shop.get_property('shop_backoffice_uri')
            body = registration_notification_body.gettext(
                name=user.name,
                email=email,
                shop_backoffice_uri=shop_backoffice_uri)
            for to_addr in shop.get_property('order_notification_mails'):
                root.send_email(to_addr, subject, text=body)

        # If need_email_validation or user not enable redirect on Welcome
        if need_email_validation is True or user_is_enabled is False:
            goto = '%s/welcome/' % context.get_link(group)
            return context.come_back(msg, goto=goto)

        ########################
        # Do authentification
        ########################
        # Set cookie
        user.set_auth_cookie(context, form['password'])

        # Set context
        context.user = user

        # Redirect
        shop = get_shop(resource)
        if form['goto']:
            goto = context.query['goto']
        elif resource == shop:
            goto = './;addresses'
        elif resource.class_id == shop.product_class.class_id:
            goto = './'
        else:
            goto = '/users/%s' % user.name
        return context.come_back(msg, goto)
Beispiel #12
0
 def test_Email(self):
     for name, result in {'*****@*****.**':True,
                          'toto@':False}.iteritems():
         self.assertEqual(Email.is_valid(name), result)
Beispiel #13
0
 def is_valid(cls, value):
     return Email.is_valid(value)
Beispiel #14
0
 def GET(self, resource, context):
     """This view load the paybox cgi. That script redirect on paybox
     server to show the payment form.
     """
     # We get the paybox CGI path on server
     cgi_path = join(dirname(sys.executable), 'paybox.cgi')
     # Configuration
     kw = {}
     order = resource.parent
     kw['PBX_CMD'] = order.name
     kw['PBX_TOTAL'] = int(resource.get_property('amount') * 100)
     # Basic configuration
     kw['PBX_MODE'] = '4'
     kw['PBX_LANGUE'] = 'FRA'
     kw['PBX_TYPEPAIEMENT'] = 'CARTE'
     kw['PBX_WAIT'] = '0'
     kw['PBX_RUF1'] = 'POST'
     kw['PBX_RETOUR'] = "transaction:T;autorisation:A;amount:M;advanced_state:E;payment:P;carte:C;sign:K"
     # PBX Retour uri
     base_uri = context.uri.resolve(context.get_link(resource))
     for option in PBXState.get_options():
         key = option['pbx']
         status = option['name']
         uri = '%s/;end?status=%s' % (base_uri, status)
         kw[key] = '%s' % uri
     # PBX_REPONDRE_A (Url to call to set payment status)
     kw['PBX_REPONDRE_A'] = '%s/;callback' % base_uri
     # Configuration
     payment_way = get_payment_way(resource, 'paybox')
     for key in ['PBX_SITE', 'PBX_IDENTIFIANT',
                 'PBX_RANG', 'PBX_DIFF', 'PBX_AUTOSEULE']:
         kw[key] = payment_way.get_property(key)
     # Devise
     kw['PBX_DEVISE'] = resource.get_property('devise')
     # PBX_PORTEUR
     # XXX Allow to overide PBX_PORTEUR
     # (If someone call and give his card number ?)
     email = context.user.get_property('email')
     if Email.is_valid(email) is False:
         raise ValueError, 'PBX_PORTEUR should be a valid Email address'
     kw['PBX_PORTEUR'] = email
     # En mode test:
     if not payment_way.get_property('real_mode'):
         kw.update(payment_way.test_configuration)
     # Build cmd
     cmd = [cgi_path] + ['%s=%s' % (x[0], x[1]) for x in kw.iteritems()]
     log_debug("Calling Paybox: {0!r}".format(cmd))
     # Call the CGI
     try:
         result = check_output(cmd)
         # Check if all is ok
         html = re.match ('.*?<HEAD>(.*?)</HTML>', result, re.DOTALL)
         if html is None:
             raise CalledProcessError
     except CalledProcessError, e:
         # Try do get error number
         num_error = re.match ('.*?NUMERR=(.*?)"', e.output, re.DOTALL)
         if num_error:
             num_error = num_error.group(1)
             error = PayboxCGIErrors.get_value(num_error)
         else:
             error = "Unknow reason"
         error = u"Error: payment module can't be loaded. (%s)" % error
         raise ValueError, error
Beispiel #15
0
class ShopUser(User, DynamicFolder):

    class_version = '20100720'
    class_id = 'user'

    # Views
    manage = ShopUser_Manage()
    profile = ShopUser_Profile()
    public_profile = ShopUser_PublicProfile()
    edit_account = ShopUser_EditAccount()
    edit_group = ShopUser_EditGroup()
    viewbox = ShopUser_Viewbox()

    # Confirm registration
    confirm_registration = Shop_UserConfirmRegistration()
    send_confirmation_view = Shop_UserSendConfirmation()

    # Orders views
    orders_view = ShopUser_OrdersView()
    order_view = ShopUser_OrderView()

    # Addresses views
    addresses_book = Addresses_Book(access='is_allowed_to_edit')
    edit_address = ShopUser_EditAddress()
    add_address = ShopUser_AddAddress()

    add_image = CurrentFolder_AddImage()

    # Base schema / widgets
    base_schema = merge_dicts(
        User.get_metadata_schema(),
        lastname=Unicode(title=MSG(u'Lastname')),
        firstname=Unicode(title=MSG(u'Firstname')),
        email=Email(title=MSG(u'Email')),
        ctime=DateTime(title=MSG(u'Register date')),
        last_time=DateTime(title=MSG(u'Last connection')),
        gender=Civilite(title=MSG(u"Civility")),
        phone1=String(mandatory=True, title=MSG(u'Phone1')),
        phone2=String(title=MSG(u'Phone2')))

    base_widgets = [
        TextWidget('email', title=MSG(u"Email")),
        SelectRadio('gender', title=MSG(u"Civility"), has_empty_option=False),
        TextWidget('lastname', title=MSG(u"Lastname")),
        TextWidget('firstname', title=MSG(u"Firstname")),
        TextWidget('phone1', title=MSG(u"Phone number")),
        TextWidget('phone2', title=MSG(u"Mobile"))
    ]

    base_items = [{
        'name': 'account',
        'title': MSG(u"Edit my account"),
        'href': ';edit_account',
        'img': '/ui/icons/48x48/card.png'
    }, {
        'name': 'preferences',
        'title': MSG(u'Edit my preferences'),
        'href': ';edit_preferences',
        'img': '/ui/icons/48x48/preferences.png'
    }, {
        'name': 'password',
        'title': MSG(u'Edit my password'),
        'href': ';edit_password',
        'img': '/ui/icons/48x48/lock.png'
    }, {
        'name': 'addresses',
        'title': MSG(u'My addresses book'),
        'href': ';addresses_book',
        'img': '/ui/icons/48x48/tasks.png'
    }, {
        'name': 'orders',
        'title': MSG(u'Orders history'),
        'href': ';orders_view',
        'img': '/ui/shop/images/bag_green.png'
    }]

    @staticmethod
    def _make_resource(cls, folder, name, *args, **kw):
        ctime = datetime.now()
        User._make_resource(cls, folder, name, ctime=ctime, *args, **kw)

    base_class_views = [
        'profile', 'addresses_book', 'edit_account', 'orders_view',
        'edit_preferences', 'edit_password'
    ]

    @property
    def class_views(self):
        context = get_context()
        # Back-Office
        hostname = context.uri.authority
        if hostname[:6] == 'admin.':
            return ['manage'] + self.base_class_views
        if hostname[:6] == 'www.aw':
            # XXX Add a configurator for public profil
            return ['public_profile'] + self.base_class_views
        return self.base_class_views

    @classmethod
    def get_metadata_schema(cls):
        return merge_dicts(DynamicFolder.get_metadata_schema(),
                           cls.base_schema,
                           is_enabled=Boolean(title=MSG(u'Enabled')),
                           user_group=UserGroup_Enumerate(title=MSG(u'Group')))

    @classmethod
    def get_dynamic_schema(cls):
        context = get_context()
        self = context.resource
        if (hasattr(context, 'view')
                and issubclass(context.view.__class__, RegisterForm)):
            group = context.view.get_group(context)
            return group.get_dynamic_schema()
        if not isinstance(self, User):
            self = context.user
        if self is None:
            group = context.site_root.get_resource('shop/groups/default')
        else:
            group = self.get_group(context)
        # By default we use default group
        if group is None:
            group = context.site_root.get_resource('shop/groups/default')
        return group.get_dynamic_schema()

    @classmethod
    def get_dynamic_widgets(cls):
        context = get_context()
        self = context.resource
        if issubclass(context.view.__class__, RegisterForm):
            group = context.view.get_group(context)
            return group.get_dynamic_widgets()
        if not isinstance(self, User):
            self = context.user
        if self is None:
            return []
        group = self.get_group(context)
        return group.get_dynamic_widgets()

    def _get_catalog_values(self):
        values = User._get_catalog_values(self)
        values['ctime'] = self.get_property('ctime')
        values['last_time'] = self.get_property('last_time')
        values['user_group'] = str(self.get_property('user_group'))
        values['is_enabled'] = self.get_property('is_enabled')
        return values

    def get_public_title(self):
        try:
            return self.get_dynamic_property('pseudo')
        except:
            # XXX Fix that bug
            return MSG(u'Unknow')

    def get_document_types(self):
        return []

    def save_form(self, schema, form):
        dynamic_schema = self.get_dynamic_schema()
        metadata_schema = self.get_metadata_schema()
        for key in schema:
            if key in ['password', 'user_must_confirm']:
                continue
            elif (key not in metadata_schema and key not in dynamic_schema):
                continue
            value = form[key]
            if value is None:
                self.del_property(value)
                continue
            datatype = schema[key]
            if issubclass(datatype, (String, Unicode)):
                value = value.strip()
            self.set_property(key, value)

    confirmation_txt = MSG(
        u"To finalize your inscription you have to confirm your identity "
        u"by clicking this link:"
        u"\n"
        u"\n {uri}\n"
        u"\n"
        u"(Your identity confirmation key is {key})")

    def send_register_confirmation(self, context, need_email_validation=False):
        # Get group
        group = self.get_group(context)
        # Get mail subject and body
        subject = group.get_register_mail_subject()
        text = group.get_register_mail_body()
        # Registration need validation ?
        if need_email_validation:
            key = generate_password(30)
            self.set_property('user_must_confirm', key)
            # Build the confirmation link
            confirm_url = deepcopy(context.uri)
            path = '/users/%s/;confirm_registration' % self.name
            confirm_url.path = Path(path)
            confirm_url.query = {'key': key, 'username': self.get_login_name()}
            confirm_url = str(confirm_url)
            text += '\n\n'
            text += self.confirmation_txt.gettext(uri=confirm_url, key=key)

        # Send mail
        context.root.send_email(to_addr=self.get_property('email'),
                                subject=subject,
                                text=text)

    def get_group(self, context):
        user_group = self.get_property('user_group')
        return context.root.get_resource(user_group)

    def to_text(self):
        texts = []
        for key, datatype in (self.get_dynamic_schema().items() +
                              self.get_metadata_schema().items()):
            if key == 'password':
                continue
            value = self.get_property(key)
            if value:
                value = datatype.encode(value)
                value = unicode(value, 'utf-8')
                texts.append(value)
        return u'\n'.join(texts)

    def get_namespace(self, context):
        root = context.root
        # Get dynamic user values
        dynamic_user_value = ResourceDynamicProperty()
        dynamic_user_value.schema = self.get_dynamic_schema()
        dynamic_user_value.resource = self
        # Module
        shop_module = ModuleLoader()
        shop_module.context = context
        shop_module.here = self
        # Get modules items
        modules_items = []
        search = context.root.search(is_shop_user_module=True)
        for brain in search.get_documents():
            shop_user_module = root.get_resource(brain.abspath)
            modules_items.append({
                'name': shop_user_module.element_name,
                'title': shop_user_module.element_title,
                'href': shop_user_module.element_name,
                'img': shop_user_module.class_icon48
            })
        # Ctime
        ctime = self.get_property('ctime')
        accept = context.accept_language
        # ACLS
        ac = self.get_access_control()
        is_authenticated = ac.is_authenticated(context.user, self)
        is_owner = context.user is not None and context.user.name == self.name
        # Build namespace
        return {
            'name': self.name,
            'link': context.get_link(self),
            'module': shop_module,
            'dynamic_user_value': dynamic_user_value,
            'is_owner': is_owner,
            'is_authenticated': is_authenticated,
            'ctime':
            format_datetime(ctime, accept) if ctime else None,  # XXX Why ?
            'items': self.base_items + modules_items
        }

    #############################
    # Api
    #############################
    def send_confirm_url(self, context, email, subject, text, view):
        # XXX We override send_confirm_url to send mail
        # without setting subject with host, to use shop_uri
        # and not backoffice_uri (Since webmaster click from backoffice uri)
        # and to use good from_addr

        # Set the confirmation key
        if self.has_property('user_must_confirm'):
            key = self.get_property('user_must_confirm')
        else:
            key = generate_password(30)
            self.set_property('user_must_confirm', key)

        # Build the confirmation link
        shop = get_shop(context.resource)
        base_uri = shop.get_property('shop_uri')
        confirm_url = get_reference(base_uri)
        path = '/users/%s/%s' % (self.name, view)
        confirm_url.path = Path(path)
        confirm_url.query = {'key': key, 'username': self.get_login_name()}
        confirm_url = str(confirm_url)
        text = text.gettext(uri=confirm_url, key=key)
        # Get from_addr
        site_root = context.site_root
        if site_root.get_property('emails_from_addr'):
            user_name = site_root.get_property('emails_from_addr')
            user = self.get_resource('/users/%s' % user_name)
            from_addr = user.get_title(), user.get_property('email')
        else:
            from_addr = context.server.smtp_from
        # Subject
        subject = u'[%s] %s' % (base_uri, subject.gettext())
        # Send email
        context.root.send_email(email,
                                subject,
                                from_addr=from_addr,
                                text=text,
                                subject_with_host=False)

    ###############################
    # Computed schema
    ###############################
    computed_schema = {
        'nb_orders': Integer(title=MSG(u'Nb orders (even cancel)')),
        'address': Unicode(title=MSG(u'Last known user address'))
    }

    @property
    def nb_orders(self):
        # XXX Orders states
        root = self.get_root()
        queries = [
            PhraseQuery('format', 'order'),
            PhraseQuery('customer_id', self.name)
        ]
        return len(root.search(AndQuery(*queries)))

    @property
    def address(self):
        # XXX We should have a default address ?
        context = get_context()
        shop = get_shop(context.resource)
        addresses_h = shop.get_resource('addresses').handler
        records = addresses_h.search(user=self.name)
        if len(records) == 0:
            return None
        record = records[0]
        addresse = addresses_h.get_record_namespace(record.id)
        addr = u''
        for key in ['address_1', 'address_2', 'zipcode', 'town', 'country']:
            try:
                addr += u'%s ' % addresse[key]
            except Exception:
                # XXX Why ?
                addr += u'XXX'
        return addr
Beispiel #16
0
class RegisterForm(AutoForm):
    access = 'is_allowed_to_view'
    title = MSG(u"Subscription")
    schema = freeze({'email': Email(mandatory=True)})
    widgets = freeze([TextWidget('email', title=MSG(u"E-mail Address"))])
    query_schema = freeze({'email': Email})
    actions = [RegisterButton, UnregisterButton]

    # Messages
    msg_user_already_subscribed = MSG_USER_ALREADY_SUBSCRIBED
    msg_confirmation_sent = MSG_CONFIRMATION_SENT
    msg_user_subscribed = MSG_USER_SUBSCRIBED
    msg_user_already_unsubscribed = MSG_USER_ALREADY_UNSUBSCRIBED
    msg_user_unsubscribed = MSG_USER_UNSUBSCRIBED

    def get_widgets(self, resource, context):
        widgets = super(RegisterForm, self).get_widgets(resource, context)
        if context.user:
            # E-mail becomes hard coded
            widgets = list(widgets)
            email = widgets[0]
            widgets[0] = ReadOnlyWidget(name=email.name,
                                        focus=True,
                                        title=email.title)
        return widgets

    def get_value(self, resource, context, name, datatype):
        if name == 'email':
            if context.user:
                return context.user.get_value('email')
            return context.query['email']
        proxy = super(RegisterForm, self)
        return proxy.get_value(self, resource, context, name, datatype)

    def action_register(self, resource, context, form):
        root = context.root
        email = form['email']
        existing_user = root.get_user_from_login(email)

        if existing_user is not None:
            username = existing_user.name
            if resource.is_subscribed(username, skip_unconfirmed=False):
                context.message = self.msg_user_already_subscribed
                return

        # Create user anyhow
        user = resource.subscribe_user(email=email, user=existing_user)

        if context.user is None:
            # Anonymous subscription
            resource.send_confirm_register(user, context)
            context.message = self.msg_confirmation_sent
        else:
            resource.after_register(user.name)
            context.message = self.msg_user_subscribed

    def action_unregister(self, resource, context, form):
        user = context.root.get_user_from_login(form['email'])
        if user is None:
            context.message = self.msg_user_already_unsubscribed
            return

        username = user.name
        if not resource.is_subscribed(username, skip_unconfirmed=False):
            context.message = self.msg_user_already_unsubscribed
            return

        if context.user is None:
            # Anonymous subscription
            resource.send_confirm_register(user, context, unregister=True)
            context.message = self.msg_confirmation_sent
        else:
            resource.unsubscribe_user(username)
            resource.after_unregister(username)
            context.message = self.msg_user_unsubscribed
Beispiel #17
0
 def test_Email(self):
     emails = {"*****@*****.**": True, "*****@*****.**": True, "toto@": False}
     for name, result in emails.iteritems():
         self.assertEqual(Email.is_valid(name), result)
Beispiel #18
0
class Email_Field(Metadata_Field):
    datatype = Email()
    size = 40
Beispiel #19
0
class Shop_UserConfirmRegistration(ImproveAutoForm):

    access = True
    title = MSG(u'Confirm your registration')

    actions = [Button(access='is_allowed_to_edit',
                      name='confirm_key',
                      title=MSG(u'Confirm my registration'))]
    schema = {'username': Email(mandatory=True),
              'key': String(mandatory=True)}
    widgets = [TextWidget('username', title=MSG(u'Your email address')),
               TextWidget('key',
                          title=MSG(u'Activation key (received by mail)'))]

    def get_value(self, resource, context, name, datatype):
        if name in ('username', 'key'):
            return context.get_form_value(name)
        proxy = super(Shop_UserConfirmRegistration, self)
        return proxy.get_value(resource, context, name, datatype)


    def _get_user(self, resource, context, email):
        results = context.root.search(username=email)
        if len(results) == 0:
            return None
        user = results.get_documents()[0]
        user = resource.get_resource('/users/%s' % user.name)
        return user


    def get_namespace(self, resource, context):
        proxy = super(Shop_UserConfirmRegistration, self)
        namespace = proxy.get_namespace(resource, context)

        confirm_msg = MSG(u"""
          You have not yet confirmed your registration.<br/>
          To confirm it, please click on the confirmation link
          included on the registration confirmation email.<br/>
          You can also fill your email address and your activation
          key (received on the mail) in the following form.<br/>
          If you havn't received your registration key,
          <a href=";send_confirmation_view">
            you can receive it again by clicking here.
          </a>
          """)
        namespace['required_msg'] = (list(XMLParser(confirm_msg.gettext().encode('utf8'))) +
                                     list(XMLParser('<br/>')) +
                                     list(namespace['required_msg']))
        return namespace


    def action_confirm_key(self, resource, context, form):
        # Get the email address
        form['username'] = form['username'].strip()
        email = form['username']

        # Get the user with the given login name
        user = self._get_user(resource, context, email)
        if user is None:
            message = ERROR(u'There is no user identified as "{username}"',
                      username=email)
            context.message = message
            return

        # Check register key
        must_confirm = user.get_property('user_must_confirm')
        if not must_confirm:
            # Already confirmed
            message = ERROR(u'Your account has already been confirmed')
            context.message = message
            return
        elif form['key'] != must_confirm:
            message = ERROR(u'Your activation key is wrong')
            context.message = message
            return

        user.del_property('user_must_confirm')
        # We log-in user
        username = str(user.name)
        crypted = user.get_property('password')
        cookie = Password.encode('%s:%s' % (username, crypted))
        context.set_cookie('__ac', cookie, path='/')
        context.user = user

        # Ok
        message = INFO(u'Operation successful! Welcome.')
        return context.come_back(message, goto='/users/%s' % user.name)
Beispiel #20
0
 def get_metadata_schema(cls):
     # XXX Administrator must be a role
     return merge_dicts(BaseRoot.get_metadata_schema(),
                        administrators=Email(multiple=True))