def remove_character(self, name=None): if not name: return 'json:', dict(success=False, message=_("character name required")) q = EVECharacter.objects(name=name) assert q.count() <= 1 if q.count() != 1: return 'json:', dict(success=False, message=_("character not found")) c = q.first() r = self.group.rules[-1] if len(self.group.rules) else None if not r or not (isinstance(r, ACLList) and r.grant and not r.inverse and r.kind == 'c'): return 'json:', dict(success=False, message=_("Sorry, I don't know what to do!")) if not c.identifier in r.ids: return 'json:', dict(success=False, message=_("Character not found in last rule!")) r.ids.remove(c.identifier) if not r.ids: # If we just removed the last user in the rule, get rid of the rule. self.group.rules.pop(-1) success = self.group.save() if success: return 'json:', dict(success=True) return 'json:', dict(success=False, message=_("Failure updating group"))
def add_character(self, name=None): if not name: return 'json:', dict(success=False, message=_("character name required")) q = EVECharacter.objects(name=name) assert q.count() <= 1 if q.count() != 1: return 'json:', dict(success=False, message=_("character not found")) c = q.first() r = self.group.rules[-1] if len(self.group.rules) else None if not r or not (isinstance(r, ACLList) and r.grant and not r.inverse and r.kind == 'c'): r = ACLList(grant=True, inverse=False, kind='c', ids=[]) self.group.rules.append(r) if c.identifier in r.ids: return 'json:', dict(success=False, message=_("Character already in rule")) r.ids.append(c.identifier) success = self.group.save() if success: return 'json:', dict(success=True) return 'json:', dict(success=False, message=_("Failure updating group"))
def remove_character(self, name=None): if not name: return 'json:', dict(success=False, message=_("character name required")) q = EVECharacter.objects(name=name) assert q.count() <= 1 if q.count() != 1: return 'json:', dict(success=False, message=_("character not found")) c = q.first() r = self.group.rules[-1] if len(self.group.rules) else None if not r or not (isinstance(r, ACLList) and r.grant and not r.inverse and r.kind == 'c'): return 'json:', dict(success=False, message=_("Sorry, I don't know what to do!")) if not c.identifier in r.ids: return 'json:', dict( success=False, message=_("Character not found in last rule!")) r.ids.remove(c.identifier) if not r.ids: # If we just removed the last user in the rule, get rid of the rule. self.group.rules.pop(-1) success = self.group.save() if success: return 'json:', dict(success=True) return 'json:', dict(success=False, message=_("Failure updating group"))
def __post_recovery(self, **post): try: data = Bunch(reset_password_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) recovery = self.__get_recovery(data.email, data.recovery_key) if not recovery: return 'json:', dict(success=False, message=_("Sorry that recovery link has already expired"), location="/account/recover") passwd_ok, error_msg = _check_password(data.password, data.pass2) if not passwd_ok: return 'json:', dict(success=False, message=error_msg) #If the password isn't strong enough, reject it if(zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data) #set new password user = recovery.user user.password = data.password user.save() #remove recovery key recovery.delete() authenticate(user.username, data.password) return 'json:', dict(success=True, message=_("Password changed, forwarding ..."), location="/")
def __post_email(self, **post): try: data = Bunch(recover_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) user = lookup_email(data.email) if not user: user = lookup_email(data.email.lower()) if not user: # FixMe: possibly do send success any way, to prevent email address confirmation # - would be necessary for register as well return 'json:', dict(success=False, message=_("Unknown email."), data=post) send_recover_email(user) return 'json:', dict( success=True, message=_( "Recovery e-mail sent - " "please follow the instructions in that mail to restore your password" ))
def add(self): # TODO: mpAjax mime/multipart this to save on escaping the HTML. # https://github.com/getify/mpAjax return 'json:', dict( title = _("Add New API Key"), content = render('mako:brave.core.key.template.add', dict()), label = dict(label=_("Add Key"), kind='btn-success') )
def translate(self, lingua=None): try: set_lang(lingua) except LanguageError: return _("Invalid language selection.") return _("I now speak %(lingua)s.") % dict(lingua=lingua)
def create(self, id=None, title=None): if not id: return 'json:', dict(success=False, message=_("id required")) if not title: return 'json:', dict(success=False, message=_("title required")) g = Group.create(id, title, user) if not g: return 'json:', dict( success=False, message=_("group with that id already existed")) return 'json:', dict(success=True, id=g.id)
def post(self, id=None, title=None): if not id: return 'json:', dict(success=False, message=_("id required")) if not title: return 'json:', dict(success=False, message=_("title required")) g = Group.create(id, title, user) if not g: return 'json:', dict(success=False, message=_("group with that id already existed")) return 'json:', dict(success=True, id=g.id)
def post(self, **kw): data = Bunch(kw) try: data.key = int(data.key) if data.key <= KEY_RESET_FLOOR: return 'json:', dict(success=False, message=_("The key given (%d) must be above minimum reset floor value of %d. Please reset your EVE API Key." % (data.key, KEY_RESET_FLOOR)), field='key') except ValueError: return 'json:', dict(success=False, message=_("Key ID must be a number."), field='key') record = EVECredential(data.key, data.code, owner=user.id) try: record.save() #Necessary to guarantee that the pull finished before returning. record.pull() characters = [] for character in record.characters: characters.append(dict(identifier = character.identifier, name = character.name)) if request.is_xhr: return 'json:', dict( success = True, message = _("Successfully added EVE API key."), identifier = str(record.id), key = record.key, code = record.code, characters = characters, violation = record.violation ) except ValidationError: if request.is_xhr: return 'json:', dict( success = False, message = _("Validation error: one or more fields are incorrect or missing."), ) except NotUniqueError: return 'json:', dict( success = False, message = _("This key has already been added by another account."), ) raise HTTPFound(location='/key/')
def get(self): app = self.app if request.is_xhr: return 'brave.core.template.form', dict( kind = _("Application"), form = manage_form('/application/manage/{0}'.format(app.id)), data = dict( name = app.name, description = app.description, site = app.site, contact = app.contact, development = app.development, key = dict( public = app.key.public, private = app.key.private, ), required = app.mask.required, optional = app.mask.optional, groups = app.groups ) ) key = SigningKey.from_string(unhexlify(app.key.private), curve=NIST256p, hashfunc=sha256) return 'brave.core.application.template.view_app', dict( app = app, key = hexlify(key.get_verifying_key().to_string()), pem = key.get_verifying_key().to_pem() )
def get(self): app = self.app if request.is_xhr: return 'brave.core.template.form', dict( kind=_("Application"), form=manage_form('/application/manage/{0}'.format(app.id)), data=dict(name=app.name, description=app.description, site=app.site, contact=app.contact, development=app.development, key=dict( public=app.key.public, private=app.key.private, ), required=app.mask.required, optional=app.mask.optional, groups=app.groups)) key = SigningKey.from_string(unhexlify(app.key.private), curve=NIST256p, hashfunc=sha256) return 'brave.core.application.template.view_app', dict( app=app, key=hexlify(key.get_verifying_key().to_string()), pem=key.get_verifying_key().to_pem())
def get(self, ar): from brave.core.application.model import ApplicationGrant ar = self.ar(ar) u = user._current_obj() grant = ApplicationGrant.objects(user=u, application=ar.application).first() if not grant: # TODO: We need a 'just logged in' flag in the request. characters = list(u.characters.order_by('name').all()) if len(characters): default = u.primary or characters[0] else: return ('brave.core.template.authorize', dict(success=False, message=_("This application requires that you have a character connected to your" " account. Please <a href=\"/key/\">add an API key</a> to your account."), ar=ar)) return 'brave.core.template.authorize', dict(success=True, ar=ar, characters=characters, default=default) ngrant = ApplicationGrant(user=u, application=ar.application, mask=grant.mask, expires=datetime.utcnow() + timedelta(days=30), character=grant.character) ngrant.save() ar.user = u ar.grant = ngrant ar.expires = datetime.utcnow() + timedelta(minutes=10) # extend to allow time for verification ar.save() r = grant.delete() target = URL(ar.success) target.query.update(dict(token=str(ngrant.id))) raise HTTPFound(location=str(target))
def send_recover_email(user): """Sends a recovery-link to the specified user objects' email address""" # generate recovery key recovery_key = SystemRandom().randint(0, (2 << 62) - 1) # send email params = {'email': user.email, 'recovery_key': str(recovery_key)} mailer = util.mail message = mailer.new( to=user.email, subject=_("Password Recovery - Brave Collective Core Services")) #explicitley get the text contend for the mail mime, content = render("brave.core.account.template.mail/lost.txt", dict(params=params)) message.plain = content #explicitley get the html contend for the mail mime, content = render("brave.core.account.template.mail/lost.html", dict(params=params)) message.rich = content mailer.send(message) # store key in DB PasswordRecovery(user, recovery_key).save()
def _check_password(passwd1, passwd2): """checks the passed passwords for equality and length (could be extended to add minimal length, complexity, ...) Returns a Tuple, the first value is a Boolean that is True, if the password is ok, the second value is the error message, should it not be ok """ #check for empty password if not passwd1: return False, _("Please enter a password") if passwd1 != passwd2: return False, _("New passwords do not match.") if len(passwd2) > 100: return False, _("Password over 100 character limit") return True, None
def post(self, username=None, userMethod=None, ip=None, duplicate=None): # Have to be an admin to access admin pages. if not is_administrator: raise HTTPNotFound() # Seed the initial results. users = User.objects() # Limit to users with the specified username. if username: if userMethod == 'contains': users = users.filter(username__icontains=username) elif userMethod == 'starts': users = users.filter(username__istartswith=username) elif userMethod == 'is': users = users.filter(username__iexact=username) else: return 'json:', dict( success=False, message=_("You broke the web page. Good Job.")) # Limit to users with the specified IP address. if ip: users = users.filter(host=ip) # Limit to users with the specified duplicate status if duplicate.lower() == "ip": users = users.filter(other_accs_IP__exists=True) elif duplicate.lower() == "char": users = users.filter(other_accs_char_key__exists=True) return 'brave.core.admin.template.searchUser', dict(area='admin', result=users, success=True)
def post(self, username=None, userMethod=None, ip=None, duplicate=None): # Have to be an admin to access admin pages. if not is_administrator: raise HTTPNotFound() # Seed the initial results. users = User.objects() # Limit to users with the specified username. if username: if userMethod == 'contains': users = users.filter(username__icontains=username) elif userMethod == 'starts': users = users.filter(username__istartswith=username) elif userMethod == 'is': users = users.filter(username__iexact=username) else: return 'json:', dict(success=False, message=_("You broke the web page. Good Job.")) # Limit to users with the specified IP address. if ip: users = users.filter(host=ip) # Limit to users with the specified duplicate status if duplicate.lower() == "ip": users = users.filter(other_accs_IP__exists=True) elif duplicate.lower() == "char": users = users.filter(other_accs_char_key__exists=True) return 'brave.core.admin.template.searchUser', dict(area='admin', result=users, success=True)
def delete(self): log.info("REVOKE %r %r", self.grant.user, self.grant.application) try: self.grant.delete() except: log.exception("Error revoking grant.") return 'json:', dict( success=False, message=_("Unable to revoke application permission.")) if request.is_xhr: return 'json:', dict( success=True, message=_("Successfully revoked application permissions.")) raise HTTPFound(location='/application/')
def set_rules(self, rules, really=False): rules = json.loads(rules) rule_objects = [] log.debug(rules) log.debug(really) def listify(rule, field): if field not in rule: rule[field] = [] elif not isinstance(r[field], list): rule[field] = [rule[field]] for r in rules: grant = r['grant'] == "true" inverse = r['inverse'] == "true" if r['type'] == "list": listify(r, 'names') cls = ACLList.target_class(r['kind']) ids = [ cls.objects(name=name).first().identifier for name in r['names'] ] rule_objects.append( ACLList(grant=grant, inverse=inverse, kind=r['kind'], ids=ids)) elif r['type'] == "key": rule_objects.append( ACLKey(grant=grant, inverse=inverse, kind=r['kind'])) elif r['type'] == "title": listify(r, 'titles') rule_objects.append( ACLTitle(grant=grant, inverse=inverse, titles=r['titles'])) elif r['type'] == "role": listify(r, 'roles') rule_objects.append( ACLRole(grant=grant, inverse=inverse, roles=r['roles'])) elif r['type'] == "mask": rule_objects.append( ACLMask(grant=grant, inverse=inverse, mask=r['mask'])) log.debug(rule_objects) if not really: log.debug("not really") return "json:", "\n".join( [r.human_readable_repr() for r in rule_objects]) log.debug("really!") self.group.rules = rule_objects success = self.group.save() log.debug(success) if success: return 'json:', dict(success=True) return 'json:', dict(success=True, message=_("unimplemented"))
def __post_email(self, **post): try: data = Bunch(recover_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) user = lookup_email(data.email) if not user: user = lookup_email(data.email.lower()) if not user: # FixMe: possibly do send success any way, to prevent email address confirmation # - would be necessary for register as well return 'json:', dict(success=False, message=_("Unknown email."), data=post) send_recover_email(user) return 'json:', dict(success=True, message=_("Recovery e-mail sent - " "please follow the instructions in that mail to restore your password"))
def delete(self): log.info("REVOKE %r %r", self.grant.user, self.grant.application) try: self.grant.delete() except: log.exception("Error revoking grant.") return 'json:', dict( success = False, message = _("Unable to revoke application permission.") ) if request.is_xhr: return 'json:', dict( success = True, message = _("Successfully revoked application permissions.") ) raise HTTPFound(location='/application/')
def __post_recovery(self, **post): try: data = Bunch(reset_password_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) recovery = self.__get_recovery(data.email, data.recovery_key) if not recovery: return 'json:', dict( success=False, message=_("Sorry that recovery link has already expired"), location="/account/recover") passwd_ok, error_msg = _check_password(data.password, data.pass2) if not passwd_ok: return 'json:', dict(success=False, message=error_msg) #If the password isn't strong enough, reject it if (zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict( success=False, message= _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters." ), data=data) #set new password user = recovery.user user.password = data.password user.save() #remove recovery key recovery.delete() authenticate(user.username, data.password) return 'json:', dict(success=True, message=_("Password changed, forwarding ..."), location="/")
def get(self, redirect=None, **get): if redirect is None: referrer = request.referrer redirect = '/' if not referrer or referrer.endswith(request.script_name) else referrer try: data = Bunch(reset_password_form.native(get)[0]) except Exception as e: if config.get('debug', False): raise raise HTTPFound(location='/') # Todo redirect to recover with error message if not data.recovery_key: # no key passed, so show email entry form = recover_form(dict(redirect=redirect)) button_label = _("Recover") else: form = reset_password_form(dict(email=data.email, recovery_key=data.recovery_key)) button_label = _("Set Password") return "brave.core.account.template.recover", dict(form=form, button_label=str(button_label))
def post(self, identity, password, remember=False, redirect=None): if not authenticate(identity, password): if request.is_xhr: return 'json:', dict(success=False, message=_("Invalid user name or password.")) return self.get(redirect) if request.is_xhr: return 'json:', dict(success=True, location=redirect or '/') raise HTTPFound(location=redirect or '/')
def delete(self): log.info("Deleted application %s owned by %s", self.app, self.app.owner) self.app.delete() if request.is_xhr: return 'json:', dict( success = True, message = _("Successfully deleted application registration.") ) raise HTTPFound(location='/application/manage/')
def delete(self): log.info("Deleted application %s owned by %s", self.app, self.app.owner) self.app.delete() if request.is_xhr: return 'json:', dict( success=True, message=_("Successfully deleted application registration.")) raise HTTPFound(location='/application/manage/')
def post(self, **post): try: data = Bunch(register_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) if not data.username or not data.email or not data.password or data.password != data.pass2: return 'json:', dict(success=False, message=_("Missing data or passwords do not match."), data=data) #Make sure that the provided email address is a valid form for an email address v = EmailValidator() email = data.email email, err = v.validate(email) if err: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) #If the password isn't strong enough, reject it if(zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data) #Ensures that the provided username and email are lowercase user = User(data.username.lower(), data.email.lower(), active=True) user.password = data.password try: user.save() except ValidationError: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) except NotUniqueError: return 'json:', dict(success=False, message=_("Either the username or email address provided is already taken."), data=data) authenticate(user.username, data.password) return 'json:', dict(success=True, location="/")
def post(self, character=None, charMethod=None, alliance=None, corporation=None, group=None): # Have to be an admin to access admin pages. if not is_administrator: raise HTTPNotFound() # Seed the initial results. chars = EVECharacter.objects() # Go through and check all of the possible posted values # Limit chars to the character name entered. if character: if charMethod == 'contains': chars = chars.filter(name__icontains=character) elif charMethod == 'starts': chars = chars.filter(name__istartswith=character) elif charMethod == 'is': chars = chars.filter(name__iexact=character) else: return 'json:', dict( success=False, message=_("You broke the web page. Good Job.")) # Limit to characters in the specified alliance. if alliance: alliance = EVEAlliance.objects(name=alliance).first() chars = chars.filter(alliance=alliance) # Limit to characters in the specified corporation. if corporation: corporation = EVECorporation.objects(name=corporation).first() chars = chars.filter(corporation=corporation) # Limit to characters in the specified group. if group: groupList = [] for c in chars: if group in c.tags: groupList.append(c.id) chars = chars.filter(id__in=groupList) return 'brave.core.admin.template.searchChar', dict(area='admin', result=chars, success=True)
def get(self, redirect=None, **get): if redirect is None: referrer = request.referrer redirect = '/' if not referrer or referrer.endswith( request.script_name) else referrer try: data = Bunch(reset_password_form.native(get)[0]) except Exception as e: if config.get('debug', False): raise raise HTTPFound( location='/') # Todo redirect to recover with error message if not data.recovery_key: # no key passed, so show email entry form = recover_form(dict(redirect=redirect)) button_label = _("Recover") else: form = reset_password_form( dict(email=data.email, recovery_key=data.recovery_key)) button_label = _("Set Password") return "brave.core.account.template.recover", dict( form=form, button_label=str(button_label))
def post(self, **post): try: data = Bunch(register_form.native(post)[0]) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) if not data.username or not data.email or not data.password or data.password != data.pass2: return 'json:', dict( success=False, message=_("Missing data or passwords do not match."), data=data) #Make sure that the provided email address is a valid form for an email address v = EmailValidator() email = data.email email, err = v.validate(email) if err: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) #If the password isn't strong enough, reject it if (zxcvbn.password_strength(data.password).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict( success=False, message= _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters." ), data=data) #Ensures that the provided username and email are lowercase user = User(data.username.lower(), data.email.lower(), active=True) user.password = data.password try: user.save() except ValidationError: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) except NotUniqueError: return 'json:', dict( success=False, message= _("Either the username or email address provided is already taken." ), data=data) authenticate(user.username, data.password) return 'json:', dict(success=True, location="/")
def get(self, ar): from brave.core.application.model import ApplicationGrant ar = self.ar(ar) u = user._current_obj() grant = ApplicationGrant.objects(user=u, application=ar.application).first() if not grant: # TODO: We need a 'just logged in' flag in the request. characters = list(u.characters.order_by('name').all()) if len(characters): default = u.primary or characters[0] else: return ( 'brave.core.template.authorize', dict( success=False, message= _("This application requires that you have a character connected to your" " account. Please <a href=\"/key/\">add an API key</a> to your account." ), ar=ar)) return 'brave.core.template.authorize', dict(success=True, ar=ar, characters=characters, default=default) ngrant = ApplicationGrant(user=u, application=ar.application, mask=grant.mask, expires=datetime.utcnow() + timedelta(days=30), character=grant.character) ngrant.save() ar.user = u ar.grant = ngrant ar.expires = datetime.utcnow() + timedelta( minutes=10) # extend to allow time for verification ar.save() r = grant.delete() target = URL(ar.success) target.query.update(dict(token=str(ngrant.id))) raise HTTPFound(location=str(target))
def set_rules(self, rules, really=False): rules = json.loads(rules) rule_objects = [] log.debug(rules) log.debug(really) def listify(rule, field): if field not in rule: rule[field] = [] elif not isinstance(r[field], list): rule[field] = [rule[field]] for r in rules: grant = r['grant'] == "true" inverse = r['inverse'] == "true" if r['type'] == "list": listify(r, 'names') cls = ACLList.target_class(r['kind']) ids = [cls.objects(name=name).first().identifier for name in r['names']] rule_objects.append(ACLList(grant=grant, inverse=inverse, kind=r['kind'], ids=ids)) elif r['type'] == "key": rule_objects.append(ACLKey(grant=grant, inverse=inverse, kind=r['kind'])) elif r['type'] == "title": listify(r, 'titles') rule_objects.append(ACLTitle(grant=grant, inverse=inverse, titles=r['titles'])) elif r['type'] == "role": listify(r, 'roles') rule_objects.append(ACLRole(grant=grant, inverse=inverse, roles=r['roles'])) elif r['type'] == "mask": rule_objects.append(ACLMask(grant=grant, inverse=inverse, mask=r['mask'])) log.debug(rule_objects) if not really: log.debug("not really") return "json:", "\n".join([r.human_readable_repr() for r in rule_objects]) log.debug("really!") self.group.rules = rule_objects success = self.group.save() log.debug(success) if success: return 'json:', dict(success=True) return 'json:', dict(success=True, message=_("unimplemented"))
def post(self, identity, password, remember=False, redirect=None): # First try with the original input success = authenticate(identity, password) if not success: # Try lowercase if it's an email or username, but not if it's an OTP if '@' in identity or len(identity) != 44: success = authenticate(identity.lower(), password) if not success: if request.is_xhr: return 'json:', dict(success=False, message=_("Invalid user name or password.")) return self.get(redirect) if request.is_xhr: return 'json:', dict(success=True, location=redirect or '/') raise HTTPFound(location=redirect or '/')
def post(self, character=None, charMethod=None, alliance=None, corporation=None, group=None): # Have to be an admin to access admin pages. if not is_administrator: raise HTTPNotFound() # Seed the initial results. chars = EVECharacter.objects() # Go through and check all of the possible posted values # Limit chars to the character name entered. if character: if charMethod == 'contains': chars = chars.filter(name__icontains=character) elif charMethod == 'starts': chars = chars.filter(name__istartswith=character) elif charMethod == 'is': chars = chars.filter(name__iexact=character) else: return 'json:', dict(success=False, message=_("You broke the web page. Good Job.")) # Limit to characters in the specified alliance. if alliance: alliance = EVEAlliance.objects(name=alliance).first() chars = chars.filter(alliance=alliance) # Limit to characters in the specified corporation. if corporation: corporation = EVECorporation.objects(name=corporation).first() chars = chars.filter(corporation=corporation) # Limit to characters in the specified group. if group: groupList = [] for c in chars: if group in c.tags: groupList.append(c.id) chars = chars.filter(id__in=groupList) return 'brave.core.admin.template.searchChar', dict(area='admin', result=chars, success=True)
def post(self, identity, password, remember=False, redirect=None): # First try with the original input success = authenticate(identity, password) if not success: # Try lowercase if it's an email or username, but not if it's an OTP if '@' in identity or len(identity) != 44: success = authenticate(identity.lower(), password) if not success: if request.is_xhr: return 'json:', dict( success=False, message=_("Invalid user name or password.")) return self.get(redirect) if request.is_xhr: return 'json:', dict(success=True, location=redirect or '/') raise HTTPFound(location=redirect or '/')
def get(self): if user.admin: adminRecords = {record for record in Application.objects() if record.owner != user._current_obj()} else: adminRecords = {} records = Application.objects(owner=user._current_obj()) if request.is_xhr: return 'brave.core.template.form', dict( kind = _("Application"), form = manage_form(), data = None, ) return 'brave.core.application.template.manage_apps', dict( area = 'apps', records = records, adminRecords = adminRecords )
def get(self): if user.admin: adminRecords = { record for record in Application.objects() if record.owner != user._current_obj() } else: adminRecords = {} records = Application.objects(owner=user._current_obj()) if request.is_xhr: return 'brave.core.template.form', dict( kind=_("Application"), form=manage_form(), data=None, ) return 'brave.core.application.template.manage_apps', dict( area='apps', records=records, adminRecords=adminRecords)
def send_recover_email(user): """Sends a recovery-link to the specified user objects' email address""" # generate recovery key recovery_key = SystemRandom().randint(0, (2<< 62)-1) # send email params = {'email': user.email, 'recovery_key': str(recovery_key)} mailer = util.mail message = mailer.new(to=user.email, subject=_("Password Recovery - Brave Collective Core Services")) #explicitley get the text contend for the mail mime, content = render("brave.core.account.template.mail/lost.txt", dict(params=params)) message.plain = content #explicitley get the html contend for the mail mime, content = render("brave.core.account.template.mail/lost.html", dict(params=params)) message.rich = content mailer.send(message) # store key in DB PasswordRecovery(user, recovery_key).save()
def post(self, **kw): data = Bunch(kw) try: data.key = int(data.key) if data.key <= int(config['core.minimum_key_id']): return 'json:', dict( success=False, message=_( "The key given (%d) must be above minimum reset floor value of %d. " "Please reset your EVE API Key." % (data.key, int(config['core.minimum_key_id']))), field='key') except ValueError: return 'json:', dict(success=False, message=_("Key ID must be a number."), field='key') record = EVECredential(data.key, data.code, owner=user.id) try: record.save() #Necessary to guarantee that the pull finished before returning. record.pull() characters = [] for character in record.characters: characters.append( dict(identifier=character.identifier, name=character.name)) if request.is_xhr: return 'json:', dict( success=True, message=_("Successfully added EVE API key."), identifier=str(record.id), key=record.key, code=record.code, characters=characters, violation=record.violation) except ValidationError: if request.is_xhr: return 'json:', dict( success=False, message= _("Validation error: one or more fields are incorrect or missing." ), ) except NotUniqueError: if EVECredential.objects(key=data.key): # Mark both of these accounts as duplicates to each other. acc = User.objects(username=user.username).first() other = EVECredential.objects(key=data.key).first().owner User.add_duplicate(acc, other) return 'json:', dict( success=False, message= _("This key has already been added to this or another account." ), ) raise HTTPFound(location='/key/')
def ugettext_alt(self): return _('This works!')
def post(self, **kw): data = Bunch(kw) try: data.key = int(data.key) if data.key <= int(config["core.minimum_key_id"]): return ( "json:", dict( success=False, message=_( "The key given (%d) must be above minimum reset floor value of %d. " "Please reset your EVE API Key." % (data.key, int(config["core.minimum_key_id"])) ), field="key", ), ) except ValueError: return "json:", dict(success=False, message=_("Key ID must be a number."), field="key") record = EVECredential(data.key, data.code, owner=user.id) try: record.save() # Necessary to guarantee that the pull finished before returning. record.pull() characters = [] for character in record.characters: characters.append(dict(identifier=character.identifier, name=character.name)) if request.is_xhr: return ( "json:", dict( success=True, message=_("Successfully added EVE API key."), identifier=str(record.id), key=record.key, code=record.code, characters=characters, violation=record.violation, ), ) except ValidationError: if request.is_xhr: return ( "json:", dict(success=False, message=_("Validation error: one or more fields are incorrect or missing.")), ) except NotUniqueError: if EVECredential.objects(key=data.key): # Mark both of these accounts as duplicates to each other. acc = User.objects(username=user.username).first() other = EVECredential.objects(key=data.key).first().owner User.add_duplicate(acc, other) return ( "json:", dict(success=False, message=_("This key has already been added to this or another account.")), ) raise HTTPFound(location="/key/")
def hello(self, name): return _("Hello, %(name)s!") % dict(name=name)
def post(self, **post): try: data = Bunch(post) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) query = dict(active=True) query[b'username'] = data.id user = User.objects(**query).first() if data.form == "changepassword": passwd_ok, error_msg = _check_password(data.passwd, data.passwd1) if not passwd_ok: return 'json:', dict(success=False, message=error_msg, data=data) if isinstance(data.old, unicode): data.old = data.old.encode('utf-8') if not User.password.check(user.password, data.old): return 'json:', dict(success=False, message=_("Old password incorrect."), data=data) #If the password isn't strong enough, reject it if (zxcvbn.password_strength(data.passwd).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict( success=False, message= _("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters." ), data=data) user.password = data.passwd user.save() elif data.form == "addotp": if isinstance(data.password, unicode): data.password = data.password.encode('utf-8') identifier = data.otp client = yubico.Yubico(config['yubico.client'], config['yubico.key'], boolean(config.get('yubico.secure', False))) if not User.password.check(user.password, data.password): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) try: status = client.verify(identifier, return_response=True) except: return 'json:', dict(success=False, message=_("Failed to contact YubiCloud."), data=data) if not status: return 'json:', dict(success=False, message=_("Failed to verify key."), data=data) if not User.addOTP(user, identifier[:12]): return 'json:', dict(success=False, message=_("YubiKey already exists."), data=data) elif data.form == "removeotp": identifier = data.otp if not User.removeOTP(user, identifier[:12]): return 'json:', dict(success=False, message=_("YubiKey invalid."), data=data) elif data.form == "configureotp": if isinstance(data.password, unicode): data.password = data.password.encode('utf-8') rotp = True if 'rotp' in data else False if not User.password.check(user.password, data.password): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) user.rotp = rotp user.save() #Handle the user attempting to delete their account elif data.form == "deleteaccount": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') #Make the user enter their username so they know what they're doing. if not user.username == data.username.lower(): return 'json:', dict(success=False, message=_("Username incorrect."), data=data) #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) #Make them type "delete" exactly if not data.confirm == "delete": return 'json:', dict( success=False, message=_( "Delete was either misspelled or not lowercase."), data=data) #Delete the user account and then deauthenticate the browser session log.info("User %s authorized the deletion of their account.", user) user.delete() deauthenticate() #Redirect user to the root of the server instead of the settings page return 'json:', dict(success=True, location="/") #Handle the user attempting to change the email address associated with their account elif data.form == "changeemail": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) #Check that the two provided email addresses match if not data.newEmail.lower() == data.newEmailConfirm.lower(): return 'json:', dict( success=False, message=_("Provided email addresses do not match."), data=data) #Make sure that the provided email address is a valid form for an email address v = EmailValidator() email = data.newEmail email, err = v.validate(email) if err: return 'json:', dict( success=False, message=_("Invalid email address provided."), data=data) #Make sure that the new email address is not already taken count = User.objects.filter(**{ "email": data.newEmail.lower() }).count() if not count == 0: return 'json:', dict( success=False, message=_("The email address provided is already taken."), data=data) #Change the email address in the database and catch any email validation exceptions that mongo throws user.email = data.newEmail.lower() try: user.save() except ValidationError: return 'json:', dict( success=False, message=_("Invalid email address provided."), data=data) except NotUniqueError: return 'json:', dict( success=False, message=_("The email address provided is already taken."), data=data) #Handle the user attempting to merge 2 accounts together elif data.form == "mergeaccount": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') if isinstance(data.passwd2, unicode): data.passwd2 = data.passwd2.encode('utf-8') #Make the user enter their username so they know what they're doing. if user.username != data.username.lower( ) and user.username != data.username: return 'json:', dict(success=False, message=_("First username incorrect."), data=data) #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("First password incorrect."), data=data) #Make sure the user isn't trying to merge their account into itself. if data.username.lower() == data.username2.lower(): return 'json:', dict( success=False, message=_("You can't merge an account into itself."), data=data) #Make the user enter the second username so we can get the User object they want merged in. if not User.objects( username=data.username2.lower()) and not User.objects( username=data.username2): return 'json:', dict( success=False, message=_("Unable to find user by second username."), data=data) other = User.objects(username=data.username2).first() if not other: other = User.objects(username=data.username2.lower()).first() #Check whether the user's supplied password is correct if not User.password.check(other.password, data.passwd2): return 'json:', dict(success=False, message=_("Second password incorrect."), data=data) #Make them type "merge" exactly if data.confirm != "merge": return 'json:', dict( success=False, message=_("Merge was either misspelled or not lowercase."), data=data) log.info("User %s merged account %s into %s.", user.username, other.username, user.username) user.merge(other) #Redirect user to the root of the server instead of the settings page return 'json:', dict(success=True, location="/") else: return 'json:', dict(success=False, message=_("Form does not exist."), location="/") return 'json:', dict(success=True, location="/account/settings")
def post(self, **post): try: data = Bunch(post) except Exception as e: if config.get('debug', False): raise return 'json:', dict(success=False, message=_("Unable to parse data."), data=post, exc=str(e)) query = dict(active=True) query[b'username'] = data.id query_user = User.objects(**query).first() if query_user.id != user.id: raise HTTPForbidden if data.form == "changepassword": passwd_ok, error_msg = _check_password(data.passwd, data.passwd1) if not passwd_ok: return 'json:', dict(success=False, message=error_msg, data=data) if isinstance(data.old, unicode): data.old = data.old.encode('utf-8') if not User.password.check(user.password, data.old): return 'json:', dict(success=False, message=_("Old password incorrect."), data=data) #If the password isn't strong enough, reject it if(zxcvbn.password_strength(data.passwd).get("score") < MINIMUM_PASSWORD_STRENGTH): return 'json:', dict(success=False, message=_("Password provided is too weak. please add more characters, or include lowercase, uppercase, and special characters."), data=data) user.password = data.passwd user.save() elif data.form == "addotp": if isinstance(data.password, unicode): data.password = data.password.encode('utf-8') identifier = data.otp client = yubico.Yubico( config['yubico.client'], config['yubico.key'], boolean(config.get('yubico.secure', False)) ) if not User.password.check(user.password, data.password): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) try: status = client.verify(identifier, return_response=True) except: return 'json:', dict(success=False, message=_("Failed to contact YubiCloud."), data=data) if not status: return 'json:', dict(success=False, message=_("Failed to verify key."), data=data) if not User.addOTP(user, identifier[:12]): return 'json:', dict(success=False, message=_("YubiKey already exists."), data=data) elif data.form == "removeotp": identifier = data.otp if not User.removeOTP(user, identifier[:12]): return 'json:', dict(success=False, message=_("YubiKey invalid."), data=data) elif data.form == "configureotp": if isinstance(data.password, unicode): data.password = data.password.encode('utf-8') rotp = True if 'rotp' in data else False if not User.password.check(user.password, data.password): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) user.rotp = rotp user.save() #Handle the user attempting to delete their account elif data.form == "deleteaccount": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') #Make the user enter their username so they know what they're doing. if not user.username == data.username.lower(): return 'json:', dict(success=False, message=_("Username incorrect."), data=data) #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) #Make them type "delete" exactly if not data.confirm == "delete": return 'json:', dict(success=False, message=_("Delete was either misspelled or not lowercase."), data=data) #Delete the user account and then deauthenticate the browser session log.info("User %s authorized the deletion of their account.", user) user.delete() deauthenticate() #Redirect user to the root of the server instead of the settings page return 'json:', dict(success=True, location="/") #Handle the user attempting to change the email address associated with their account elif data.form == "changeemail": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("Password incorrect."), data=data) #Check that the two provided email addresses match if not data.newEmail.lower() == data.newEmailConfirm.lower(): return 'json:', dict(success=False, message=_("Provided email addresses do not match."), data=data) #Make sure that the provided email address is a valid form for an email address v = EmailValidator() email = data.newEmail email, err = v.validate(email) if err: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) #Make sure that the new email address is not already taken count = User.objects.filter(**{"email": data.newEmail.lower()}).count() if not count == 0: return 'json:', dict(success=False, message=_("The email address provided is already taken."), data=data) #Change the email address in the database and catch any email validation exceptions that mongo throws user.email = data.newEmail.lower() try: user.save() except ValidationError: return 'json:', dict(success=False, message=_("Invalid email address provided."), data=data) except NotUniqueError: return 'json:', dict(success=False, message=_("The email address provided is already taken."), data=data) #Handle the user attempting to merge 2 accounts together elif data.form == "mergeaccount": if isinstance(data.passwd, unicode): data.passwd = data.passwd.encode('utf-8') if isinstance(data.passwd2, unicode): data.passwd2 = data.passwd2.encode('utf-8') #Make the user enter their username so they know what they're doing. if user.username != data.username.lower() and user.username != data.username: return 'json:', dict(success=False, message=_("First username incorrect."), data=data) #Check whether the user's supplied password is correct if not User.password.check(user.password, data.passwd): return 'json:', dict(success=False, message=_("First password incorrect."), data=data) #Make sure the user isn't trying to merge their account into itself. if data.username.lower() == data.username2.lower(): return 'json:', dict(success=False, message=_("You can't merge an account into itself."), data=data) #Make the user enter the second username so we can get the User object they want merged in. if not User.objects(username=data.username2.lower()) and not User.objects(username=data.username2): return 'json:', dict(success=False, message=_("Unable to find user by second username."), data=data) other = User.objects(username=data.username2).first() if not other: other = User.objects(username=data.username2.lower()).first() #Check whether the user's supplied password is correct if not User.password.check(other.password, data.passwd2): return 'json:', dict(success=False, message=_("Second password incorrect."), data=data) #Make them type "merge" exactly if data.confirm != "merge": return 'json:', dict(success=False, message=_("Merge was either misspelled or not lowercase."), data=data) log.info("User %s merged account %s into %s.", user.username, other.username, user.username) user.merge(other) #Redirect user to the root of the server instead of the settings page return 'json:', dict(success=True, location="/") else: return 'json:', dict(success=False, message=_("Form does not exist."), location="/") return 'json:', dict(success=True, location="/account/settings")
def index(self): return _('Hello world!')