def _do_db_instances_for_user(self): """ Instances for user creation """ self._dbSettings = SettingDAO(self._ctx_min) self._dbSignupData = SignupDataDAO(self._ctx_min) self._dbUser = UserDAO(self._ctx_min) self._dbSocialNetworkUser = SocialNetworkUserDAO(self._ctx_min) self._dbUserProfile = UserProfileDAO(self._ctx_min) self._dbUserChannel = UserChannelDAO(self._ctx_min) self._dbUserChannelGroup = UserChannelGroupDAO(self._ctx_min) self._dbAddress = AddressDAO(self._ctx_min) self._dbUserAddress = UserAddressDAO(self._ctx_min) self._dbMetaKey= MetaKeyDAO(self._ctx_min) self._dbUserMeta = UserMetaDAO(self._ctx_min) self._dbGroup = GroupDAO(self._ctx_min) self._dbGroupSys = GroupSysDAO(self._ctx_min) self._dbParam = ParamDAO(self._ctx_min) self._dbCoreParam = CoreParameterDAO(self._ctx_min) self._dbInvitation = InvitationDAO(self._ctx_min)
class SiteService ( CommonService ): @validation() def _authen_user(self): if self._f()['authSource'] == K.FACEBOOK and self._f()['socialId'] != '': self._ctx.user = self._authenticate_user_soc_net(self._f()['socialId'], self._f()['socialToken'], self._f()['authSource'], 'facebook', _m.ERR_wrong_password) else: self._ctx.user = self._authenticate_user(self._f()['username'], self._f()['password'], 'password', _m.ERR_wrong_password) logger.debug('user: %s' % (self._ctx.user)) @validation() def _validate_user_not_signed_up(self): """Validate user and email in system in case sign up with user/password. In case signup with social networks, only validate that username does not exist.""" if self._f()['authSource'] == K.PASSWORD: self._validate_not_exists([ [self._dbUser, {'username': self._f()['username']}, 'username', _m.ERR_ximpia_id], [self._dbUser, {'email': self._f()['email']}, 'email', _m.ERR_email] ]) else: self._validate_not_exists([ [self._dbUser, {'username': self._f()['username']}, 'username', _m.ERR_ximpia_id], [self._dbUser, {'email': self._f()['email']}, 'email', _m.ERR_email], [self._dbSocialNetworkUser, {'socialId': self._f()['socialId']}, 'socialNet', _m.ERR_social_id_exists] ]) @validation() def _validate_invitation_pending(self, invitation_code): """ Validates that invitation is pending """ setting = self._get_setting(K.SET_SITE_SIGNUP_INVITATION) logger.debug('_validate_invitation_pending :: setting: %s value: %s' % (K.SET_SITE_SIGNUP_INVITATION, setting.is_checked())) if setting.is_checked(): self._validate_exists([ [self._dbInvitation, {'invitationCode': invitation_code, 'status': K.PENDING}, 'invitationCode', _m.ERR_invitation_not_valid] ]) @validation() def _validate_invitation_not_used(self): """ Validates that invitation is valid: Checks that invitation has not been used in case invitations defined in settings """ setting = self._get_setting(K.SET_SITE_SIGNUP_INVITATION) logger.debug('_validateInvitationNotUsed :: setting: %s value: %s' % (K.SET_SITE_SIGNUP_INVITATION, setting.is_checked())) if setting.is_checked(): self._validate_not_exists([ [self._dbInvitation, {'invitationCode': self._f()['invitationCode'], 'status': K.USED}, 'invitationCode', _m.ERR_invitation_not_valid] ]) def _create_user(self): """ Create user Will create user and related information 1. Creates django user 2. Sets password 3. Creates UserChannel 4. Obtains params statusActive, addressTypePersonal 5. Gets or create address with city and country 6. Creates UserProfile with user and status active 7. Creates UserAddress with userProfile, address and addressTypePersonal 8. Creates user meta variable HAS_VALIDATED_EMAIL to 'True' 9. In case social network signup, links socialId, socialToken 10. Associates django groups and ximpia groups to user ** Returns** None """ # System User user = self._dbUser.create(username=self._f()['username'], email=self._f()['email'], first_name=self._f()['firstName'], last_name=self._f()['lastName']) if self._f()['authSource'] == 'password': user.set_password(self._f()['password']) user.save() # Ximpia User userChannel = self._dbUserChannel.create(user=user, name=K.USER, title=self._f()['firstName'], userCreateId=user.id) # Profile (Address, UserProfile, UserAddress) statusActive = self._dbParam.get_user_status_active() address, created = self._dbAddress.get_create(city=self._f()['city'], country=self._f()['country']) addressTypePersonal = self._dbParam.get_address_type_personal() userProfile = self._dbUserProfile.create(user=user, status=statusActive) userAddress = self._dbUserAddress.create(userProfile=userProfile, address=address, type=addressTypePersonal) # User Meta keyEmail = self._dbMetaKey.get(name=K.KEY_HAS_VALIDATED_EMAIL) self._dbUserMeta.create(user=user, meta=keyEmail, value='True') # Social networks if self._f()['authSource'] != 'password': socialNetwork = self._dbCoreParam.get(mode=CoreK.NET, name=self._f()['authSource']) self._dbSocialNetworkUser.create(user=user, socialNetwork=socialNetwork, socialId=self._f()['socialId'], token=self._f()['socialToken']) # Groups userGroupId = json.loads(self._f()['params'])['userGroup'] groupSys = self._dbGroupSys.get(id=userGroupId) user.groups.add(groupSys) group = self._dbGroup.get(group__group=groupSys) self._dbUserChannelGroup.create(userChannel=userChannel, group=group) # Invitation setInvitation = self._get_setting(K.SET_SITE_SIGNUP_INVITATION) if setInvitation.is_checked() and self._f()['invitationCode'] != '': invitation = self._dbInvitation.get(invitationCode=self._f()['invitationCode']) invitation.status = K.USED invitation.save() @validation() def _validate_user(self): """Validate user: Check user password""" self._ctx.user = self._authenticate_user(self._ctx.user, self._f()['password'], 'password', _m.ERR_wrong_password) @validation() def _validate_reminder(self, username, reminderId): newDate = date.today() logger.debug('_validateReminder :: New Password Data : username: %s newDate: %s reminderId: %s' % (username, newDate, reminderId)) # Show actual password, new password and confirm new password # 'resetPasswordDate__lte' : newDate}, 'noField', _m.ERR_changePassword], self._validate_exists([ [self._dbUser, {'username': username}, 'username', _m.ERR_change_password], [self._dbUserMeta, { 'user__username': username, 'meta__name': K.META_REMINDER_ID, 'value': str(reminderId)}, 'noField', _m.ERR_change_password], ]) # Validate reset password date logger.debug('_validateReminder :: validate reset date...') reset_date_str = self._dbUserMeta.get(user__username=username, meta__name=K.META_RESET_PASSWORD_DATE).value if reset_date_str != '': reset_date_fields = reset_date_str.split('-') resetDate = date(year=int(reset_date_fields[0]), month=int(reset_date_fields[1]), day=int(reset_date_fields[2])) logger.debug('_validateReminder :: today: %s resetDate: %s' % (date.today(), resetDate)) if date.today() > resetDate: # show error self._addError('noField', _m.ERR_change_password) else: self._addError('noField', _m.ERR_change_password) @validation() def _validate_email_exist(self): self._validate_exists([ [self._dbUser, {'email': self._f()['email']}, 'email', _m.ERR_email_does_not_exist] ]) def _do_db_instances_for_user(self): """ Instances for user creation """ self._dbSettings = SettingDAO(self._ctx_min) self._dbSignupData = SignupDataDAO(self._ctx_min) self._dbUser = UserDAO(self._ctx_min) self._dbSocialNetworkUser = SocialNetworkUserDAO(self._ctx_min) self._dbUserProfile = UserProfileDAO(self._ctx_min) self._dbUserChannel = UserChannelDAO(self._ctx_min) self._dbUserChannelGroup = UserChannelGroupDAO(self._ctx_min) self._dbAddress = AddressDAO(self._ctx_min) self._dbUserAddress = UserAddressDAO(self._ctx_min) self._dbMetaKey= MetaKeyDAO(self._ctx_min) self._dbUserMeta = UserMetaDAO(self._ctx_min) self._dbGroup = GroupDAO(self._ctx_min) self._dbGroupSys = GroupSysDAO(self._ctx_min) self._dbParam = ParamDAO(self._ctx_min) self._dbCoreParam = CoreParameterDAO(self._ctx_min) self._dbInvitation = InvitationDAO(self._ctx_min) @view(forms.LoginForm) def view_login(self): """Checks if user is logged in. If true, get login user information in the context ** Returns ** Shows view login when not authenticated. Else, shows user login home when no value in cookie, otherwise would show value from cookie.""" # Check if login: logger.debug('login...') self._add_attr('isSocialLogged', False) if not self._ctx.user.is_authenticated(): logger.debug('viewLogin :: User not authenticated...') # no login: login form self._set_main_form(forms.LoginForm()) # Popup - Password reminder self._add_form(forms.PasswordReminderForm()) else: # We must redirect to homeLogin or other views if self._ctx.cookies.has_key(K.COOKIE_LOGIN_REDIRECT) and len(self._ctx.cookies[K.COOKIE_LOGIN_REDIRECT]) != 0: # We redirect to cookie value self._show_view(self._ctx.cookies[K.COOKIE_LOGIN_REDIRECT]) else: self._show_view(K.Views.HOME_LOGIN) @view(DefaultForm) def view_logout(self): """Show logout view""" pass @view(DefaultForm) def view_home_login(self): """Show home after login""" pass @action(forms.LoginForm) def login(self): """ Performs the login action. Puts workflow parameter username, write context variables userChannel and session. ** Returns ** Does login action and shows view user area home or view name from cookie variable in case set. """ logger.debug('***************************************************') logger.debug('login...' ) logger.debug('***************************************************') logger.debug('login :: authSource: %s' % (self._f()['authSource'])) self._authen_user() logger.debug('login :: user: %s' % (self._ctx.user)) self._login() logger.debug('login :: Session: %s' % (self._ctx.session)) logger.debug('login :: user: %s' % (self._ctx.user) ) logger.debug('login :: cookies: %s' % (self._ctx.cookies)) user_channel_name = self._get_user_channel_name() logger.debug('login :: userChannelName: %s' % (user_channel_name)) self._dbUserChannel = UserChannelDAO(self._ctx_min) self._ctx.userChannel = self._dbUserChannel.get(user=self._ctx.user, name=user_channel_name) self._ctx.session['userChannel'] = self._ctx.userChannel logger.debug('login :: userChannel: %s' % (self._ctx.userChannel)) # Redirect if self._ctx.cookies.has_key(K.COOKIE_LOGIN_REDIRECT) and len(self._ctx.cookies[K.COOKIE_LOGIN_REDIRECT]) != 0: self._show_view(self._ctx.cookies[K.COOKIE_LOGIN_REDIRECT]) self._set_cookie(K.COOKIE_LOGIN_REDIRECT, '') else: self._show_view(K.Views.HOME_LOGIN) @action(forms.UserSignupInvitationForm) def signup(self): """ Signup user **Attributes** **Returns** """ # Instances self._do_db_instances_for_user() # Business Validation self._validate_user_not_signed_up() self._validate_invitation_not_used() if self._f()['authSource'] != K.PASSWORD: self._create_user() # set ok message self._set_ok_msg('OK_SOCIAL_SIGNUP') else: # user/password. Save in temp table user data activation_code = random.randrange(10, 100) logger.debug('doUser :: activation_code: %s' % (activation_code)) form_serialized = base64.encodestring(self._f().serialize_JSON()) self._dbSignupData.delete_if_exists(user=self._f()['username'], is_real=True) self._dbSignupData.create(user=self._f()['username'], data=form_serialized, activationCode=activation_code) # Send email to user to validate email xml_message = self._dbSettings.get(name__name='Msg/Site/Signup/User/_en').value logger.debug(xml_message) logger.debug('path: %s' % (self._ctx.path)) EmailService.send(xml_message, {'scheme': settings.XIMPIA_SCHEME, 'host': settings.XIMPIA_BACKEND_HOST, 'appSlug': K.Slugs.SITE, 'activate': K.Slugs.ACTIVATE_USER, 'firstName': self._f()['firstName'], 'user': self._f()['username'], 'activationCode': activation_code}, settings.XIMPIA_WEBMASTER_EMAIL, [self._f()['email']]) # set ok message self._set_ok_msg('OK_USER_SIGNUP') @view(forms.ActivateUserForm) def view_activation_user(self): """Confirmation message for user activation """ pass @workflow_action(forms.ActivateUserForm) def activate_user(self, username, activation_code): """Create user in system with validation link from email. Only used in case auth source is user/password. """ # Instances self._do_db_instances_for_user() logger.debug('activate_user...') # Logic try: form_str_64 = self._dbSignupData.get(user=username).data except: raise XpMsgException(None, _('User was already activated')) form_dict = json.loads(base64.decodestring(form_str_64)) form = forms.UserSignupInvitationForm(form_dict, ctx=self._ctx) self._set_form(form) # validate form again self._validate_user_not_signed_up() # Create user self._create_user() self._dbSignupData.delete_if_exists(user=username, is_real=True) @view(forms.UserSignupInvitationForm) def view_signup(self, invitation_code=None): """Show signup form. Get get invitation code. """ self._dbInvitation = self._instances(InvitationDAO)[0] logger.debug('viewSignup :: invitationCode: %s' % (invitation_code)) self._add_attr('isSocialLogged', False) set_invitation = self._get_setting(K.SET_SITE_SIGNUP_INVITATION) self._validate_invitation_pending(invitation_code) if invitation_code != None and set_invitation.is_checked(): # Add invitation code to form form_signup invitation = self._dbInvitation.get(invitationCode=invitation_code, status=K.PENDING) self._put_form_value('invitationCode', invitation_code) self._put_form_value('email', invitation.email) self._f().disable_fields(['invitationCode', 'email']) @workflow_action(DefaultForm) def logout(self): """Logout user """ self._logout() @view(forms.UserChangePasswordForm) def view_change_password(self): """Change password form with current password and new password """ self._put_form_value('username', self._ctx.user.username) @action(forms.UserChangePasswordForm) def change_password(self): """Change password from user area """ self._dbUser = self._instances(UserDAO)[0] self._validate_user() user = self._dbUser.get(username= self._ctx.user) user.set_password(self._f()['newPassword']) user.save() @view(forms.ChangePasswordForm) def view_reminder_new_password(self, username=None, reminder_id=None): """Shows form to enter new password and confirm new password. Save button will call doNewPassword. ** Attributes ** * ``username`` (str): username * ``reminderId`` (str): reminderId """ self._dbUser, self._dbUserMeta = self._instances(UserDAO, UserMetaDAO) self._validate_reminder(username, reminder_id) self._put_form_value('username', username) self._f().put_param_list(username=username) @action(forms.PasswordReminderForm) def request_reminder(self): """Checks that email exists, then send email to user with reset link """ logger.debug('requestReminder...') self._dbUser, self._dbSetting, self._dbUserMeta, self._dbMetaKey = self._instances(UserDAO, SettingDAO, UserMetaDAO, MetaKeyDAO) self._validate_email_exist() # Update User user = self._dbUser.get(email = self._f()['email']) days = self._get_setting(K.SET_REMINDER_DAYS).value new_date = date.today() + timedelta(days=int(days)) # Write reminderId and resetPasswordDate reminder_id = str(random.randint(1, 999999)) metas = self._dbMetaKey.metas([K.META_REMINDER_ID, K.META_RESET_PASSWORD_DATE]) self._dbUserMeta.save_meta(user, metas, { K.META_REMINDER_ID: reminder_id, K.META_RESET_PASSWORD_DATE: str(new_date)}) # Send email with link to reset password. Link has time validation xml_message = self._dbSetting.get(name__name='Msg/Site/Login/PasswordReminder/_en').value EmailService.send(xml_message, { 'home': settings.XIMPIA_HOME, 'appSlug': K.Slugs.SITE, 'viewSlug': K.Slugs.REMINDER_NEW_PASSWORD, 'firstName': user.first_name, 'userAccount': user.username, 'reminderId': reminder_id}, settings.XIMPIA_WEBMASTER_EMAIL, [self._f()['email']]) logger.debug('requestReminder :: sent Email') self._set_ok_msg('OK_PASSWORD_REMINDER') @action(forms.ChangePasswordForm) def finalize_reminder(self): """Saves new password, it does authenticate and login user. """ self._dbUser, self._dbUserMeta = self._instances(UserDAO, UserMetaDAO) user = self._dbUser.get(username= self._f().get_param('username')) user.set_password(self._f()['newPassword']) user.save() # Remove reminder data so that it is not used again self._dbUserMeta.search(meta__name__in=[K.META_REMINDER_ID, K.META_RESET_PASSWORD_DATE]).update(value='')