示例#1
0
def token_to_object(request, strict=True):
    """ Processes the "Authorization" param in the header and returns an http
    response OR a user object. Requires the application's initialized JWT to
    work. """
    # khoa's back door - chop this whole block when he gets CORS sorted out
    if request.method == "POST" and request.json is not None and request.json.get(
            'user_id', None) is not None:
        logger.warn(
            "'user_id' key in POST body; attempting Khoa-style token-less auth..."
        )
        try:
            user_oid = ObjectId(request.json['user_id'])
        except Exception as e:
            msg = "User OID '%s' does not look like an OID!" % request.json[
                'user_id']
            logger.error(msg)
            logger.error(e)
            raise utils.InvalidUsage(msg, status_code=422)
        try:
            return User(_id=user_oid)
        except Exception as e:
            msg = "The OID '%s' does not belong to any known user! %s" % (
                user_oid, e)
            logger.error(msg)
            raise utils.InvalidUsage(msg, status_code=401)

    #   real auth workflow starts here
    # first, get the token or bail
    auth_token = request.headers.get("Authorization", None)
    if auth_token is None:
        msg = "'Authorization' header missing!"
        logger.error(msg)
        raise utils.InvalidUsage(msg, status_code=401)

    # now, try to decode the token and get a dict
    try:
        if strict:
            decoded = jwt.decode(auth_token, secret_key, verify=True)
            user_dict = dict(json.loads(decoded["identity"]))
            return User(_id=user_dict["_id"]["$oid"])
        else:
            user_dict = refresh_authorization(auth_token)
            return User(_id=user_dict["_id"])
    except jwt.DecodeError:
        logger.error("Incorrectly formatted token!")
        logger.error("Token contents: |%s|" % auth_token)
    except Exception as e:
        logger.exception(e)

    raise utils.InvalidUsage("Incoming JWT could not be processed!",
                             status_code=422)
示例#2
0
    def check_request_params(self,
                             keys=[],
                             verbose=True,
                             raise_exception=True):
        """ Checks self.params for the presence of all keys specified in 'keys'
        list. Returns True if they're present and False if they're not.

        Set 'verbose' to True if you want to log validation failures as errors.
        """

        for k in keys:
            if k not in self.params.keys():
                if verbose:
                    self.logger.error(
                        "Request JSON is missing required parameter '%s'!" % k)
                if raise_exception:
                    curframe = inspect.currentframe()
                    calframe = inspect.getouterframes(curframe, 2)
                    caller_function = calframe[1][3]
                    msg = "Insufficient request parameters for this route! The %s() method requires values for the following keys: %s." % (
                        caller_function, utils.list_to_pretty_string(keys))
                    self.logger.exception(msg)
                    self.logger.error("Bad request params were: %s" %
                                      self.params)
                    raise utils.InvalidUsage(msg, status_code=400)
                else:
                    return False

        return True
示例#3
0
    def get_asset(self,
                  handle=None,
                  backoff_to_name=False,
                  raise_exception_if_not_found=True):
        """ Return an asset dict based on a handle. Return None if the handle
        cannot be retrieved. """

        asset = copy(self.assets.get(
            handle, None))  # return a copy, so we don't modify the actual def

        # implement backoff logic
        if asset is None and backoff_to_name:
            asset = copy(self.get_asset_from_name(handle))

        # if the asset is still None, see if we want to raise an expception
        if asset is None and raise_exception_if_not_found:
            if not backoff_to_name:
                msg = "The handle '%s' is not in %s and could not be retrieved! " % (
                    handle, self.get_handles())
                self.logger.error(msg)
            elif backoff_to_name:
                msg = "After backoff to name lookup, asset handle '%s' is not in %s and could not be retrieved." % (
                    handle, self.get_names())
                self.logger.error(msg)
            raise utils.InvalidUsage(msg)

        # finally, return the asset (or the NoneType)
        return asset
示例#4
0
    def get_random_names(self, count=100):
        """ Returns 'count' random names for each sex. This is meant primarily
        as a front-end helper, so it returns a JSON-like dict. It also raises
        a big, wordy error if you ask it for too many names. """

        m = copy(names.male)
        f = copy(names.female)

        m.extend(copy(names.neuter))
        f.extend(copy(names.neuter))

        male = set()
        female = set()

        for l in m, f:
            if count > len(l):
                raise utils.InvalidUsage(
                    'Cannot return more than %s random names!' % len(l))

        for i in [(male, m), (female, f)]:
            l, s = (i)
            while len(l) < count:
                l.add(random.choice(s))

        return {'M': sorted(list(male)), 'F': sorted(list(female))}
示例#5
0
    def set_preferences(self):
        """ Expects a request context and will not work without one. Iterates
        thru a list of preference handles and sets them. """

        self.check_request_params(['preferences'])
        pref_list = self.params['preferences']
        if type(pref_list) != list:
            raise utils.InvalidUsage("set_preferences() endpoint requires 'preferences' to be a list!")

        for pref_dict in pref_list:
            handle = pref_dict.get('handle',None)
            value = pref_dict.get('value',None)
            for p in [handle, value]:
                if p is None:
                    raise utils.InvalidUsage("Nah, bro: individual preference hashes/dicts should follow this syntax: {handle: 'preference_handle', value: true}")
            self.user['preferences'][handle] = value
#            self.logger.info("%s Set '%s' = %s'" % (request.User.login, handle, value))

        self.save()
示例#6
0
    def new(self):
        """ Creates a new user based on request.json values. Like all UserAsset
        'new()' methods, this one returns the new user's MDB _id when it's done.
        """

        self.logger.info("Creating new user...")
        self.check_request_params(['username','password'])

        # clean up the incoming values so that they conform to our data model
        username = self.params["username"].strip().lower()
        password = self.params["password"].strip()

        # do some minimalistic validation (i.e. rely on front-end for good data)
        #   and barf if it fails #separationOfConcerns

        msg = "The email address '%s' does not appear to be a valid email address!" % username
        if not '@' in username:
            raise utils.InvalidUsage(msg)
        elif not '.' in username:
            raise utils.InvalidUsage(msg)

        # make sure the new user doesn't already exist

        msg = "The email address '%s' is already in use by another user!" % username
        if utils.mdb.users.find_one({'login': username}) is not None:
            raise utils.InvalidUsage(msg)


        # now do it
        self.user = {
            'created_on': datetime.now(),
            'login': username,
#            'password': md5(password).hexdigest(),
            'password': generate_password_hash(password),
            'preferences': {},
            'collection': {"expansions": []},
            'notifications': {},
        }
        self._id = utils.mdb.users.insert(self.user)
        self.load()
        logger.info("New user '%s' created!" % username)

        return self.user["_id"]
示例#7
0
 def __init__(self, img_id):
     try:
         img_oid = ObjectId(img_id)
     except:
         raise utils.InvalidUsage(
             'Invalid OID! Image OIDs must be 12-byte input or 24-character hex string!',
             status_code=400)
     try:
         self.img = gridfs.GridFS(utils.mdb).get(img_oid)
     except gridfs.errors.NoFile:
         self.img = None
示例#8
0
    def __init__(self,
                 collection=None,
                 _id=None,
                 normalize_on_init=True,
                 new_asset_attribs={},
                 Settlement=None):

        # initialize basic vars
        self.logger = utils.get_logger()
        self.normalize_on_init = normalize_on_init
        self.new_asset_attribs = new_asset_attribs

        if collection is not None:
            self.collection = collection
        elif hasattr(self, "collection"):
            pass
        else:
            err_msg = "User assets (settlements, users, etc.) may not be initialized without specifying a collection!"
            self.logger.error(err_msg)
            raise AssetInitError(err_msg)

        # use attribs to determine whether the object has been loaded
        self.loaded = False

        if _id is None:
            self.get_request_params()
            self.new()
            _id = self._id

        # if we're initializing with a settlement object already in memory, use it
        # if this object IS a Settlement, the load() call below will overwrite this
        self.Settlement = Settlement

        # now do load() stuff
        try:
            try:
                self._id = ObjectId(_id)
            except Exception as e:
                self.logger.error(e)
                raise utils.InvalidUsage(
                    "The asset OID '%s' does not appear to be a valid object ID! %s"
                    % (_id, e),
                    status_code=422)
            self.load()
            self.loaded = True
        except Exception as e:
            self.logger.error("Could not load _id '%s' from %s!" %
                              (_id, self.collection))
            self.logger.exception(e)
            raise
示例#9
0
def get_admin_data(resource=None):
    """ Retrieves admin panel data. """

    try:
        if resource == 'user_data':
            return panel.get_user_data()
        if resource == 'settlement_data':
            return panel.get_settlement_data()
        elif resource == 'logs':
            return panel.serialize_system_logs()
    except Exception as e:
        logger.error("Unable to return '%s' admin data!" % resource)
        logger.error(e)
        raise utils.InvalidUsage(e, status_code=500)

    return utils.http_500
示例#10
0
    def new(self):
        """ Creates a new webapp alert; initializes. """

        self.alert = request.json

        # sanity check the incoming
        for req_var in ['body', 'title']:
            if self.alert[req_var] is None:
                raise utils.InvalidUsage(
                    "Webapp Alert key '%s' cannot be None type!" % req_var)

        self.alert['sub_type'] = self.alert['type']
        self.alert['type'] = 'webapp_alert'
        self.alert['created_on'] = datetime.now()
        self.alert['created_by'] = ObjectId(self.alert['created_by'])
        self.alert['expired'] = False
        self.alert['release'] = settings.get('api', 'version')
        self.alert['remote_ip'] = request.remote_addr

        # finally, save it and return it
        self.alert['_id'] = utils.mdb.notifications.insert(self.alert)
示例#11
0
 def load(self):
     self.alert = utils.mdb.notifications.find_one({'_id': self._id})
     if self.alert is None:
         raise utils.InvalidUsage('Notification %s does not exist!' %
                                  (self._id),
                                  status_code=404)