def on_get(self, req, res, user_id=None): if req.get_header('SUPER-ADMIN-KEY') == SUPER_ADMIN_KEY: if user_id: users = db.fetch_users(user_id=user_id, hide_pass=True) if users: data = { 'id': user_id, 'username': users[0]['username'] } else: error = { 'description': 'Invalid user_id', 'details': f"{user_id} doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error) else: username = req.params.get('username') user_id = req.params.get('id') users = db.fetch_users(username=username, user_id=user_id, hide_pass=True) data = {'count': len(users),'items': users} self.on_success(res, data) else: error = { 'description': 'Unauthorized', 'details': "Permission Denied" } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error)
def on_post(self, req, res): skills = req.get_json('skills') if not isinstance(skills, list): error = { 'description': 'invalid skills', 'details': f"'skills' field needs to be an array/list" } LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) astronaut = { 'id': str(uuid.uuid4()), 'active': True, 'firstName': req.get_json('firstName', dtype=str, min=3, max=20), 'lastName': req.get_json('lastName', dtype=str, min=3, max=20), 'skills': skills, 'hoursInSpace': req.get_json('hoursInSpace', dtype=int, min=0), 'picture': req.get_json('picture', dtype=str, min=3) } try: db.add_astronauts_bulk([astronaut]) except Exception as ex: error = {'description': ex} LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) self.on_created(res, astronaut)
def on_delete(self, req, res, user_id=None): if user_id: users = db.fetch_users(None, user_id=user_id, hide_pass=True) if users: if req.get_header('SUPER_ADMIN_KEY') == SUPER_ADMIN_KEY: db.delete_from_table('users', user_id) if req.params.get('details') == 'true': data = users[0] data['meta'] = {'action': f'user \'{users[0]["username"]}\' has been deleted'} self.on_success(res, data) else: self.on_no_content(res, {}) else: error = { 'description': 'Unauthorized', 'details': "Permission Denied" } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error) else: error = { 'description': 'Invalid user_id', 'details': f"{user_id} doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error) else: raise generic_error_handler(500, req=req)
def on_post(self, req, res): if "multipart/form-data" in req.content_type: username = req.params.get('username') password = req.params.get('password') elif "application/json" in req.content_type: username = req.get_json('username', dtype=str, min=3, max=20) password = req.get_json('password', dtype=str, min=8, max=20) else: error = { 'description': 'Invalid content-type', 'details': 'Only \'multipart/form-data\' and \'json/application\' allowed' } LOG.error(error) raise generic_error_handler(415, req=req, error_override=error) users = db.fetch_users(username) if len(users) >= 1: error = { 'description': 'Invalid username', 'details': f"user '{username}' already exists." } LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) else: user_id = str(uuid.uuid4()) pasword = make_password_hashing(password) db.create_user(user_id, username, pasword) data = { 'id': user_id, 'username': username } self.on_created(res, data)
def on_put(self, req, res): username = req.get_json('username', dtype=str, min=3, max=20) password = req.get_json('password', dtype=str, min=8, max=20) new_password = req.get_json('new_password', dtype=str, min=8, max=20) users = db.fetch_users(username) user_id = str(uuid.uuid4()) pasword = make_password_hashing(new_password) if len(users) == 1: if not checking_password_hash(password, users[0]['password']): error = { 'description': 'Incorrect password entered', } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error) else: db.replace_user_info(user_id, username, pasword) elif len(users) > 1: error = { 'description': f"There was more than 1 user found for username: '******'" } LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) else: db.create_user(user_id, username, pasword) data = { 'id': user_id, 'username': username } self.on_success(res, data)
def create_user(id_, username, password): conn = create_connection(DATABASE) c = conn.cursor() try: c.execute("INSERT INTO users(id_, username, password) VALUES(?, ?, ?)", (id_, username, password)) conn.commit() except sqlite3.IntegrityError as ex: LOG.error(ex) raise Exception(ex) conn.close()
def create_table(conn, create_table_sql): """ create a table from the create_table_sql statement :param conn: Connection object :param create_table_sql: a CREATE TABLE statement :return: """ try: c = conn.cursor() c.execute(create_table_sql) except Error as ex: LOG.error(ex) raise Exception(ex)
def replace_user_info(id_, username, password): conn = create_connection(DATABASE) c = conn.cursor() try: c.execute(f"DELETE FROM users WHERE username=?", (username, )) c.execute("INSERT INTO users(id_, username, password) VALUES(?, ?, ?)", (id_, username, password)) conn.commit() except sqlite3.IntegrityError as ex: LOG.error(ex) raise Exception(ex) conn.close()
def create_connection(db_file): """ create a database connection to the SQLite database specified by db_file :param db_file: database file :return: Connection object or None """ try: conn = sqlite3.connect(db_file) return conn except Error as ex: LOG.error(ex) raise Exception(ex) return None
def on_get(self, req, res, id_): params = {'id_': id_} astronauts = db.fetch_astronauts(filters=params) if astronauts: data = astronauts[0] else: error = { 'description': 'Invalid astronaut', 'details': f"An astronaut with id '{id_}' doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error) self.on_success(res, data)
def init_session(): conn = create_connection(DATABASE) if conn is not None: drop_table('users') drop_table('astronauts') create_table(conn, sql_create_users_table) create_table(conn, sql_create_astronauts_table) add_astronauts_bulk(ASTRONAUTS) else: message = "Cannot create database connection!" LOG.error(message) raise Exception(message) conn.close()
def validate_token(req, resp, resource, params): LOG.debug('JWT Validation') token = req.get_header('Authorization') if token is None: error = { "description": "Please provide JWT token as part of the request." } raise generic_error_handler(401, error_override=error) try: token_is_valid(req, token) except Exception as ex: error = {"description": "invalid token, try again", "details": str(ex)} raise generic_error_handler(401, error_override=error)
def token_is_valid(req, token): if token.startswith("JWT "): token_type = "JWT" else: LOG.error("Token validation failed") raise Exception("Invalid token type -> Only 'JWT' allowed") req.jwt_token = token token = token.split(f"{token_type} ")[1] try: jwt_body = jwt.decode(token, API_SECRET_KEY, verify=True, algorithms=['HS256']) if 'username' in jwt_body: req.username = jwt_body['username'] except Exception as ex: LOG.error(f"There was an error : {ex}") raise Exception(f"{ex}")
def on_post(self, req, res): username = req.get_json('username', dtype=str) password = req.get_json('password', dtype=str) users = db.fetch_users(username) if len(users) == 1: if not checking_password_hash(password, users[0]['password']): error = { 'description': 'either username or password is invalid' } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error) else: payload = OrderedDict() payload['id'] = users[0]['id'] payload['username'] = username data = jwt_payload_handler(payload) payload = {**payload, **data} self.on_success(res, payload) elif len(users) > 1: error = { 'description': f"There was more than 1 user found for username: '******'" } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error) else: error = {'description': 'either username or password is invalid'} LOG.error(error) raise generic_error_handler(401, req=req, error_override=error)
def on_patch(self, req, res, id_): params = {'id_': id_} astronauts = db.fetch_astronauts(filters=params) if astronauts: data = astronauts[0] payload = OrderedDict() payload["active"] = req.get_json("active", default=data['active']) payload["firstName"] = req.get_json("firstName", default=data['firstName']) payload["lastName"] = req.get_json("lastName", default=data['lastName']) skills = req.get_json("skills", default=data['skills']) if not isinstance(skills, list): error = { 'description': 'invalid skills', 'details': f"'skills' field needs to be an array/list" } LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) payload["skills"] = skills payload["hoursInSpace"] = req.get_json( "hoursInSpace", default=data['hoursInSpace']) payload["picture"] = req.get_json("picture", default=data['picture']) db.update_astronaut_info(id_, fields=payload) else: error = { 'description': 'Invalid astronaut', 'details': f"An astronaut with id '{id_}' doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error) payload = {**{'id': id_}, **payload} self.on_success(res, payload)
def __init__(self, *args, **kwargs): super(App, self).__init__(*args, **kwargs) LOG.info(f'Starting {APP_NAME}') self.add_route('/', base.BaseResource()) # Users self.add_route('/api/users', users.Users()) self.add_route('/api/users/{user_id}', users.Users()) # Credentials to get JWT self.add_route('/api/credentials', users.JWTLogin()) # Astronauts self.add_route('/api/astronauts', astronauts.List()) self.add_route('/api/astronauts/{id_}', astronauts.Detail()) # This catches none existing paths self.add_sink(generic_path_error_handler, '') # This is needed starting in Falcon 2.0 (where the default value changed # from `True` to `False`). self.req_options.strip_url_path_trailing_slash = True
def on_delete(self, req, res, id_): params = {'id_': id_} astronauts = db.fetch_astronauts(filters=params) if astronauts: data = astronauts[0] astronaut_id = astronauts[0]['id'] db.delete_from_table('astronauts', astronaut_id) else: error = { 'description': 'Invalid astronaut', 'details': f"An astronaut with id '{id_}' doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error) if req.params.get('details') == 'true': data['meta'] = { 'action': f'astronaut {astronauts[0]["firstName"]} {astronauts[0]["lastName"]} has been deleted' } self.on_success(res, data) else: self.on_no_content(res, {})
def add_astronauts_bulk(astronauts): conn = create_connection(DATABASE) c = conn.cursor() for astronaut in astronauts: skills = ",".join(astronaut["skills"]) try: c.execute(f"""INSERT INTO astronauts ( id_, active, firstName, lastName, skills, hoursInSpace, picture) VALUES ( '{astronaut["id"]}', '{astronaut["active"]}', '{astronaut["firstName"]}', '{astronaut["lastName"]}', '{skills}', '{astronaut["hoursInSpace"]}', '{astronaut["picture"]}');""") except sqlite3.IntegrityError as ex: conn.close() LOG.error(ex) raise Exception( f"{ex} when processing: {astronaut['firstName']} {astronaut['lastName']}" ) conn.commit() conn.close()
def on_patch(self, req, res): username = req.get_json('username', dtype=str, min=3, max=20) password = req.get_json('password', dtype=str, min=8, max=20) new_password = req.get_json('new_password', dtype=str, min=8, max=20) pasword = make_password_hashing(new_password) users = db.fetch_users(username) if len(users) == 1: if not checking_password_hash(password, users[0]['password']): error = { 'description': 'Incorrect password entered', } LOG.error(error) raise generic_error_handler(401, req=req, error_override=error) else: db.update_password(users[0]['id'], pasword) data = { 'id': users[0]['id'], 'username': username } self.on_success(res, data) elif len(users) > 1: error = { 'description': f"There was more than 1 user found for username: '******'" } LOG.error(error) raise generic_error_handler(400, req=req, error_override=error) else: error = { 'description': 'Invalid username', 'details': f"{username} doesn't exist." } LOG.error(error) raise generic_error_handler(404, req=req, error_override=error)