def _check(credentials, request): login, password = credentials['login'], credentials['password'] users = find_users(request.context) user = users.get(login=login) if user is None or user['password'] != get_sha_password(password): return None return [user['id']] + list(user['groups'])
def login_view(context, request): login = '' password = '' came_from = request.params.get('came_from') message = request.params.get('reason') if 'form.submitted' in request.params: login = request.params['login'] password = request.params['password'] users = find_users(context) info = users.get_by_login(login) if info: if info['password'] == get_sha_password(password): headers = remember(request, info['id']) if came_from: return HTTPFound(location=came_from, headers=headers) else: url = resource_url(context, request, 'login') return HTTPFound(location=url, headers=headers) else: message = 'Wrong password' else: message = 'No such user name %s' % login logged_in = authenticated_userid(request) return dict( api = API(context, request), login = login, password = password, logged_in = logged_in, came_from = came_from, message = message, )
def test_handle_submit_utf8_password(self): password = u'password\xe1' reg = get_current_registry() config = Configurator(reg) renderer = config.testing_add_template('templates/reset_complete.pt') request = self.request request.params['key'] = '0' * 40 self._setupUsers() context = self.context context['profiles'] = testing.DummyModel() profile = context['profiles']['me'] = testing.DummyModel() profile.password_reset_key = '0' * 40 controller = self._makeOne(context, request) converted = {'login': '******', 'password': password} import datetime keytime = datetime.datetime.now() profile.password_reset_time = keytime response = controller.handle_submit(converted) self.failUnless(hasattr(renderer, 'api')) self.assertEqual(renderer.api.page_title, 'Password Reset Complete') renderer.assert_(login='******', password=password) self.failUnless(profile.password_reset_key is None) self.failUnless(profile.password_reset_time is None) user = self.context.users.get(login='******') from repoze.who.plugins.zodb.users import get_sha_password self.assertEqual(user['password'], get_sha_password(password.encode('utf8')))
def login(request): logged_in = authenticated_userid(request) login_url = request.resource_url(request.context, "login") referrer = request.url if referrer == login_url: referrer = "/" # never use the login form itself as came_from came_from = request.params.get("came_from", referrer) message = "" login = "" password = "" if "form.submitted" in request.params: login = request.params["login"] password = request.params["password"] user_folder = request.context["users"] user = user_folder.get(login) if user is not None and user["password"] == get_sha_password(password): headers = remember(request, login) return HTTPFound(location=came_from, headers=headers) message = "The username or password that you entered was not correct, try " "again" return dict( message=message, url=request.application_url + "/login", came_from=came_from, login=login, password=password, logged_in=logged_in, )
def __call__(self, v): # XXX: repoze.who.plugins.zodb.interfaces.IUsers # really should have a check_password(id, password) # method. We shouldn't have to use get_sha_password # directly. enc = get_sha_password(v) if enc != self.user['password']: raise Invalid('Incorrect password', v)
def change_password_view(context, request): min_pw_length = get_setting(context, 'min_pw_length') form = ChangePasswordForm(min_pw_length=min_pw_length) if 'form.cancel' in request.POST: return HTTPFound(location=model_url(context, request)) if 'form.submitted' in request.POST: try: converted = form.validate(request.POST) users = find_users(context) userid = context.__name__ user = users.get_by_id(userid) # check the old password # XXX: repoze.who.plugins.zodb.interfaces.IUsers # really should have a check_password(id, password) # method. We shouldn't have to use get_sha_password # directly. enc = get_sha_password(converted['old_password']) if enc != user['password']: raise CustomInvalid({'old_password': '******'}) users.change_password(userid, converted['password']) # send email system_name = get_setting(context, 'system_name', 'KARL') mail = karl.mail.Message() admin_email = get_setting(context, 'admin_email') mail["From"] = "%s Administrator <%s>" % (system_name, admin_email) mail["To"] = "%s <%s>" % (context.title, context.email) mail["Subject"] = "%s Password Change Notification" % system_name system_name = get_setting(context, 'system_name', 'KARL') body = render_template( "templates/email_change_password.pt", login=user['login'], password=converted['password'], system_name=system_name, ) if isinstance(body, unicode): body = body.encode("UTF-8") mail.set_payload(body, "UTF-8") mail.set_type("text/html") recipients = [context.email] mailer = getUtility(IMailDelivery) mailer.send(admin_email, recipients, mail) path = model_url(context, request) msg = '?status_message=Password%20changed' return HTTPFound(location=path+msg) except Invalid, e: fielderrors = e.error_dict fill_values = form.convert(request.POST)
def handle_submit(self, converted): context = self.context request = self.request users = self.users userid = self.userid user = self.user if user is not None: login = converted.get('login') login_changed = users.get_by_login(login) != user if (login_changed and (users.get_by_id(login) is not None or users.get_by_login(login) is not None or login in context)): msg = "Login '%s' is already in use" % login raise ValidationError(login=msg) objectEventNotify(ObjectWillBeModifiedEvent(context)) if user is not None: # Set new login try: users.change_login(userid, converted['login']) except ValueError, e: raise ValidationError(login=str(e)) # Set group memberships user_groups = self.user_groups chosen_groups = set(converted['groups']) for group, group_title in self.group_options: if group in chosen_groups and group not in user_groups: users.add_user_to_group(userid, group) if group in user_groups and group not in chosen_groups: users.remove_user_from_group(userid, group) # Edit password if converted.get('password', None): new_password = converted['password'] sha_password = get_sha_password(new_password) if context.last_passwords is None: context.last_passwords = PersistentList() if sha_password in context.last_passwords: msg = "Please use a password that was not previously used" raise ValidationError(password=msg) users.change_password(userid, new_password) context.last_passwords.append(sha_password) if len(context.last_passwords) > 10: context.last_passwords = context.last_passwords[1:] self.request.session['password_expired'] = False context.password_expiration_date = (datetime.utcnow() + timedelta(days=180))
def test_success(self): from karl.testing import DummyUsers context = DummyProfile() context.__name__ = 'me' parent = testing.DummyModel() parent.__name__ = '' parent.__parent__ = None context.__parent__ = parent context.title = 'Me' context.email = '*****@*****.**' parent.users = DummyUsers() parent.users.add('me', 'me', self._old_password(), []) request = testing.DummyRequest({ 'form.submitted': 1, 'old_password': '******', 'password': '******', 'password_confirm': 'newnewnew', }) renderer = testing.registerDummyRenderer( 'templates/change_password.pt') from repoze.sendmail.interfaces import IMailDelivery from karl.testing import DummyMailer mailer = DummyMailer() testing.registerUtility(mailer, IMailDelivery) response = self._callFUT(context, request) from repoze.who.plugins.zodb.users import get_sha_password new_enc = get_sha_password('newnewnew') self.assertEqual(parent.users.get_by_id('me')['password'], new_enc) self.assertEqual(response.location, 'http://example.com/me/?status_message=Password%20changed') self.assertEqual(len(mailer), 1) msg = mailer.pop() self.assertEqual(msg.mto, ['*****@*****.**']) self.assertEqual(msg.mfrom, "*****@*****.**")
def handle_submit(self, converted): context = self.context users = find_users(context) userid = context.__name__ new_password = converted['password'] sha_password = get_sha_password(new_password) if context.last_passwords is None: context.last_passwords = PersistentList() if sha_password in context.last_passwords: msg = "Please use a password that was not previously used" raise ValidationError(password=msg) users.change_password(userid, new_password) context.last_passwords.append(sha_password) if len(context.last_passwords) > 10: context.last_passwords = context.last_passwords[1:] self.request.session['password_expired'] = False context.password_expiration_date = (datetime.utcnow() + timedelta(days=180)) path = resource_url(context, self.request) msg = '?status_message=Password%20changed' return HTTPFound(location=path+msg)
def handle_submit(self, converted): context = self.context users = find_users(context) userid = context.__name__ new_password = converted['password'] sha_password = get_sha_password(new_password) if context.last_passwords is None: context.last_passwords = PersistentList() if sha_password in context.last_passwords: msg = "Please use a password that was not previously used" raise ValidationError(password=msg) users.change_password(userid, new_password) context.last_passwords.append(sha_password) if len(context.last_passwords) > 10: context.last_passwords = context.last_passwords[1:] self.request.session['password_expired'] = False context.password_expiration_date = (datetime.utcnow() + timedelta(days=180)) path = resource_url(context, self.request) msg = '?status_message=Password%20changed' return HTTPFound(location=path + msg)
def test_handle_submit(self): from repoze.who.plugins.zodb.users import get_sha_password controller = self._makeOne(self.context, self.request) converted = {} converted['home_path'] = '/home_path' converted['password'] = '******' converted['login'] = '******' converted['groups'] = ['group.KarlAdmin'] response = controller.handle_submit(converted) context = self.context self.assertEqual(context.home_path, '/home_path') user = self.users.get_by_id('profile') self.assertEqual(user['password'], get_sha_password('secret')) self.assertEqual(user['login'], 'newlogin') self.assertEqual(self.users.added_groups, [('profile', 'group.KarlAdmin')]) self.assertEqual(self.users.removed_groups, [('profile', 'group.KarlLovers')]) self.assertEqual(response.location, 'http://example.com/profile/' '?status_message=User%20edited') # make sure the www. URLs get prepended converted['website'] = 'www.example.com' controller.handle_submit(converted) self.assertEqual(self.context.website, 'http://www.example.com') # try again w/ a login already in use context['inuse'] = testing.DummyModel() converted['login'] = '******' from repoze.bfg.formish import ValidationError self.assertRaises(ValidationError, controller.handle_submit, converted) # try again w/ special login value that will trigger ValueError converted['login'] = '******' self.assertRaises(ValidationError, controller.handle_submit, converted)
def change_password(self, userid, password): from repoze.who.plugins.zodb.users import get_sha_password self._by_id[userid]["password"] = get_sha_password(password)
def password_authenticator(users, login, password): user = users.get(login=login) if user and user['password'] == get_sha_password(password): return user['id']
def handle_submit(self, converted): context = self.context request = self.request userid = converted['login'] users = self.users if (users.get_by_id(userid) is not None or users.get_by_login(userid) is not None): msg = "User ID '%s' is already in use" % userid raise ValidationError(login=msg) profile = context.get(userid) if profile is not None: if profile.security_state == 'inactive': url = resource_url(profile, request, 'reactivate.html') self.reactivate_user = dict(userid=userid, url=url) msg = ("User ID '%s' is used by a previously deactivated " "user. Perhaps you mean to reactivate this user. " "See link above."% userid) else: msg = "User ID '%s' is already in use" % userid raise ValidationError(login=msg) search = ICatalogSearch(context) count, docids, resolver = search( interfaces=[IProfile], email=converted['email'] ) if count: msg = 'Email address is already in use by another user(s).' if count == 1: profile = resolver(docids[0]) if profile.security_state == 'inactive': url = resource_url(profile, request, 'reactivate.html') userid = profile.__name__ self.reactivate_user = dict(userid=userid, url=url) msg = ("Email address is in use by a previously " "deactivated user. Perhaps you mean to reactivate " "this user. See link above.") raise ValidationError(email=msg) # If user was previously invited to join any communities, those # invitations are no longer needed. count, docids, resolver = search( interfaces=[IInvitation], email=converted['email']) for docid in docids: invitation = resolver(docid) del invitation.__parent__[invitation.__name__] users.add(userid, userid, converted['password'], converted['groups']) _normalize_websites(converted) kw = {} for k, v in converted.items(): if k in ('login', 'password', 'password_confirm', 'photo', 'groups'): continue kw[k] = v profile = create_content(IProfile, **kw) profile.modified_by = authenticated_userid(request) password = get_sha_password(converted['password']) profile.last_passwords = PersistentList([password]) context[userid] = profile workflow = get_workflow(IProfile, 'security', context) if workflow is not None: workflow.initialize(profile) try: handle_photo_upload(profile, converted) except Invalid, e: raise ValidationError(**e.error_dict)
def _old_password(self): from repoze.who.plugins.zodb.users import get_sha_password return get_sha_password('oldoldold')
def handle_submit(self, converted): context = self.context request = self.request userid = converted['login'] users = self.users if (users.get_by_id(userid) is not None or users.get_by_login(userid) is not None): msg = "User ID '%s' is already in use" % userid raise ValidationError(login=msg) profile = context.get(userid) if profile is not None: if profile.security_state == 'inactive': url = resource_url(profile, request, 'reactivate.html') self.reactivate_user = dict(userid=userid, url=url) msg = ("User ID '%s' is used by a previously deactivated " "user. Perhaps you mean to reactivate this user. " "See link above." % userid) else: msg = "User ID '%s' is already in use" % userid raise ValidationError(login=msg) search = ICatalogSearch(context) count, docids, resolver = search(interfaces=[IProfile], email=converted['email']) if count: msg = 'Email address is already in use by another user(s).' if count == 1: profile = resolver(docids[0]) if profile.security_state == 'inactive': url = resource_url(profile, request, 'reactivate.html') userid = profile.__name__ self.reactivate_user = dict(userid=userid, url=url) msg = ("Email address is in use by a previously " "deactivated user. Perhaps you mean to reactivate " "this user. See link above.") raise ValidationError(email=msg) # If user was previously invited to join any communities, those # invitations are no longer needed. count, docids, resolver = search(interfaces=[IInvitation], email=converted['email']) for docid in docids: invitation = resolver(docid) del invitation.__parent__[invitation.__name__] users.add(userid, userid, converted['password'], converted['groups']) _normalize_websites(converted) kw = {} for k, v in converted.items(): if k in ('login', 'password', 'password_confirm', 'photo', 'groups'): continue kw[k] = v profile = create_content(IProfile, **kw) profile.modified_by = authenticated_userid(request) password = get_sha_password(converted['password']) profile.last_passwords = PersistentList([password]) context[userid] = profile workflow = get_workflow(IProfile, 'security', context) if workflow is not None: workflow.initialize(profile) try: handle_photo_upload(profile, converted) except Invalid, e: raise ValidationError(**e.error_dict)
def test_handle_submit_full(self): testing.registerAdapter(lambda *arg: DummyImageFile, (ICommunityFile,), IContentFactory) self.request.POST = MultiDict([ ('__start__', u'names_fieldset:mapping'), ('first_name', u'Ad'), ('last_name', u'Min'), ('email', u'*****@*****.**'), ('__end__', u'names_fieldset:mapping'), ('__start__', u'passwords:mapping'), ('__start__', u'password:mapping'), ('value', u'newpass'), ('confirm', u'newpass'), ('__end__', u'password:mapping'), ('__end__', u'passwords:mapping'), ('__start__', u'profile_image:mapping'), ('__start__', u'photo:mapping'), ('upload', DummyUpload(filename='test.jpg', mimetype='image/jpeg', data=one_pixel_jpeg)), ('__end__', u'photo:mapping'), ('__end__', u'profile_image:mapping'), ('__start__', u'details:mapping'), ('position', u'missionary'), ('organization', u'foo'), ('biography', u'my biog'), ('__start__', u'websites:sequence'), ('url',u'http://one.example.com'), ('url',u'http://two.example.com'), ('__end__', u'websites:sequence'), ('country', u'AF'), ('__start__', u'social_networks:mapping'), ('twitter', u'@mytwitter'), ('facebook', u'myfacebook'), ('__end__', u'social_networks:mapping'), ('__end__', u'details:mapping'), ('save', u'save'), ]) controller = self._makeOne() response = controller() self.assertEqual( response.location, # dunno why model_url doesn't quite work here 'http://example.comadmin/?status_message=DummyProfile+edited' ) # stuff we changed self.assertEqual(self.context.firstname,'Ad') self.assertEqual(self.context.lastname,'Min') self.assertEqual(self.context.email,'*****@*****.**') self.assertEqual(self.context.country,'AF') self.assertEqual(self.context.position,'missionary') self.assertEqual(self.context.organization,'foo') self.assertEqual(self.context.biography,'my biog') self.assertEqual(self.context.websites,[ 'http://one.example.com', 'http://two.example.com', ]) # no social stuff, none has been added self.assertEqual( self.context.categories['social']['facebook'].id, 'myfacebook') self.assertEqual( self.context.categories['social']['twitter'].id, '@mytwitter') # check profile image self.assertEqual(self.context['photo'].data, one_pixel_jpeg) # check password has changed self.assertEqual( self.context.users.get('admin')['password'], get_sha_password('newpass')) # check modified_by is recorded self.assertEqual(self.context.modified_by,'auth_user_id')
def _makeOne(self): from karl.views.forms.validators import CorrectUserPassword user = {'password': get_sha_password(self.password)} return CorrectUserPassword(user)