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='./')
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), }
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)
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}
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')
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)
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
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)
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='./')
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)
def test_Email(self): for name, result in {'*****@*****.**':True, 'toto@':False}.iteritems(): self.assertEqual(Email.is_valid(name), result)
def is_valid(cls, value): return Email.is_valid(value)
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
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
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
def test_Email(self): emails = {"*****@*****.**": True, "*****@*****.**": True, "toto@": False} for name, result in emails.iteritems(): self.assertEqual(Email.is_valid(name), result)
class Email_Field(Metadata_Field): datatype = Email() size = 40
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)
def get_metadata_schema(cls): # XXX Administrator must be a role return merge_dicts(BaseRoot.get_metadata_schema(), administrators=Email(multiple=True))