def absolute_keywords(doc_id, check_owner=True): """ Fetches the keywords for a document that were created when the document was added. Returns a dictionary / key-value set where the keys are keywords and values are weights. """ response = None _, cur = get_db() cur.execute( 'SELECT d.created, d.name, d.owner_id' ' FROM document d' ' WHERE d.id = %s', (doc_id, )) doc_info = cur.fetchone() if doc_info is None: response = make_response( {"message": "Document with id {} doesn't exist.".format(doc_id)}, 400) if not response: if check_owner and doc_info['owner_id'] != g.user: response = make_response({"message": "Insufficient privileges."}, 403) if not response: cur.execute( 'SELECT keyword_text, keyword_weight' ' FROM keyword' ' WHERE document_id = %s' ' ORDER BY keyword_weight DESC', (doc_id, )) response = dict(cur.fetchall()) return response
def verify_password(username_or_token, password): """ Verification function used by flask_httpauth. Expects either a username and password, or a token. The token is checked first, and username/password verification only proceeds if the token fails. If a valid token is provided the password variable is never used.""" verification_result = False user = verify_auth_token(username_or_token) if user: verification_result = True g.user = user else: _, cur = get_db() cur.execute('SELECT id, password FROM users WHERE username = %s', (username_or_token, )) user = cur.fetchone() if user and check_password_hash(user["password"], password): g.user = user["id"] verification_result = True return verification_result
def delete(doc_id): """ Deletes a document and the keywords associated with it. May only be performed by the user that added the document. """ response = None db, cur = get_db() cur.execute( 'SELECT d.created, d.name, d.owner_id' ' FROM document d' ' WHERE d.id = %s', (doc_id, )) doc_info = cur.fetchone() if doc_info is None: response = make_response( {"message": "Document with id {} doesn't exist.".format(doc_id)}, 400) if not response: if doc_info["owner_id"] != g.user: response = make_response({"message": "Insufficient privileges."}, 403) if not response: cur.execute('DELETE FROM keyword WHERE document_id = %s', (doc_id, )) cur.execute('DELETE FROM document WHERE id = %s', (doc_id, )) db.commit() response = make_response({ "message": "Document {} and its keywords deleted.".format(doc_id) }) return response
def verify_auth_token(token): """ Verifies a token. If verificiation succeeds, the return value is the user_id of the user that obtained the token.""" serializer = Serializer(current_app.config['SECRET_KEY']) user_id = None try: data = serializer.loads(token) _, cur = get_db() cur.execute('SELECT id FROM users WHERE id = %s', (data["id"], )) user_id = cur.fetchone()[0] except (SignatureExpired, BadSignature): pass return user_id
def register(): """ API for registration of a new user. """ error_messages = { "username": "******", "password": "******" } errors = [] for key in error_messages: if key not in request.json: errors.append(error_messages[key]) response = make_response({"message": " ".join(errors)}, 400) if errors else None if not response: username = request.json['username'] password = request.json['password'] db, cur = get_db() cur.execute('SELECT id FROM users WHERE username = %s', (username, )) user_exists = cur.fetchone() if user_exists: response = make_response( {"message": "User {} is already registered.".format(username)}, 400) if not response: cur.execute('INSERT INTO users (username, password) VALUES (%s, %s)', (username, generate_password_hash(password))) db.commit() cur.execute('SELECT max(id) FROM users') user_id = cur.fetchone()[0] response = make_response({ "message": "User {} created.".format(username), "id": user_id }) return response
def app(): app = keywords_service.create_app() app.config["TESTING"] = True with app.app_context(): db, cur = get_db() cur.execute('DELETE from keyword') cur.execute('DELETE from document') cur.execute('DELETE from users') db.commit() for user in test_users: username = user["username"] password = user["password"] cur.execute( 'INSERT INTO users (username, password) VALUES (%s, %s)', (username, generate_password_hash(password)) ) db.commit() yield app
def create_absolute_keywords(): """ Post a document to add it to the working set. When a document is added the content is not stored in the database. Rather, the 'absolute keywords' are extracted along with their weights, and these are stored until the document is deleted. """ error_messages = { "name": "Key 'name' is required.", "content": "Key 'content' is required.", "empty": "No data provided." } errors = [] if not request.json: errors.append(error_messages["empty"]) else: for key in ("name", "content"): if key not in request.json.keys(): errors.append(error_messages[key]) response = make_response({"message": " ".join(errors)}, 400) if errors else None if not response: content = request.json["content"] checksum = hashlib.md5(content.encode('utf-8')).hexdigest() db, cur = get_db() cur.execute( 'SELECT name, id, created FROM document' ' WHERE checksum = %s', (checksum, )) prior_creation = cur.fetchone() if prior_creation: response = make_response( { "message": "Content was added at a prior time ({}).".format( prior_creation["created"]) }, 302) response.headers["Location"] = url_for( 'absolute_keywords.absolute_keywords', doc_id=prior_creation["id"]) if not response: name = request.json["name"] cur.execute( 'INSERT INTO document (name, checksum, owner_id)' ' VALUES (%s, %s, %s)', (name, checksum, g.user)) db.commit() cur.execute('SELECT max(id) FROM document') doc_id = cur.fetchone()[0] keyword_data = extract_keywords(content) records = [(doc_id, keyword_text, keyword_weight) for keyword_text, keyword_weight in keyword_data.items()] for record in records: cur.execute( 'INSERT INTO keyword' ' (document_id, keyword_text, keyword_weight)' ' VALUES (%s, %s, %s)', (record)) db.commit() response = make_response({ "message": "Keywords created.", "id": doc_id }, 201) response.headers["Location"] = url_for( 'absolute_keywords.absolute_keywords', doc_id=doc_id) return response