def test_send(self): message = Bunch(id='foo') interface = Mailer(base_config) with pytest.raises(MailerNotRunning): interface.send(message) interface.start() #logging.getLogger().handlers[0].truncate() #messages = logging.getLogger().handlers[0].buffer assert interface.send(message) == (message, True) #assert messages[0] == "Attempting delivery of message foo." #assert messages[-1] == "Message foo delivered." message_fail = Bunch(id='bar', die=True) with pytest.raises(Exception): interface.send(message_fail) #assert messages[-4] == "Attempting delivery of message bar." #assert messages[-3] == "Acquired existing transport instance." #assert messages[-2] == "Shutting down transport due to unhandled exception." #assert messages[-1] == "Delivery of message bar failed." interface.stop()
def lookup(cls, identifier): uid, credential = identifier user = cls.objects.with_id(uid) if not user: return None cred = None for i in user.credentials: if i.identity == credential: cred = i break bundle = Bunch(identity=user, credential=cred) bundle.effective = [i for i in user.permissions] for cred in user.credentials: if cred.identity == identifier: for perm in cred.permissions: if perm.startswith('-'): bundle.effective.remove(perm[1:]) break bundle.effective.append(perm) break bundle.permissions = set(bundle.effective) return bundle
def test_send(self): message = Bunch(id='foo') interface = Mailer(base_config) self.assertRaises(MailerNotRunning, interface.send, message) interface.start() logging.getLogger().handlers[0].truncate() messages = logging.getLogger().handlers[0].buffer self.assertEqual(interface.send(message), (message, True)) self.assertEqual(messages[0].getMessage(), "Attempting delivery of message foo.") self.assertEqual(messages[-1].getMessage(), "Message foo delivered.") message_fail = Bunch(id='bar', die=True) self.assertRaises(Exception, interface.send, message_fail) self.assertEqual(messages[-4].getMessage(), "Attempting delivery of message bar.") self.assertEqual(messages[-3].getMessage(), "Acquired existing transport instance.") self.assertEqual(messages[-2].getMessage(), "Shutting down transport due to unhandled exception.") self.assertEqual(messages[-1].getMessage(), "Delivery of message bar failed.") interface.stop()
def bunchify(data, name=None): if isinstance(data, Bunch): return data if isinstance(data, list): if name == 'rowset': # we unpack these into a dictionary based on name return Bunch({i['name']: bunchify(i, 'rowset') for i in data}) return [bunchify(i) for i in data] if isinstance(data, dict): data = data.copy() if name == 'row' and 'row' in data: # Special case of CCP's silly key:value text. pass if name and name in data and not data.get(name, '').strip(): data.pop(name) if name == 'rowset' and 'name' in data: data.pop('name') if len(data) == 1 and isinstance(data.values()[0], dict): return bunchify(data.values()[0], data.keys()[0]) result = Bunch({ k: bunchify( [v] if k in ('row', ) and not isinstance(v, list) else v, k ) for k, v in data.iteritems() if k != 'rowset' }) if 'rowset' in data: rowset = bunchify(data['rowset'] if isinstance(data['rowset'], list) else [data['rowset']], 'rowset') result.update(rowset) if name == 'rowset': # rowsets always contain rows, even if there are no results result.setdefault('row', []) return result if isinstance(data, str): data = data.decode('utf-8') if isinstance(data, (str, unicode)): try: return number(data) except ValueError: pass try: return boolean(data) except ValueError: pass if ',' in data and (name in ('key', 'columns') or ' ' not in data): return array(data) return data
def __init__(self, config, prefix=None): self.manager, self.Manager = None, None self.Transport = None self.running = False self.config = config = Bunch(config) if prefix is not None: self.config = config = Bunch.partial(prefix, config) try: self.manager_config = manager_config = Bunch.partial('manager', config) except ValueError: self.manager_config = manager_config = Bunch() try: self.transport_config = transport_config = Bunch.partial('transport', config) except ValueError: self.transport_config = transport_config = Bunch() try: self.message_config = Bunch.partial('message', config) except ValueError: self.message_config = Bunch() self.Manager = Manager = self._load(config.manager, 'marrow.mailer.manager') if not Manager: raise LookupError("Unable to determine manager from specification: %r" % (config.manager, )) self.Transport = Transport = self._load(config.transport, 'marrow.mailer.transport') if not Transport: raise LookupError("Unable to determine transport from specification: %r" % (config.transport, )) self.manager = Manager(manager_config, partial(Transport, transport_config))
def __init__(self, config, prefix=None): self.manager, self.Manager = None, None self.Transport = None self.running = False self.config = config = Bunch(config) if prefix is not None: self.config = config = Bunch.partial(prefix, config) try: if 'manager' in config and isinstance(config.manager, dict): self.manager_config = manager_config = config.manager else: self.manager_config = manager_config = Bunch.partial('manager', config) except ValueError: # pragma: no cover self.manager_config = manager_config = Bunch() if isinstance(config.manager, basestring): warnings.warn("Use of the manager directive is deprecated; use manager.use instead.", DeprecationWarning) manager_config.use = config.manager try: if 'transport' in config and isinstance(config.transport, dict): self.transport_config = transport_config = Bunch(config.transport) else: self.transport_config = transport_config = Bunch.partial('transport', config) except ValueError: # pragma: no cover self.transport_config = transport_config = Bunch() if isinstance(config.transport, basestring): warnings.warn("Use of the transport directive is deprecated; use transport.use instead.", DeprecationWarning) transport_config.use = config.transport try: if 'message' in config and isinstance(config.message, dict): self.message_config = Bunch(config.message) else: self.message_config = Bunch.partial('message', config) except ValueError: # pragma: no cover self.message_config = Bunch() self.Manager = Manager = self._load(manager_config.use if 'use' in manager_config else 'immediate', 'marrow.mailer.manager') if not Manager: raise LookupError("Unable to determine manager from specification: %r" % (config.manager, )) if not isinstance(Manager, IManager): raise TypeError("Chosen manager does not conform to the manager API.") self.Transport = Transport = self._load(transport_config.use, 'marrow.mailer.transport') if not Transport: raise LookupError("Unable to determine transport from specification: %r" % (config.transport, )) if not isinstance(Transport, ITransport): raise TypeError("Chosen transport does not conform to the transport API.") self.manager = Manager(manager_config, partial(Transport, transport_config))
def test_partial(self): d1 = Bunch({'foo.bar': 1, 'foo.baz': 2, 'diz': 3}) d2 = Bunch.partial('foo', d1) self.assertEqual(d2.get('diz', None), None) self.assertEqual(d2.baz, 2) d2.bar = 4 self.assertEqual(d1['foo.bar'], 1) self.assertEqual(d1.foo.bar, 1) self.assertRaises(AttributeError, lambda: d1.bar.foo)
def native(self, data): from marrow.util.bunch import Bunch result = dict() data = data[self.name] if self.name in data else Bunch.partial(self.name, data) for child in self.children: if isinstance(child, NestedWidget): result.update(child.native(Bunch.partial(child.name, data))[0]) continue result[child.name] = child.native(data) return {self.name: result}, dict()
def native(self, data): from marrow.util.bunch import Bunch result = dict() data = data[self.name] if self.name in data else Bunch.partial( self.name, data) for child in self.children: if isinstance(child, NestedWidget): result.update(child.native(Bunch.partial(child.name, data))[0]) continue result[child.name] = child.native(data) return {self.name: result}, dict()
def post(self, ajax=False, **kw): data = Bunch(kw) data.password = (data.password, data.yubikey) if 'redirect' not in data: data.redirect = '/' if not web.auth.authenticate(data.identity, data.password): web.core.session['flash'] = dict(cls="error", title="Authentication Failure", message="Invalid username or password.") return 'login', dict(redirect=data.redirect, identity=data.identity) web.core.session['flash'] = dict(cls="success", title="Success", message="Successful authentication.") raise web.core.http.HTTPFound(location=data.redirect)
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 recurse(parts, target, source, indent=0): parts = list(parts) while parts: part = parts.pop(0) if hasattr(part.source, '__call__'): part.source = part.source(options) if hasattr(part.target, '__call__'): part.target = part.target(options) if isinstance(part, (Folder, File)) and not part.condition(options): # print("%sSkipping source %s %s..." % (" " * indent, part.__class__.__name__.lower(), part.source)) continue if isinstance(part, Folder): print("%sEntering %s..." % (" " * indent, part.target)) newtarget = path.join(target, part.target) if part.target else target if not path.exists(newtarget): os.makedirs(newtarget) recurse(part.children, newtarget, (source + '/' + part.source) if part.source else source, indent+1) elif isinstance(part, File): print("%sConstructing %s%s..." % (" " * indent, part.target, (" from %s" % (path.basename(part.source), )) if part.source != part.target else "")) # print("%s -> %s" % (source + '/' + part.source, path.join(target, part.target))) try: data = Bunch(settings=options) if hasattr(part.data, '__call__'): data.update(part.data(options)) else: data.update(part.data) _, content = self.engines(source + '/' + part.source, data) except: print("\nError constructing %s%s.\n" % (part.target, (" from %s" % (path.basename(part.source), )) if part.source != part.target else "")) raise with open(path.join(target, part.target), 'w') as fh: fh.write(content) elif hasattr(part, '__call__'): additional = part(self.options) parts.extend(additional)
def __call__(self, *credential, **payload): """Perform the RPC call while following CCP's caching guidelines.""" if len(credential) > 1: raise Exception("The only positional parameter allowed is the credentials object.") now = datetime.utcnow() uri = self.uri(self.name) # Define the keyID/vCode API key arguments, if we have credentials. if credential: payload['keyID'] = credential[0].key payload['vCode'] = credential[0].code # Hash the arguments in a reliable way by converting to text in a way which sorts the keys. payload_hash = sha256(EnhancedBencode().encode(payload)).hexdigest() # Examine the cache. cv = CachedAPIValue.objects( key = payload.get('keyID', None), name = self.name, arguments = payload_hash, expires__gte = now ).first() if cv and cv.current: log.info("Returning cached result of %s for key ID %d.", self.name, payload.get('keyID', -1)) return bunchify_lite(cv.result) log.info("Making query to %s for key ID %d.", self.name, payload.get('keyID', -1)) # Actually perform the query if a cached version could not be found. response = requests.post(uri, data=payload or None) response.raise_for_status() # We don't want the initial XML prefix. We should still check it, though. prefix, _, data = response.text.partition('\n') if prefix.strip() != "<?xml version='1.0' encoding='UTF-8'?>": raise Exception("Data returned doesn't seem to be XML!") data = xml(data)['eveapi'] result = bunchify(data['result'], 'result') data = Bunch(data) if len(result) == 1: result = getattr(result, result.keys()[0]) # Upsert (update if exists, create if it doesn't) the cache value. CachedAPIValue.objects( key = payload.get('keyID', None), name = self.name, arguments = payload_hash ).update_one( upsert = True, set__expires = datetime.strptime(data.cachedUntil, "%Y-%m-%d %H:%M:%S"), set__result = result ) return result
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 inner(cls, search): record = cls.get(search) if not record: return dict(success=False, message="No matching record found.") result = Bunch(success=True) def process(value): if isinstance(value, EVEEntity): if cls is EVEAlliance and isinstance( value, EVECorporation): return dict(id=value.identifier, name=value.name, joined=process(value.joined)) return dict(id=value.identifier, name=value.name) if hasattr(value, 'strftime'): return value.strftime('%y-%m-%d %H:%M:%S') if isinstance(value, list) or hasattr(value, '__iter__'): return [process(i) for i in value] return value for field in fields: result[_mapping.get(field, field)] = process(getattr(record, field)) return result
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 test_delete(self): d = Bunch(name='value') del d.name self.assertEqual(repr(d), 'Bunch({})') def error_test(): del d.foo self.assertRaises(AttributeError, error_test)
def __call__(self, *args, **kwargs): result = self.pool.post( self.path + (('/' + '/'.join(args)) if args else ''), data=kwargs, auth=SignedAuth(self.identity, self.private, self.public)) if not result.status_code == requests.codes.ok: return None return Bunch(result.json())
def __init__(self, application, config=dict(), prefix='auth.'): self.application = application prefix_length = len(prefix) our_config = Bunch(default_config.copy()) for i, j in config.iteritems(): if i.startswith(prefix): our_config[i[prefix_length:]] = j our_config.intercept = [i.strip() for i in array(our_config.intercept)] our_config.internal = boolean(our_config.internal) if our_config.lookup is None: raise Exception('You must define an authentication lookup method.') our_config.lookup = self.get_method(our_config.lookup) our_config.authenticate = self.get_method(our_config.authenticate) web.auth.config = our_config
def specification(self): """Determine the high-level script specification. Additionally, prepare the way for sub-command calling. """ spec = Bunch( name = None, author = None, version = None, copyright = None, license = None, url = None ) # TODO: Load some of this from setuptools. spec.update(getattr(self.callable, '_cmd_script_info', dict())) spec.callables = [ self.specification_for(self.callable, spec) ] return spec
def bunchify(data, name=None): if isinstance(data, Bunch): return data if isinstance(data, list): return [bunchify(i) for i in data] if isinstance(data, dict): if hasattr(data, 'iteritems'): bunch_data = {k: bunchify(v, k) for k, v in data.iteritems()} else: bunch_data = {k: bunchify(v, k) for k, v in data.items()} return Bunch(bunch_data) return data
def get(self, call, **kwargs): from newauth.models import APIKey, db cache_key = hash((self.base, call, frozenset(kwargs))) cached_data = redis.get(cache_key) if cached_data: cached_data = cPickle.loads(cached_data) if arrow.utcnow() < cached_data[0]: return cached_data[1] try: req = self.session.get(self.base + call + '.xml.aspx', params=kwargs) req.raise_for_status() except requests.exceptions.RequestException as e: raise e if req.status_code != 200: if req.status_code == requests.codes['not_found']: raise Exception( "{} is not available on the API server (404)".format( call.value)) elif req.status_code == requests.codes['forbidden']: if self.api_key and self.api_key.id: self.api_key.disabled = True db.session.add(self.api_key) db.session.commit() raise AuthenticationException(self.key_id) else: raise Exception("Eve API server exception.") request_data = req.text prefix, _, data = req.text.partition('\n') if prefix.strip() != "<?xml version='1.0' encoding='UTF-8'?>": raise Exception("Data returned doesn't seem to be XML!") if isinstance(data, unicode): data = data.encode('UTF-8') data = xml(data)['eveapi'] result = bunchify(data['result'], 'result') data = Bunch(data) if len(result) == 1: result = getattr(result, result.keys())[0] redis.set(cache_key, cPickle.dumps((arrow.get(data.cachedUntil), result), -1)) return result
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?", data=data) user = User(data.username, data.email, active=True) user.password = data.password user.save() authenticate(data.username, data.password) return 'json:', dict(success=True, location="/")
def post(self, **kw): data = Bunch(kw) record = EVECredential(data.key, data.code, owner=user.id) record.save() # If record is a character key: # Create character owned by user.id if request.is_xhr: return 'json:', { 'success': True, 'identifier': str(record.id), 'key': record.key, 'code': record.code } raise HTTPFound(location='/key/')
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, **kw): data = Bunch(kw) record = EVECredential(data.key, data.code, owner=user.id) try: record.save() record.importChars() if request.is_xhr: return 'json:', { 'success': True, 'identifier': str(record.id), 'key': record.key, 'code': record.code } except ValidationError: if request.is_xhr: return 'json:', { 'success': False, 'message': 'Validation error for Eve Credential: One or more fields are incorrect or missing' } raise HTTPFound(location='/key/')
def test_empty_creation(self): d = Bunch() assert not d
def test_attribute_read(self): d = Bunch() d.name = 'value' assert d.name == 'value'
def test_repr(self): d = Bunch() assert repr(d) == 'Bunch({})' d.name = 'value' self.assertEqual(repr(d), "Bunch({'name': 'value'})")
# encoding: utf-8 from unittest import TestCase from marrow.util.bunch import Bunch from marrow.util.escape import unescape PLAYERS = Bunch(alice=Bunch(name="Alice", gender='female'), bob=Bunch(name="Bob", gender='male'), everyone=Bunch(name="everyone", gender='group'), bender=Bunch(name='Bender', gender='i', role="bending robot")) CASES = [ (None, '%N', 'Anonymous'), (PLAYERS.alice, '%N welcomes you.', 'Alice welcomes you.'), (PLAYERS.alice, 'The book is %a.', 'The book is hers.'), (PLAYERS.alice, '%S loves coffee.', 'She loves coffee.'), (PLAYERS.alice, '%s %o %p %a %S %O %P %A %N', 'she her her hers She Her Her Hers Alice'), (PLAYERS.bob, '%s %o %p %a %S %O %P %A %N', 'he him his his He Him His His Bob'), (PLAYERS.everyone, '%s %o %p %a %S %O %P %A %N', 'they them their theirs They Them Their Theirs everyone'), (PLAYERS.bender, '%s %o %p %a %S %O %P %A %N', 'it it its its It It Its Its Bender'), ] def assert_expected(caller, testing, expected, obj=None): assert unescape(caller, testing, obj) == expected, "Expected '%s', returned '%s'." % (
def test_attribute_assignment(self): d = Bunch() d.name = 'value' assert hasattr(d, 'name') self.assertEqual(d['name'], 'value')
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")
import pkg_resources from marrow.util.bunch import Bunch # from web.extras.cmf.core.decorators import action, view __all__ = ['components', 'action', 'api', 'view', 'Action', 'View'] log = __import__('logging').getLogger(__name__) connection = None components = Bunch() models = Bunch() namespace = Bunch() # namespace.master = [dotted.get_dotted_filename(config.master)] if config.get('master', None) else [] for res in pkg_resources.iter_entry_points('contentment.component'): try: instance = res.load() if callable(instance): instance = instance() except: log.exception("Error scanning available CMF components. CMF unavailable.") break
yield last.split('/'), parent, False last = str(chunk) if isclass(current): current = current(context) yield last.split('/'), current, True if __debug__ and __name__ == '__main__': # pragma: no cover from marrow.util.bunch import Bunch from marrow.logging import Log, DEBUG request = Bunch(remainder='/') context = Bunch(log=Log(level=DEBUG).name(__file__), request=request) class Controller(object): def __init__(self, context): self._ctx = context class RootController(Controller): def __call__(self): return "Hello world!" router = ObjectDispatchDialect(dict()) for i,j,k in router(context, RootController): context.log.info(path=i,obj=j,final=k)
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 __init__(self, config, prefix=None): self.manager, self.Manager = None, None self.Transport = None self.running = False self.config = config = Bunch(config) if prefix is not None: self.config = config = Bunch.partial(prefix, config) try: if 'manager' in config and isinstance(config.manager, dict): self.manager_config = manager_config = config.manager else: self.manager_config = manager_config = Bunch.partial( 'manager', config) except ValueError: # pragma: no cover self.manager_config = manager_config = Bunch() if isinstance(config.manager, basestring): warnings.warn( "Use of the manager directive is deprecated; use manager.use instead.", DeprecationWarning) manager_config.use = config.manager try: if 'transport' in config and isinstance(config.transport, dict): self.transport_config = transport_config = Bunch( config.transport) else: self.transport_config = transport_config = Bunch.partial( 'transport', config) except ValueError: # pragma: no cover self.transport_config = transport_config = Bunch() if isinstance(config.transport, basestring): warnings.warn( "Use of the transport directive is deprecated; use transport.use instead.", DeprecationWarning) transport_config.use = config.transport try: if 'message' in config and isinstance(config.message, dict): self.message_config = Bunch(config.message) else: self.message_config = Bunch.partial('message', config) except ValueError: # pragma: no cover self.message_config = Bunch() self.Manager = Manager = self._load( manager_config.use if 'use' in manager_config else 'immediate', 'marrow.mailer.manager') if not Manager: raise LookupError( "Unable to determine manager from specification: %r" % (config.manager, )) if not isinstance(Manager, IManager): raise TypeError( "Chosen manager does not conform to the manager API.") self.Transport = Transport = self._load(transport_config.use, 'marrow.mailer.transport') if not Transport: raise LookupError( "Unable to determine transport from specification: %r" % (config.transport, )) if not isinstance(Transport, ITransport): raise TypeError( "Chosen transport does not conform to the transport API.") self.manager = Manager(manager_config, partial(Transport, transport_config))
# encoding: utf-8 import pkg_resources from web.extras.contentment import release from web.extras.contentment.api import IComponent from marrow.util.bunch import Bunch __all__ = ['PageComponent', 'controller', 'model', 'templates', 'engines'] log = __import__('logging').getLogger(__name__) engines = Bunch() class PageComponent(IComponent): title = "Page" summary = "An embeddable page of static content." description = None icon = 'base-page' group = "Basic Types" version = release.version author = release.author email = release.email url = release.url copyright = release.copyright license = release.license @property
def __init__(self): """Perform some startup work, like configuring the mail interface.""" super(RootController, self).__init__() adam.auth.util.mail = Mailer(Bunch(config).mail) adam.auth.util.mail.start()
def test_populated_creation(self): d = Bunch(name='value') self.assertEqual(d['name'], 'value') d = Bunch({'name': 'value'}) self.assertEqual(d['name'], 'value')
def construct_yaml_bunch(self, node): data = Bunch() yield data value = self.construct_mapping(node) data.update(value)
def test_death(self): transport = MockTransport(dict()) self.assertRaises(ZeroDivisionError, transport.deliver, Bunch(die=True))