Esempio n. 1
0
def get_sess(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        # NOTE: dictize session for response
        return rpc.make_success_resp(apihandler.dictize_session(session), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "get_sess" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "get_sess",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 2
0
def add_ints(params, _id, conn, logger, config):
    # the entire method gets wrapped in a try except to ensure any uncaught errors return a JSON-RPC error object
    # rather than an http 5xx.
    try:
        # get the typized version of config
        schemes = t.typize_config(config)
        # does the params object match any of your the param schemes specified in config.json ?
        if not t.check_params_against_scheme_set(schemes["add_ints"], params):
            # if not then throw a JSON-RPC error
            return rpc.make_error_resp(const.INVALID_PARAMS_CODE,
                                       const.INVALID_PARAMS, _id)
        # do our calculation
        _sum = 0
        for i in params.values():
            _sum += i
        # lets log to stdout saying what we're doing (assuming debugging is on)
        logger.info(
            "We just calculated the sum, {}. Now time to format and return the response!"
            .format(_sum))
        # make and return our JSON-RPC response object
        return rpc.make_success_resp(_sum, _id)
    # catch everything!
    except Exception as e:
        # something went really wrong to be here. So, we write an error object to error.log for later review
        log.log_error({
            "method": "add_ints",
            "params": params,
            "error": str(e)
        })
        # finally, we return a JSON-RPC error saying something we messed up. Sorry 😢
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 3
0
def login_user(params, _id, conn, logger, config, session):
    try:
        # NOTE: calculate user_id
        user_id = params.get(
            "user_id",
            ludeim.generate_user_user_id(params["username"],
                                         params["password_hash"]))
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: get the user's type
            user = db.load_user_w_user_id(conn, user_id, _id)
        # NOTE: add the user's user_id to the session
        session["user_id"] = user.user_id
        # NOTE: add the user's type to the session
        session["type"] = user.type
        # NOTE: add user uuid to the session
        session["uuid"] = user.uuid
        return rpc.make_success_resp(user.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "login_user" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "login_user",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 4
0
def add_admin(params, _id, conn, logger, config, session):
    try:
        # NOTE: make the new admin
        admin = Admin(username=params["username"],
                      password_hash=params["password_hash"])
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # CHECK: is the admin-name free?
            if __is_adminname_taken(conn, params["username"]):
                return rpc.make_error_resp(const.USERNAME_TAKEN_CODE,
                                           const.USERNAME_TAKEN, _id)
            # NOTE: save the new admin
            db.save_new_admin(conn, admin, _id)
        return rpc.make_success_resp(
            {
                "type": "admin",
                "user_id": admin.user_id
            }, _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "add_admin " + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "add_admin",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 5
0
def get_sister_items(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(0,
                                       "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                                       "located in the session.\n"
                                       "SUGGESTION: Either either try again with a `user_id` argument, call "
                                       "login() then try again, or use put_sess() to manually add your user_id to "
                                       "your session then try again.",
                                       _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the target location
            target = db.load_item(conn, params["item_uuid"], _id)
            # NOTE: load the target's items
            items = [db.load_item(conn, uuid, _id) for uuid in target.sister_items]
        return rpc.make_success_resp([i.one_hot_jsonify() for i in items], _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "get_sister_items" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "get_sister_items",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE, const.INTERNAL_ERROR, _id)
def backup_database(params, _id, conn, logger, config):
    try:
        schemes = t.typize_config(config)
        if not t.check_params_against_scheme_set(schemes["backup_database"], params):
            return rpc.make_error_resp(
                const.INVALID_PARAMS_CODE,
                const.INVALID_PARAMS,
                _id
            )
        resp = __helper(params, _id, conn, logger, config)
        if resp is not True:
            return resp
        with open(config["database_path"] + ".backup", "w+") as f:
            for line in conn.iterdump():
                f.write('%s\n' % line)
        file_logger.log_general({  # database backups are probably worth writing to a general log file
            "method": "backup_database",
            "params": params,
        })
        return rpc.make_success_resp({"success": True}, _id)
    except Exception as e:
        file_logger.log_error({
            "method": "backup_database",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(
            const.INTERNAL_ERROR_CODE,
            const.INTERNAL_ERROR,
            _id)
def get_table_names(params, _id, conn, logger, config):
    try:
        schemes = t.typize_config(config)
        if not t.check_params_against_scheme_set(schemes["get_table_names"], params):
            return rpc.make_error_resp(
                const.INVALID_PARAMS_CODE,
                const.INVALID_PARAMS,
                _id
            )
        resp = __helper(params, _id, conn, logger, config)
        if resp is not True:
            return resp
        c = conn.cursor()
        c.execute("SELECT name FROM sqlite_master WHERE type='table';")
        resp = c.fetchall()
        ret = list()
        for table_tuple in resp:
            ret.append(table_tuple[0])
        return rpc.make_success_resp(ret, _id)
    except Exception as e:
        file_logger.log_error({
            "method": "backup_database",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(
            const.INTERNAL_ERROR_CODE,
            const.INTERNAL_ERROR,
            _id)
Esempio n. 8
0
def add_location(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        # CHECK: is the location type valid?
        if params["type"] not in lconst.LOCATION_TYPES:
            return rpc.make_error_resp(
                0, "PROBLEM: The provided location type is not valid.\n"
                "SUGGESTION: Try again with a valid location type.", _id)
        # CHECK: is the representative's title valid?
        if params["representative"]["title"] not in lconst.TITLES:
            return rpc.make_error_resp(
                0, "PROBLEM: The provided representative title is not valid.\n"
                "SUGGESTION: Try again with a valid representative title.",
                _id)
        location = Location(_type=params["type"],
                            name=params["name"],
                            address=params["address"],
                            details=params["details"],
                            latitude=params["latitude"],
                            longitude=params["longitude"],
                            representative=params["representative"])
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the user
            user = db.load_user_w_user_id(conn, user_id, _id)
            # NOTE: add the location to the user's location_uuids list
            user.location_uuids.add(location.uuid)
            # NOTE: add the user to the location's user_uuids list
            location.user_uuids.add(user.uuid)
            # NOTE: save everything
            db.save_existing_user(conn, user, _id)
            db.save_new_location(conn, location, _id)
        return rpc.make_success_resp(location.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "add_location" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "add_location",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 9
0
def main(): 
	pdfs = sorted(fd.askopenfilenames(title="Choose expenditure reports"), reverse=True)

	for pdf in pdfs:
		try:
			pdf_to_csv(pdf)
		except Exception as e: 
			log_error(pdf, e)
			continue            
Esempio n. 10
0
def get_user_locations(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(0,
                                       "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                                       "located in the session.\n"
                                       "SUGGESTION: Either either try again with a `user_id` argument, call "
                                       "login() then try again, or use put_sess() to manually add your user_id to "
                                       "your session then try again.",
                                       _id)
        if "username" in params:
            with conn:
                # NOTE: get a lock on the database
                conn.execute("BEGIN EXCLUSIVE")
                # CHECK: is there a user associated with the given username?
                if not __is_username_taken(_id, conn, params["username"]):
                    return rpc.make_error_resp(0,
                                               "PROBLEM: No user in the system exists with the designated username.\n"
                                               "SUGGESTION: Try a different username.",
                                               _id)
                # NOTE: load the target user
                target = db.load_user_w_uuid(conn,
                                             conn
                                             .execute("""SELECT uuid FROM users WHERE username = ?""",
                                                      (params["username"],))
                                             .fetchone()[0],
                                             _id)
                # NOTE: load the target's locations
                locations = [db.load_location(conn, uuid, _id) for uuid in target.location_uuids]
        else:
            with conn:
                # NOTE: get a lock on the database
                conn.execute("BEGIN EXCLUSIVE")
                # NOTE: load the caller's user
                caller = db.load_user_w_user_id(conn, user_id, _id)
                # NOTE: load the caller's locations
                locations = [db.load_location(conn, uuid, _id) for uuid in caller.location_uuids]
        return rpc.make_success_resp([i.one_hot_jsonify() for i in locations], _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "get_user_locations" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "get_user_locations",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE, const.INTERNAL_ERROR, _id)
Esempio n. 11
0
def drop_location(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the user
            user = db.load_user_w_user_id(conn, user_id, _id)
            # CHECK: is the location attached to the user?
            if params["location_uuid"] not in user.location_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated location uuid doesn't correspond to a location "
                    "owned by the user.\n"
                    "SUGGESTIONS: Try again with a valid location uuid.", _id)
            # NOTE: load the location
            location = db.load_location(conn, params["location_uuid"], _id)
            # CHECK: is the location empty of items?
            if len(location.item_uuids | location.incoming_item_uuids
                   | location.outgoing_item_uuids) != 0:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated location has incoming, outgoing, or inventory  items.\n"
                    "SUGGESTION: Try transferring all items then trying again.",
                    _id)
            # NOTE: remove the location from the user's location_uuids list
            user.location_uuids.discard(location.uuid)
            # NOTE: save everything
            db.save_existing_user(conn, user, _id)
        return rpc.make_success_resp(location.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "drop_location" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "drop_location",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 12
0
def change_username(params, _id, conn, logger, config, session):
	try:
		# CHECK: is the username valid?
		length = len(params["new_username"])
		if length < lconst.MIN_USERNAME_LEN or length > lconst.MAX_USERNAME_LEN:
			return rpc.make_error_resp(const.INVALID_USER_USERNAME_CODE,
									   const.INVALID_USER_USERNAME, _id)
		# NOTE: find user_id
		user_id = params.get("user_id", session.get("user_id", None))
		# CHECK: was a user_id found?
		if user_id is None:
			return rpc.make_error_resp(0,
									   "PROBLEM: There was no `user_id` argument provided and no user_id could be "
									   "located in the session.\n"
									   "SUGGESTION: Either either try again with a `user_id` argument, call "
									   "login() then try again, or use put_sess() to manually add your user_id to "
									   "your session then try again.",
									   _id)
		with conn:
			# NOTE: get a lock on the database
			conn.execute("BEGIN EXCLUSIVE")
			# CHECK: is the username available?
			if len(conn.execute("""SELECT * FROM users WHERE username = ?""",
								(params["new_username"],)).fetchall()) != 0:
				return rpc.make_error_resp(0,
										   "PROBLEM: The requested username is taken.\n"
										   "SUGGESTION: Try again with a different username.",
										   _id)
			# NOTE: load the caller's user
			caller = db.load_user_w_user_id(conn, user_id, _id)
			# NOTE: update the caller's username
			caller.username = params["new_username"]
			# NOTE: recalculate the caller's user_id
			caller.recalculate_user_id()
			# NOTE: save the caller
			db.save_existing_user(conn, caller, _id)
			# NOTE: update the user_id in the session
			session["user_id"] = caller.user_id
		return rpc.make_success_resp(caller.one_hot_jsonify(), _id)
	except WrappedErrorResponse as e:
		file_logger.log_error({
			"method": "change_username" + str(e.methods),
			"params": params,
			"error": str(e.exception)
		})
		return e.response_obj
	except Exception as e:
		file_logger.log_error({
			"method": "change_username",
			"params": params,
			"error": str(e)
		})
		return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
								   const.INTERNAL_ERROR, _id)
Esempio n. 13
0
    def teardown(self):
        """
        Removes the account alias.
        """
        conn = boto.iam.IAMConnection()

        try:
            conn.delete_account_alias(self.alias)
            print(Fore.GREEN + "Removed account alias '" + Fore.YELLOW + self.alias + Fore.GREEN + "'" + Fore.RESET)
        except boto.exception.BotoServerError as error:
            log_error(error)
            raise
Esempio n. 14
0
    def setup(self):
        """
        Creates the account alias.
        """
        conn = boto.iam.IAMConnection()

        try:
            conn.create_account_alias(self.alias)
            print(Fore.GREEN + "Added account alias '" + Fore.YELLOW + self.alias + Fore.GREEN + "'" + Fore.RESET)
        except boto.exception.BotoServerError as error:
            log_error(error)
            raise
Esempio n. 15
0
def drop_user(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the user
            user = db.load_user_w_user_id(conn, user_id, _id)
            # CHECK: does the user have no items?
            if len(user.item_uuids | user.incoming_item_uuids
                   | user.outgoing_item_uuids) != 0:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated user has at least 1 item under their ownership or "
                    "currently incoming.\n"
                    "SUGGESTION: Try transferring/dropping/reject all items then trying again.",
                    _id)
            # CHECK: does the user have no locations?
            if len(user.location_uuids) != 0:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated user has at least 1 location attached to their "
                    "account.\n"
                    "SUGGESTION: Try dropping all locations then trying again.",
                    _id)
            # NOTE: delete the user
            conn.execute("""DELETE FROM users WHERE uuid = ?""", (user.uuid, ))
        return rpc.make_success_resp(True, _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "drop_user" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "drop_user",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 16
0
    def post(self, request):
        """
        creates a new Mechanic in the db
        :param request: http request for the view
            method allowed: POST
            mandatory fields: ['name', 'email', 'number', 'password', 'mechanic_code']
        :returns Response object with
            mechanics list and 200 status if no error
            message and corresponding status if error
        """
        serializer = SignUpSerializer(data=request.data)
        if not serializer.is_valid():
            log_error(request.path, request.data, status.HTTP_400_BAD_REQUEST,
                      serializer.errors)
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)
        mechanic_details = serializer.data

        if User.objects.filter(email=mechanic_details['email']).exists():
            return Response({'message': messages.EMAIL_ALREADY_EXISTS},
                            status=status.HTTP_400_BAD_REQUEST)
        if Mechanic.objects.filter(
                mechanic_code=mechanic_details['mechanic_code']).exists():
            return Response({'message': messages.MEC_CODE_ALREADY_EXISTS},
                            status=status.HTTP_400_BAD_REQUEST)
        try:
            user_id = User.objects.aggregate(models.Max('id'))['id__max'] + 1
        except TypeError:
            user_id = 1

        user = User.objects.create(
            id=user_id,
            email=mechanic_details['email'],
            number=mechanic_details['number'],
            password=bcrypt.hashpw(
                mechanic_details['password'].encode('utf-8'),
                bcrypt.gensalt()).decode(),
            role=User.ROLE_CHOICES.MECH,
            created_on=timezone.now())
        Mechanic.objects.create(
            mechanic_code=mechanic_details['mechanic_code'], user=user)
        try:
            user_details_id = UserDetails.objects.aggregate(
                models.Max('id'))['id__max'] + 1
        except TypeError:
            user_details_id = 1
        UserDetails.objects.create(id=user_details_id,
                                   available_credit=0,
                                   name=mechanic_details['name'],
                                   status='ACTIVE',
                                   user=user)
        return Response({'message': messages.MEC_CREATED.format(user.email)},
                        status=status.HTTP_200_OK)
Esempio n. 17
0
def get_user_items(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(0,
                                       "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                                       "located in the session.\n"
                                       "SUGGESTION: Either either try again with a `user_id` argument, call "
                                       "login() then try again, or use put_sess() to manually add your user_id to "
                                       "your session then try again.",
                                       _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the target user
            if "uuid" in params:
                target = db.load_user_w_uuid(conn, params["uuid"], _id)
            else:
                target = db.load_user_w_user_id(conn, user_id, _id)
            # NOTE: load the target's items
            items = [db.load_item(conn, uuid, _id) for uuid in (target.item_uuids | target.incoming_item_uuids | target.outgoing_item_uuids)]
        # NOTE: form the predicate function for the filter
        stages = [target.incoming_item_uuids, target.item_uuids, target.outgoing_item_uuids]
        p = lambda item: (
                ("status_filter" not in params or
                 item.status == params.get("status_filter")) and
                ("ownership_filter" not in params or
                 (item.uuid in target.incoming_item_uuids) == params["ownership_filter"]) and
                ("location_uuid_filter" not in params or
                 item.location_uuids[-1] == params["location_uuid_filter"]) and
                ("stage_filter" not in params or
                 item.uuid in stages[params["stage_filter"]]))
        return rpc.make_success_resp([i.one_hot_jsonify() for i in items if p(i)], _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "get_user_items" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "get_user_items",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE, const.INTERNAL_ERROR, _id)
Esempio n. 18
0
def add_user(params, _id, conn, logger, config, session):
    try:
        user = User(_type=params["type"],
                    username=params["username"],
                    password_hash=params["password_hash"])
        if user.type not in lconst.USER_TYPES:
            return rpc.make_error_resp(const.INVALID_USER_TYPE_CODE,
                                       const.INVALID_USER_TYPE, _id)
        if len(user.username) < lconst.MIN_USERNAME_LEN or len(
                user.username) > lconst.MAX_USERNAME_LEN:
            return rpc.make_error_resp(const.INVALID_USER_USERNAME_CODE,
                                       const.INVALID_USER_USERNAME, _id)
        if len(user.password_hash) < lconst.MIN_PASSWORD_HASH_LEN or len(
                user.password_hash) > lconst.MAX_PASSWORD_HASH_LEN:
            return rpc.make_error_resp(const.INVALID_USER_PASSWORD_HASH_CODE,
                                       const.INVALID_USER_PASSWORD_HASH, _id)
        with conn:
            conn.execute("BEGIN EXCLUSIVE")
            if __is_username_taken(conn, params["username"]):
                return rpc.make_error_resp(const.USERNAME_TAKEN_CODE,
                                           const.USERNAME_TAKEN, _id)
            db.save_new_user(conn, user, _id)
        return rpc.make_success_resp(
            {
                "type": user.type,
                "user_id": user.user_id
            }, _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "add_user " + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        exc_type, exc_value, exc_traceback = sys.exc_info()
        file_logger.log_error({
            "method": "add_user",
            "params": params,
            "error": str(e),
            "trace": str(traceback.extract_tb(exc_traceback))
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 19
0
    def post(self, request, user=None):
        """
        api for checking if coupon is already claimed
        if claimed before: returns an error message
        else: increases the user credit
        :param request: http request for the view
            method allowed: POST
            http request should be authorised by the jwt token of the user
        :param user: User object of the requesting user
        :returns Response object with
            message and 200 status if no error
            message and corresponding status if error
        """
        coupon_request_body = request.data

        serializer = CouponSerializer(data=coupon_request_body)
        if not serializer.is_valid():
            log_error(request.path, request.data, 400, serializer.errors)
            return Response(serializer.errors,
                            status=status.HTTP_400_BAD_REQUEST)
        try:
            coupon = Coupon.objects.using('mongodb').get(
                coupon_code=coupon_request_body['coupon_code'])
        except ObjectDoesNotExist as e:
            log_error(request.path, request.data, 400, e)
            return Response({'message': "Coupon not found"},
                            status=status.HTTP_400_BAD_REQUEST)
        if AppliedCoupon.objects.filter(
                user=user,
                coupon_code=coupon_request_body['coupon_code']).first():
            return Response({'message': messages.COUPON_ALREADY_APPLIED},
                            status=status.HTTP_400_BAD_REQUEST)
        AppliedCoupon.objects.create(
            user=user, coupon_code=coupon_request_body['coupon_code'])
        user_details = UserDetails.objects.get(user=user)
        user_details.available_credit += coupon_request_body['amount']
        user_details.save()
        return Response(
            {
                'credit': user_details.available_credit,
                'message': messages.COUPON_APPLIED
            },
            status=status.HTTP_200_OK)
Esempio n. 20
0
 def post(self, request, order_id=None, user=None):
     """
     order view for adding a new order
     :param request: http request for the view
         method allowed: POST
         http request should be authorised by the jwt token of the user
         mandatory fields: ['product_id', 'quantity']
     :param order_id:
         order_id of the order referring to
         mandatory for GET and PUT http methods
     :param user: User object of the requesting user
     :returns Response object with
         order object and 200 status if no error
         message and corresponding status if error
     """
     request_data = request.data
     serializer = ProductQuantitySerializer(data=request_data)
     if not serializer.is_valid():
         log_error(request.path, request.data, status.HTTP_400_BAD_REQUEST,
                   serializer.errors)
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
     product = Product.objects.get(id=request_data['product_id'])
     user_details = UserDetails.objects.get(user=user)
     if user_details.available_credit < product.price:
         return Response({'message': messages.INSUFFICIENT_BALANCE},
                         status=status.HTTP_400_BAD_REQUEST)
     user_details.available_credit -= float(product.price *
                                            request_data['quantity'])
     order = Order.objects.create(
         user=user,
         product=product,
         quantity=request_data['quantity'],
         created_on=timezone.now(),
     )
     user_details.save()
     return Response(
         {
             'id': order.id,
             'message': messages.ORDER_CREATED,
             'credit': user_details.available_credit,
         },
         status=status.HTTP_200_OK)
Esempio n. 21
0
 def post(self, request, user):
     """
     products view for adding a new product
     :param request: http request for the view
         method allowed: POST
         http request should be authorised by the jwt token of the user
         mandatory fields for POST and PUT http methods: ['name', 'price', 'image_url']
     :param user: User object of the requesting user
     :returns Response object with
         products list and 200 status if no error
         message and corresponding status if error
     """
     user_request_body = request.data
     serializer = ProductSerializer(data=user_request_body)
     if not serializer.is_valid():
         log_error(request.path, request.data, 400, serializer.errors)
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
     serializer.save()
     return Response(serializer.data, status=status.HTTP_200_OK)
Esempio n. 22
0
def put_sess(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        # CHECK: type key isn't not being updated?
        if params["key"] == "type":
            return rpc.make_error_resp(
                0,
                "PROBLEM: Updating the `type` key is not allowed since it could present "
                "a permission escalation attack vector.\n"
                "SUGGESTION: Just login and your type will automatically be added to your "
                "session.", _id)
        # NOTE: update the session
        session[params["key"]] = params["value"]
        # NOTE: dictize session for response
        return rpc.make_success_resp(apihandler.dictize_session(session), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "put_sess" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "put_sess",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 23
0
def get_all_users(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(0,
                                       "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                                       "located in the session.\n"
                                       "SUGGESTION: Either either try again with a `user_id` argument, call "
                                       "login() then try again, or use put_sess() to manually add your user_id to "
                                       "your session then try again.",
                                       _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load partial users
            db_resp = conn.execute("""SELECT uuid, type_, username, avatar, location_uuids, item_uuids FROM users""").fetchall()
        return rpc.make_success_resp([{
            "uuid": line[0],
            "type": line[1],
            "username": line[2],
            "avatar": line[3],
            "location_uuids": line[4],
            "item_uuids": line[5]} for line in db_resp], _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "get_all_users" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "get_all_users",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE, const.INTERNAL_ERROR, _id)
Esempio n. 24
0
def change_avatar(params, _id, conn, logger, config, session):
	try:
		# NOTE: find user_id
		user_id = params.get("user_id", session.get("user_id", None))
		# CHECK: was a user_id found?
		if user_id is None:
			return rpc.make_error_resp(0,
									   "PROBLEM: There was no `user_id` argument provided and no user_id could be "
									   "located in the session.\n"
									   "SUGGESTION: Either either try again with a `user_id` argument, call "
									   "login() then try again, or use put_sess() to manually add your user_id to "
									   "your session then try again.",
									   _id)
		with conn:
			# NOTE: get a lock on the database
			conn.execute("BEGIN EXCLUSIVE")
			# NOTE: load the caller's user
			caller = db.load_user_w_user_id(conn, user_id, _id)
			# NOTE: update the caller's username
			caller.avatar = params["new_avatar"]
			# NOTE: save the caller
			db.save_existing_user(conn, caller, _id)
		return rpc.make_success_resp(caller.one_hot_jsonify(), _id)
	except WrappedErrorResponse as e:
		file_logger.log_error({
			"method": "change_avatar" + str(e.methods),
			"params": params,
			"error": str(e.exception)
		})
		return e.response_obj
	except Exception as e:
		file_logger.log_error({
			"method": "change_avatar",
			"params": params,
			"error": str(e)
		})
		return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
								   const.INTERNAL_ERROR, _id)
Esempio n. 25
0
def drop_admin(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load the admin
            admin = db.load_admin(conn, user_id, _id)
            # NOTE: delete the user
            conn.execute("""DELETE FROM admins WHERE user_id = ?""",
                         (admin.user_id, ))
        return rpc.make_success_resp(True, _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "drop_admin" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "drop_admin",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 26
0
 def get(self, request):
     """
     receive_report endpoint for mechanic
     :param request: http request for the view
         method allowed: POST
         mandatory fields: ['mechanic_code', 'problem_details', 'vin']
     :returns Response object with
         { service request id, report link } and 200 status if no error
         message and corresponding status if error
     """
     serializer = ReceiveReportSerializer(data=request.GET)
     if not serializer.is_valid():
         log_error(request.path, request.data, status.HTTP_400_BAD_REQUEST,
                   serializer.errors)
         return Response(serializer.errors,
                         status=status.HTTP_400_BAD_REQUEST)
     report_details = serializer.data
     mechanic = Mechanic.objects.get(
         mechanic_code=report_details['mechanic_code'])
     vehicle = Vehicle.objects.get(vin=report_details['vin'])
     service_request = ServiceRequest.objects.create(
         vehicle=vehicle,
         mechanic=mechanic,
         problem_details=report_details['problem_details'],
         created_on=timezone.now())
     service_request.save()
     report_link = "{}?report_id={}".format(reverse("get-mechanic-report"),
                                            service_request.id)
     report_link = request.build_absolute_uri(report_link)
     return Response(
         {
             'id': service_request.id,
             'sent': True,
             'report_link': report_link
         },
         status=status.HTTP_200_OK)
Esempio n. 27
0
    def post(self, request, user=None):
        """
        contact_mechanic view to call the mechanic api
        :param request: http request for the view
            method allowed: POST
            http request should be authorised by the jwt token of the user
            mandatory fields: ['mechanic_api', 'repeat_request_if_failed', 'number_of_repeats']
        :param user: User object of the requesting user
        :returns Response object with
            response_from_mechanic_api and 200 status if no error
            message and corresponding status if error
        """
        request_data = request.data
        serializer = ContactMechanicSerializer(data=request_data)
        if not serializer.is_valid():
            log_error(request.path, request.data, status.HTTP_400_BAD_REQUEST, serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

        repeat_request_if_failed = request_data['repeat_request_if_failed']
        number_of_repeats = request_data['number_of_repeats']
        if repeat_request_if_failed and number_of_repeats < 1:
            return Response(
                {'message': messages.MIN_NO_OF_REPEATS_FAILED},
                status=status.HTTP_503_SERVICE_UNAVAILABLE
            )
        elif repeat_request_if_failed and number_of_repeats > 100:
            return Response(
                {'message': messages.NO_OF_REPEATS_EXCEEDED},
                status=status.HTTP_503_SERVICE_UNAVAILABLE
            )

        repeat_count = 0
        while True:
            logger.info(f"Repeat count: {repeat_count}")
            try:
                mechanic_response = requests.get(
                    url=request_data['mechanic_api'],
                    params=request_data,
                    headers={'Authorization': request.META.get('HTTP_AUTHORIZATION')}
                )
                if mechanic_response.status_code == status.HTTP_200_OK:
                    logger.info(f"Got a valid response at repeat count: {repeat_count}")
                    break
                if not repeat_request_if_failed:
                    break
                if repeat_count == number_of_repeats:
                    break
                repeat_count += 1
            except (MissingSchema, InvalidURL) as e:
                log_error(request.path, request.data, status.HTTP_400_BAD_REQUEST, e)
                return Response({'message': str(e)}, status=status.HTTP_400_BAD_REQUEST)
            except requests.exceptions.ConnectionError as e:
                if not repeat_request_if_failed:
                    return Response(
                        {'message': messages.COULD_NOT_CONNECT},
                        status=status.HTTP_400_BAD_REQUEST
                    )
                if repeat_count == number_of_repeats:
                    return Response(
                        {'message': messages.COULD_NOT_CONNECT},
                        status=status.HTTP_400_BAD_REQUEST
                    )
                repeat_count += 1
                continue
        mechanic_response_status = mechanic_response.status_code
        try:
            mechanic_response = mechanic_response.json()
        except ValueError:
            mechanic_response = mechanic_response.text
        return Response({
            'response_from_mechanic_api': mechanic_response,
            'status': mechanic_response_status
        }, status=mechanic_response_status)
Esempio n. 28
0
def change_item_detail(params, _id, conn, logger, config, session):
	try:
		# NOTE: find user_id
		user_id = params.get("user_id", session.get("user_id", None))
		# CHECK: was a user_id found?
		if user_id is None:
			return rpc.make_error_resp(
				0,
				"PROBLEM: There was no `user_id` argument provided and no "
				"user_id could be located in the session.\n"
				"SUGGESTION: Either either try again with a `user_id` "
				"argument, call login() then try again, or use put_sess() to "
				"manually add your user_id to your session then try again.",
				_id
			)
		with conn:
			# NOTE: get a lock on the database
			conn.execute("BEGIN EXCLUSIVE")
			# NOTE: load the caller's user
			caller = db.load_user_w_user_id(conn, user_id, _id)
			# NOTE: load the item
			item = db.load_item(conn, params["item_uuid"], _id)
			# CHECK: does the caller own this item?
			if item.uuid not in caller.item_uuids | caller.outgoing_item_uuids:
				return rpc.make_error_resp(
					0,
					"PROBLEM: You don't own the item you're trying to edit.\n"
					"SUGGESTION: Try editing an edit you own or ensure you're "
					"not logged in to someone else's account.",
					_id
				)
			# CHECK: is the item stationary?
			if item.status != lconst.STATIONARY:
				return rpc.make_error_resp(
					0,
					"PROBLEM: You can't edit a non-stationary item.\n"
					"SUGGESTION: Rescind the transfer then try again.",
					_id
				)
			# NOTE: update the item's details field
			item.details[params["key"]] = params["value"]
			# NOTE: save the item
			db.save_existing_item(conn, item, _id)
		return rpc.make_success_resp(item.one_hot_jsonify(), _id)
	except WrappedErrorResponse as e:
		file_logger.log_error({
			"method": "change_item_detail" + str(e.methods),
			"params": params,
			"error": str(e.exception)
		})
		return e.response_obj
	except Exception as e:
		file_logger.log_error({
			"method": "change_item_detail",
			"params": params,
			"error": str(e)
		})
		return rpc.make_error_resp(
			const.INTERNAL_ERROR_CODE,
			const.INTERNAL_ERROR, _id
		)
Esempio n. 29
0
def split_item(params, _id, conn, logger, config, session):
	try:
		# NOTE: find user_id
		user_id = params.get("user_id", session.get("user_id", None))
		# CHECK: was a user_id found?
		if user_id is None:
			return rpc.make_error_resp(
				0,
				"PROBLEM: There was no `user_id` argument provided and no "
				"user_id could be located in the session.\n"
				"SUGGESTION: Either either try again with a `user_id` "
				"argument, call login() then try again, or use put_sess() to "
				"manually add your user_id to your session then try again.",
				_id
			)
		with conn:
			# NOTE: get a lock on the database
			conn.execute("BEGIN EXCLUSIVE")
			# NOTE: load the caller's user
			caller = db.load_user_w_user_id(conn, user_id, _id)
			# NOTE: load the item
			item = db.load_item(conn, params["item_uuid"], _id)
			# CHECK: does the caller own this item?
			if item.uuid not in caller.item_uuids | caller.outgoing_item_uuids:
				return rpc.make_error_resp(
					0,
					"PROBLEM: You don't own the item you're trying to edit.\n"
					"SUGGESTION: Try editing an edit you own or ensure you're "
					"not logged in to someone else's account.",
					_id
				)
			# CHECK: is the item stationary?
			if item.status != lconst.STATIONARY:
				return rpc.make_error_resp(
					0,
					"PROBLEM: You can't edit a non-stationary item.\n"
					"SUGGESTION: Rescind the transfer then try again.",
					_id
				)
			# NOTE: load the item's location
			location = db.load_location(conn, item.location_uuids[-1], _id)
			# NOTE: make n new items with the parent item's
			children = {Item(
				_type=item.type,
				location_uuids=item.location_uuids,
				user_uuids=item.user_uuids,
				status=item.status,
				details=item.details
			) for _ in range(params.get("ways", 2))}
			# NOTE: generate the set of sister item uuids
			sister_uuids =\
				{child.uuid for child in children} | set(item.sister_items)
			for child in children:
				# NOTE: add the sisters to the child
				child.sister_items = list(sister_uuids - {child.uuid})
				# NOTE: save the new child
				db.save_new_item(conn, child, _id)
				# NOTE: add the child to the location's item_uuids list
				location.item_uuids.add(child.uuid)
				# NOTE: add the child to the caller's item_uuids list
				caller.item_uuids.add(child.uuid)
			# NOTE: update the item's status to `split`
			item.status = lconst.SPLIT
			# NOTE: remove the item from the location's item_uuids list
			location.item_uuids.discard(item.uuid)
			# NOTE: remove the item from the caller's item_uuids list
			caller.item_uuids.discard(item.uuid)
			# NOTE save everything
			db.save_existing_item(conn, item, _id)
			db.save_existing_location(conn, location, _id)
			db.save_existing_user(conn, caller, _id)
		children = [child.one_hot_jsonify() for child in children]
		return rpc.make_success_resp(list(children), _id)
	except WrappedErrorResponse as e:
		file_logger.log_error({
			"method": "split_item" + str(e.methods),
			"params": params,
			"error": str(e.exception)
		})
		return e.response_obj
	except Exception as e:
		file_logger.log_error({
			"method": "split_item",
			"params": params,
			"error": str(e)
		})
		return rpc.make_error_resp(
			const.INTERNAL_ERROR_CODE,
			const.INTERNAL_ERROR, _id
		)
Esempio n. 30
0
def rescind_transfer(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load item
            item = db.load_item(conn, params["item_uuid"], _id)
            # CHECK: is the item actually in transit?
            if item.status != lconst.TRANSIT:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The item designated by the `item_uuid` argument is not in transit,"
                    " and therefore, there is no transfer to rescind.\n"
                    "SUGGESTION: Try calling this method with an `item_uuid` that corresponds to"
                    " an item that is in transit.", _id)
            # NOTE: load the caller's user
            caller = db.load_user_w_user_id(conn, user_id, _id)
            # CHECK: does the caller own the item?
            if item.uuid not in caller.outgoing_item_uuids | caller.item_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: You are not the owner of this item, and therefore, can't rescind "
                    "it's transfer\n"
                    "SUGGESTION: You may be logged in to someone else's account without "
                    "realizing it. Try calling login() then trying again.",
                    _id)
            # NOTE: load the origin
            origin = db.load_location(conn, item.location_uuids[-2], _id)
            # NOTE: load the destination
            destination = db.load_location(conn, item.location_uuids[-1], _id)
            # NOTE: combine if necessary
            if origin.uuid == destination.uuid:
                destination = origin
            # NOTE: load the receiver's user
            receiver = db.load_user_w_uuid(conn, item.user_uuids[-1], _id)
            # NOTE: combine if necessary
            if caller.uuid == receiver.uuid:
                receiver = caller
            # NOTE: remove the item from the destination's incoming_item_uuids
            destination.incoming_item_uuids.discard(item.uuid)
            # NOTE: remove the item from the origin's outgoing_item_uuids list
            origin.outgoing_item_uuids.discard(item.uuid)
            # NOTE: add the item to the origin's item_uuids list
            origin.item_uuids.add(item.uuid)
            # NOTE: set the item to stationary
            item.status = lconst.STATIONARY
            # NOTE: remove the item from the user's outgoing_item_uuids list
            caller.outgoing_item_uuids.discard(item.uuid)
            # NOTE: add the item to the user's item_uuids list
            caller.item_uuids.add(item.uuid)
            # NOTE: remove the item from the receiever's incoming_item_uuids
            receiver.incoming_item_uuids.discard(item.uuid)
            # NOTE: remove the receiver from the item's user_uuids list
            item.user_uuids = item.user_uuids[:-1]
            # NOTE: remove the destination from the item's location_uuids list
            item.location_uuids = item.location_uuids[:-1]
            # NOTE: save everything
            db.save_existing_item(conn, item, _id)
            db.save_existing_user(conn, caller, _id)
            db.save_existing_user(conn, receiver, _id)
            db.save_existing_location(conn, origin, _id)
            db.save_existing_location(conn, destination, _id)
        return rpc.make_success_resp(item.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "rescind_transfer" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "rescind_transfer",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 31
0
def redirect_transfer(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load item
            item = db.load_item(conn, params["item_uuid"], _id)
            # CHECK: is the item actually in transit?
            if item.status != lconst.TRANSIT:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The item designated by the `item_uuid` argument is not in transit,"
                    " and therefore, there is no transfer to redirect.\n"
                    "SUGGESTION: Try calling this method with an `item_uuid` that corresponds to"
                    " an item that is in transit.", _id)
            # NOTE: load the caller's user
            caller = db.load_user_w_user_id(conn, user_id, _id)
            # CHECK: is the caller the owner of this item?
            if item.uuid not in caller.outgoing_item_uuids | caller.item_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: You are not the owner of this item, and therefore, don't have the "
                    "ability to redirect this transfer\n"
                    "SUGGESTION: You may be logged in to someone else's account without "
                    "realizing it. Try calling login() then trying again.",
                    _id)
            # NOTE: load the new receiver's user
            new_receiver = db.load_user_w_uuid(
                conn, params["new_destination_user_uuid"], _id)
            # NOTE: load the new destination location
            new_destination = db.load_location(
                conn, params["new_destination_location_uuid"], _id)
            # CHECK: is the destination attached to the receiver?
            if new_destination.uuid not in new_receiver.location_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated new receiver has no presence at the designated "
                    "new destination which is a contradiction.\n"
                    "SUGGESTION: Try again with either a different new receiver who has a "
                    "presence at the destination, or a different new destination where the "
                    "receiver has a presence.", _id)
            # NOTE: load the old_destination
            old_destination = db.load_location(conn, item.location_uuids[-1],
                                               _id)
            # NOTE: combine if necessary
            if new_destination.uuid == old_destination.uuid:
                new_destination = old_destination
            # NOTE: remove the item from the old_destination's incoming_item_uuids list
            old_destination.incoming_item_uuids.discard(item.uuid)
            # NOTE: add the item to the new_destination's incoming_item_uuids
            new_destination.incoming_item_uuids.add(item.uuid)
            # NOTE: load the sender's user
            sender = db.load_user_w_uuid(conn, item.user_uuids[-2], _id)
            # NOTE: load the old_receiver's user
            old_receiver = db.load_user_w_uuid(conn, item.user_uuids[-1], _id)
            # NOTE: combine if necessary
            if (sender.uuid == old_receiver.uuid
                    and old_receiver.uuid == caller.uuid):
                old_receiver = sender
                caller = old_receiver
            elif old_receiver.uuid == caller.uuid:
                old_receiver = caller
            elif caller.uuid == sender.uuid:
                caller = sender
            elif sender.uuid == old_receiver.uuid:
                sender = old_receiver
            # NOTE: remove the item from the old receiver's incoming_item_uuids
            old_receiver.incoming_item_uuids.discard(item.uuid)
            # NOTE: is this an external redirect?
            if sender.uuid != new_receiver.uuid:
                # NOTE: add the item to the new receiver's incoming_item_uuids
                new_receiver.incoming_item_uuids.append(item.uuid)
                # NOTE: remove the item from the sender's item_uuids list
                sender.item_uuids.discard(item.uuid)
                # NOTE: add the item to the sender's outgoing_item_uuids list
                sender.outgoing_item_uuids.add(item.uuid)
            # NOTE: remove the old receiver from the item's user_uuids list
            item.user_uuids = item.user_uuids[:-1]
            # NOTE: remove the old destination from the item's location_uuids
            item.location_uuids = item.location_uuids[:-1]
            # NOTE: add the new receiver to the item's user_uuids list
            # OPT: combine with the above step
            item.user_uuids.append(new_receiver.uuid)
            # NOTE: add the new destination to the item's location_uuids list
            # OPT: combine with the above step
            item.location_uuids.append(new_destination.uuid)
            # NOTE: save everything
            db.save_existing_item(conn, item, _id)
            db.save_existing_user(conn, new_receiver, _id)
            db.save_existing_user(conn, old_receiver, _id)
        return rpc.make_success_resp(item.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "redirect_transfer" + str(e.methods),
            "params": params,
            "error": str(e.exception)
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "redirect_transfer",
            "params": params,
            "error": str(e)
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)
Esempio n. 32
0
def begin_transfer(params, _id, conn, logger, config, session):
    try:
        # NOTE: find user_id
        user_id = params.get("user_id", session.get("user_id", None))
        # CHECK: was a user_id found?
        if user_id is None:
            return rpc.make_error_resp(
                0,
                "PROBLEM: There was no `user_id` argument provided and no user_id could be "
                "located in the session.\n"
                "SUGGESTION: Either either try again with a `user_id` argument, call "
                "login() then try again, or use put_sess() to manually add your user_id to "
                "your session then try again.", _id)
        with conn:
            # NOTE: get a lock on the database
            conn.execute("BEGIN EXCLUSIVE")
            # NOTE: load item
            item = db.load_item(conn, params["item_uuid"], _id)
            # CHECK: is the item not stationary?
            if item.status != lconst.STATIONARY:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The item designated by the `item_uuid` argument is not in "
                    "stationary, and therefore, it cannot be transferred.\n"
                    "SUGGESTION: Try calling this method with an `item_uuid` that corresponds to"
                    " an item that is stationary, call redirect_transfer() instead, or call "
                    "rescind_transfer() on this item then try again.", _id)
            # NOTE: load the caller's user
            caller = db.load_user_w_user_id(conn, user_id, _id)
            # CHECK: does the caller own the item?
            if item.uuid not in caller.item_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The item begin transferred is not owned by this account.\n"
                    "SUGGESTION: You may be logged in to someone else's account without "
                    "realizing it. Try calling login() then trying again.",
                    _id)
            # NOTE: load the receiver's user
            receiver = db.load_user_w_uuid(conn,
                                           params["destination_user_uuid"],
                                           _id)
            # NOTE: load the destination
            destination = db.load_location(conn,
                                           params["destination_location_uuid"],
                                           _id)
            # CHECK: is the destination attached to the receiver?
            if destination.uuid not in receiver.location_uuids:
                return rpc.make_error_resp(
                    0,
                    "PROBLEM: The designated receiver has no presence at the designated "
                    "destination which is a contradiction.\n"
                    "SUGGESTION: Try again with either a different receiver who has a presence "
                    "at the destination, or a different destination where the receiver has a "
                    "presence.", _id)
            # NOTE: load the origin
            origin = db.load_location(conn, item.location_uuids[-1], _id)
            # NOTE: combine if necessary
            if origin.uuid == destination.uuid:
                destination = origin
            # NOTE: remove the item from the origin's item_uuids list
            origin.item_uuids.discard(item.uuid)
            # NOTE: add the item to the origin's outgoing_item_uuids list
            origin.outgoing_item_uuids.add(item.uuid)
            # NOTE: add the item to the destination's incoming_item_uuids list
            destination.incoming_item_uuids.add(item.uuid)
            # NOTE: conditionally move item around in the user
            if receiver.uuid != caller.uuid:
                # NOTE: remove the item from the caller's item_uuids list
                caller.item_uuids.discard(item.uuid)
                # NOTE: add the item to the caller's outgoing_item_uuids list
                caller.outgoing_item_uuids.add(item.uuid)
                # NOTE: add the item to the receiver's incoming_item_uuids list
                receiver.incoming_item_uuids.add(item.uuid)
            # NOTE: set the item to transit
            item.status = lconst.TRANSIT
            # NOTE: add the destination to the item's location_uuids list
            item.location_uuids.append(destination.uuid)
            # NOTE: add the receiver to the item's user_uuids list
            item.user_uuids.append(receiver.uuid)
            # NOTE: save everything
            db.save_existing_item(conn, item, _id)
            db.save_existing_user(conn, caller, _id)
            db.save_existing_user(conn, receiver, _id)
            db.save_existing_location(conn, origin, _id)
            db.save_existing_location(conn, destination, _id)
        return rpc.make_success_resp(item.one_hot_jsonify(), _id)
    except WrappedErrorResponse as e:
        file_logger.log_error({
            "method": "begin_transfer" + str(e.methods),
            "params": params,
            "error": str(e.exception),
        })
        return e.response_obj
    except Exception as e:
        file_logger.log_error({
            "method": "begin_transfer",
            "params": params,
            "error": str(e),
        })
        return rpc.make_error_resp(const.INTERNAL_ERROR_CODE,
                                   const.INTERNAL_ERROR, _id)