def refresh(): try: current_user = get_jwt_identity() value = { 'access_token': create_access_token(identity=current_user, expires_delta=False) } return response_with(resp.CREATED_201, value) except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def expired_token_callback(expired_token): token_type = expired_token['type'] value = { 'sub_status': 666, 'msg': f'The {token_type} token has expired' } return response_with(resp.UNAUTHORIZED_401, value)
def verify_email(token): try: email = confirm_verification_token(token) except: return response_with(resp.SERVER_ERROR_401) user = User.query.filter_by(email=email).first_or_404() if user.isVerified: return response_with(resp.INVALID_INPUT_422) else: user.isVerified = True db.session.add(user) db.session.commit() return response_with( resp.SUCCESS_200, value={'message': 'E-mail verified, you can proceed to login now.'})
def update_book_detail(id): data, get_book = _find_book_by_id(id) get_book.title = data['title'] get_book.year = data['year'] _persist(db, get_book, action='update') book_schema = BookSchema() book = book_schema.dump(get_book) return response_with(resp.SUCCESS_200, value={"book": book})
def _persist(db, book, action='add'): try: if action == 'update': db.session.add(book) elif action == 'delete': db.session.delete(book) else: raise Exception("action is either update or delete") db.session.commit() except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def authenticate_user(): try: data = request.get_json() if data.get('email'): current_user = User.find_by_email(data['email']) elif data.get('username'): current_user = User.find_by_username(data['username']) else: # TODO: raise exception pass if not current_user: return response_with(resp.SERVER_ERROR_404) if current_user and not current_user.isVerified: return response_with(resp.BAD_REQUEST_400) if User.verify_hash(data['password'], current_user.password): access_token = create_access_token(identity=current_user.username, expires_delta=False) refresh_token = create_refresh_token( identity=current_user.username, expires_delta=False) return response_with(resp.SUCCESS_200, value={ 'message': f'Logged in as {current_user.username}', 'access_token': access_token, 'refresh_token': refresh_token }) else: return response_with(resp.UNAUTHORIZED_401) except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def get_author_detail(author_id): """ Get author details endpoint --- parameters: - name: author_id in: path description: author ID required: true schema: type: integer responses: 200: description: Author Details schema: properties: code: type: string message: type: string author: schema: properties: id: type: integer first_name: type: string last_name: type: string 404: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ fetched = Author.query.get_or_404(author_id) author_schema = AuthorSchema() author = author_schema.dump(fetched) return response_with(resp.SUCCESS_200, value={"author": author})
def delete_book(id): """ Delete book endpoint --- parameters: - name: id in: path description: book ID required: true schema: type: integer - in: header name: authorization type: string required: true security: - Bearer: [] responses: 204: description: Book successfully deleted schema: 422: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ get_book = Book.query.get_or_404(id) _persist(db, get_book, action='delete') return response_with(resp.SUCCESS_204)
def get_book_detail(book_id): fetched = Book.query.get_or_404(book_id) book_schema = BookSchema() book = book_schema.dump(fetched) return response_with(resp.SUCCESS_200, value={"book": book})
def create_book(): """ Create book endpoint --- parameters: - in: body name: body schema: id: Book required: - title - year - author_id properties: title: type: string description: Title of the book year: type: integer description: Year book was published author_id: type: integer description: Book's author - in: header name: authorization type: string required: true security: - Bearer: [] responses: 201: description: Book successfully created schema: id: BookCreated properties: code: type: string message: type: string value: schema: id: BookFull properties: title: type: string year: type: integer author_id: type: integer 422: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ try: data = request.get_json() book_schema = BookSchema() book = book_schema.load(data) result = book_schema.dump(book.create()) return response_with(resp.CREATED_201, value={"book": result}) except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def create_user(): """ Create user endpoint --- parameters: - in: body name: body schema: id: UserSignup required: - username - password - email properties: username: type: string description: Unique username of the user default: "John Doe" password: type: string description: Password of the user default: "something strong" email: type: string description: email of the user default: "*****@*****.**" responses: 201: description: User successfully created schema: id: UserSignUpSchema properties: code: type: string 422: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ try: data = request.get_json() ## user already defined if User.find_by_email(data['email']) is not None or \ User.find_by_username(data['username']) is not None: return response_with(resp.INVALID_INPUT_422) ## ok user does not yet exist data['password'] = User.generate_hash(data['password']) user_schema = UserSchema() user = user_schema.load(data) token = generate_verification_token(data['email']) verif_email = url_for('user_routes.verify_email', token=token, _external=True) html = render_template_string( "<p>Welcome! Thanks for signing up.Please follow this link to activate your account:</p> <p><a href='{{ verif_email }}'>{{ verif_email }}</a></p> <br /> <p>Thank you</p>", verification_email=verif_email) subject = "Please Verify your email" curr_env = current_app.config['ENV'] if curr_env != 'development' and curr_env != 'testing': send_email(user.email, subject, html) else: logging.error(f"email: {user.email}, subject: {subject}") logging.error(html) logging.error(verif_email) result = user_schema.dump(user.create()) return response_with(resp.CREATED_201) except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def not_found(err): logging.error(err) return response_with(resp.SERVER_ERROR_404)
def get_author_list(): """ Get author list endpoint --- parametrers: responses: 200: description: Author List schema: properties: code: type: string message: type: string count: type: integer next_url: type: string prev_url: type: string authors: type: array items: schema: properties: id: type: integer first_name: type: string last_name: type: string """ page = request.args.get('page', 1, type=int) # default 1st page, cast it as an int num_item_per_page = current_app.config['YABOOK_ITEMS_PER_PAGE'] # start from first page: if page < 0: page = 1 pagination = Author.query.paginate(page, per_page=num_item_per_page, error_out=False) count = pagination.total max_pages = count // num_item_per_page max_pages += 0 if count % num_item_per_page == 0 else 1 fetched = pagination.items prev_url, next_url = None, None if pagination.has_prev: if page <= max_pages: prev_url = url_for('author_routes.get_author_list', page=page - 1) else: # point to actual last page (for example) prev_url = url_for('author_routes.get_author_list', page=max_pages) if pagination.has_next: next_url = url_for('author_routes.get_author_list', page=page + 1) author_schema = AuthorSchema(many=True, only=['first_name', 'last_name', 'id']) authors = author_schema.dump(fetched) value = { 'authors': authors, 'prev_url': prev_url, 'next_url': next_url, 'count': count } return response_with(resp.SUCCESS_200, value=value)
def modify_author_detail(id): """ Partial Update author endpoint --- parameters: - in: body name: body schema: id: Author optional: - first_name - last_name properties: first_name: type: string description: First name of the author last_name: type: string description: Last name of the author - name: id in: path description: author ID required: true schema: type: integer - in: header name: authorization type: string required: true security: - Bearer: [] responses: 200: description: Author successfully updated schema: id: AuthorModified properties: code: type: string message: type: string value: schema: id: AuthorFull properties: first_name: type: string last_name: type: string created_at: type: string format: date-time books: type: array items: schema: id: BookSchema 422: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ data, get_author = _find_author_by_id(id) if data.get('first_name'): get_author.first_name = data['first_name'] if data.get('last_name'): get_author.last_name = data['last_name'] _persist(db, get_author, action='update') author_schema = AuthorSchema() author = author_schema.dump(get_author) return response_with(resp.SUCCESS_200, value={"author": author})
def create_author(): """ Create author endpoint --- parameters: - in: body name: body schema: id: Author required: - first_name - last_name - books properties: first_name: type: string description: First name of the author default: "John" last_name: type: string description: Last name of the author default: "Doe" - in: header name: authorization type: string required: true security: - Bearer: [] responses: 201: description: Author successfully created schema: id: AuthorCreated properties: code: type: string message: type: string value: schema: id: AuthorFull properties: first_name: type: string last_name: type: string books: type: array items: schema: id: BookSchema 422: description: Invalid input arguments schema: id: invalidInput properties: code: type: string message: type: string """ try: data = request.get_json() author_schema = AuthorSchema() author = author_schema.load(data) result = author_schema.dump(author.create()) # .data return response_with(resp.CREATED_201, value={"author": result}) except Exception as ex: logging.error(f"Intercepted Exception: {ex}") return response_with(resp.INVALID_INPUT_422)
def server_error(err): logging.error(e) return response_with(resp.SERVER_ERROR_500)
def get_book_list(): """ Get book list endpoint --- parametrers: responses: 200: description: Book List schema: properties: code: type: string message: type: string value: schema: books: type: array items: schema: id: BookFull properties: title: type: string year: type: integer author_id: type: integer """ page = request.args.get('page', 1, type=int) # default 1st page, cast it as an int num_item_per_page = current_app.config['YABOOK_ITEMS_PER_PAGE'] # start from first page: if page < 0: page = 1 pagination = Book.query.paginate(page, per_page=num_item_per_page, error_out=False) count = pagination.total max_pages = count // num_item_per_page max_pages += 0 if count % num_item_per_page == 0 else 1 fetched = pagination.items prev_url, next_url = None, None if pagination.has_prev: if page <= max_pages: prev_url = url_for('book_routes.get_book_list', page=page - 1) else: # point to actual last page (for example) prev_url = url_for('book_routes.get_book_list', page=max_pages) if pagination.has_next: next_url = url_for('book_routes.get_book_list', page=page + 1) book_schema = BookSchema(many=True, only=['author_id', 'title', 'year']) books = book_schema.dump(fetched) value = { 'books': books, 'prev_url': prev_url, 'next_url': next_url, 'count': count } return response_with(resp.SUCCESS_200, value=value)
def bad_request(err): logging.error(err) return response_with(resp.BAD_REQUEST_400)