From 03a5c3d3e2960eda781e9cb1c67fda2426c7169d Mon Sep 17 00:00:00 2001 From: ansengarvin <45224464+ansengarvin@users.noreply.github.com> Date: Fri, 2 Feb 2024 20:28:36 -0800 Subject: [PATCH] Login integration (#156) * Integrated login page with API. * Added ability for login to store cookie to browser * Linting pass --- backend/src/api/users.py | 12 ++-- backend/src/api_types.py | 10 +--- frontend/package.json | 2 + frontend/src/openapi/index.ts | 3 +- frontend/src/openapi/models/EditBody.ts | 1 - .../src/openapi/models/HTTPValidationError.ts | 1 - frontend/src/openapi/models/LoginBody.ts | 1 - frontend/src/openapi/models/LoginError.ts | 11 ---- .../{ResponseToken.ts => LoginResponse.ts} | 4 +- frontend/src/openapi/models/ProteinEntry.ts | 1 - frontend/src/openapi/models/UploadBody.ts | 1 - .../src/openapi/models/ValidationError.ts | 1 - .../src/openapi/services/DefaultService.ts | 59 +++++++++---------- frontend/src/routes/login/+page.svelte | 52 +++++++++++++--- frontend/yarn.lock | 10 ++++ 15 files changed, 95 insertions(+), 74 deletions(-) delete mode 100644 frontend/src/openapi/models/LoginError.ts rename frontend/src/openapi/models/{ResponseToken.ts => LoginResponse.ts} (75%) diff --git a/backend/src/api/users.py b/backend/src/api/users.py index bf6639fc..27791d9c 100644 --- a/backend/src/api/users.py +++ b/backend/src/api/users.py @@ -1,14 +1,14 @@ from fastapi import APIRouter import logging as log from passlib.hash import bcrypt -from ..api_types import LoginBody, LoginError, ResponseToken +from ..api_types import LoginBody, LoginResponse from ..db import Database from ..auth import generateAuthToken router = APIRouter() -@router.post("/users/login", response_model=ResponseToken | LoginError) +@router.post("/users/login", response_model=LoginResponse | None) def login(body: LoginBody): with Database() as db: try: @@ -22,20 +22,20 @@ def login(body: LoginBody): # Returns "incorrect email/password" message if there is no such account. if entry_sql is None or len(entry_sql) == 0: - return LoginError.INCORRECT + return LoginResponse(token="", error="Invalid Email or Password") # Grabs the stored hash and admin. password_hash, admin = entry_sql[0] # Returns "incorrect email/password" message if password is incorrect. if not bcrypt.verify(password, password_hash): - return LoginError.INCORRECT + return LoginResponse(token="", error="Invalid Email or Password") # Generates the token and returns token = generateAuthToken(email, admin) - return ResponseToken(token=token) + return LoginResponse(token=token, error="") except Exception as e: log.error(e) # TODO: Return something better than query error - return LoginError.QUERY_ERROR + return LoginResponse(token="", error="Server error.") diff --git a/backend/src/api_types.py b/backend/src/api_types.py index ae9db3ac..abab1dec 100644 --- a/backend/src/api_types.py +++ b/backend/src/api_types.py @@ -69,12 +69,6 @@ class LoginBody(CamelModel): password: str -class LoginError(str, enum.Enum): - DEBUG_ACCOUNT = "Debug: Account Not Found" - DEBUG_PASSWORD = "Debug: Incorrect password" - INCORRECT = "Invalid Email or Password" - QUERY_ERROR = "QUERY_ERROR" - - -class ResponseToken(CamelModel): +class LoginResponse(CamelModel): token: str + error: str diff --git a/frontend/package.json b/frontend/package.json index bc851907..bc38ade8 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -19,6 +19,7 @@ "@sveltejs/adapter-auto": "^2.0.0", "@sveltejs/kit": "^1.20.4", "@types/cookie": "^0.5.1", + "@types/js-cookie": "^3.0.6", "autoprefixer": "^10.4.14", "flowbite": "^2.1.1", "flowbite-svelte": "^0.44.19", @@ -39,6 +40,7 @@ "type": "module", "dependencies": { "bibtex": "^0.9.0", + "js-cookie": "^3.0.5", "marked": "^10.0.0" } } diff --git a/frontend/src/openapi/index.ts b/frontend/src/openapi/index.ts index 62b90b9b..f16baf35 100644 --- a/frontend/src/openapi/index.ts +++ b/frontend/src/openapi/index.ts @@ -10,9 +10,8 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { EditBody } from './models/EditBody'; export type { HTTPValidationError } from './models/HTTPValidationError'; export type { LoginBody } from './models/LoginBody'; -export { LoginError } from './models/LoginError'; +export type { LoginResponse } from './models/LoginResponse'; export type { ProteinEntry } from './models/ProteinEntry'; -export type { ResponseToken } from './models/ResponseToken'; export type { UploadBody } from './models/UploadBody'; export { UploadError } from './models/UploadError'; export type { ValidationError } from './models/ValidationError'; diff --git a/frontend/src/openapi/models/EditBody.ts b/frontend/src/openapi/models/EditBody.ts index b0bf7ae9..214bf290 100644 --- a/frontend/src/openapi/models/EditBody.ts +++ b/frontend/src/openapi/models/EditBody.ts @@ -11,4 +11,3 @@ export type EditBody = { newContent?: (string | null); newRefs?: (string | null); }; - diff --git a/frontend/src/openapi/models/HTTPValidationError.ts b/frontend/src/openapi/models/HTTPValidationError.ts index c0bcc87c..e218a9f3 100644 --- a/frontend/src/openapi/models/HTTPValidationError.ts +++ b/frontend/src/openapi/models/HTTPValidationError.ts @@ -8,4 +8,3 @@ import type { ValidationError } from './ValidationError'; export type HTTPValidationError = { detail?: Array; }; - diff --git a/frontend/src/openapi/models/LoginBody.ts b/frontend/src/openapi/models/LoginBody.ts index c1d3fa38..bdd5b19b 100644 --- a/frontend/src/openapi/models/LoginBody.ts +++ b/frontend/src/openapi/models/LoginBody.ts @@ -7,4 +7,3 @@ export type LoginBody = { email: string; password: string; }; - diff --git a/frontend/src/openapi/models/LoginError.ts b/frontend/src/openapi/models/LoginError.ts deleted file mode 100644 index 56f0c5fb..00000000 --- a/frontend/src/openapi/models/LoginError.ts +++ /dev/null @@ -1,11 +0,0 @@ -/* generated using openapi-typescript-codegen -- do no edit */ -/* istanbul ignore file */ -/* tslint:disable */ -/* eslint-disable */ - -export enum LoginError { - DEBUG_ACCOUNT_NOT_FOUND = 'Debug: Account Not Found', - DEBUG_INCORRECT_PASSWORD = 'Debug: Incorrect password', - INVALID_EMAIL_OR_PASSWORD = 'Invalid Email or Password', - QUERY_ERROR = 'QUERY_ERROR', -} diff --git a/frontend/src/openapi/models/ResponseToken.ts b/frontend/src/openapi/models/LoginResponse.ts similarity index 75% rename from frontend/src/openapi/models/ResponseToken.ts rename to frontend/src/openapi/models/LoginResponse.ts index 6aeffa32..f3ecf279 100644 --- a/frontend/src/openapi/models/ResponseToken.ts +++ b/frontend/src/openapi/models/LoginResponse.ts @@ -3,7 +3,7 @@ /* tslint:disable */ /* eslint-disable */ -export type ResponseToken = { +export type LoginResponse = { token: string; + error: string; }; - diff --git a/frontend/src/openapi/models/ProteinEntry.ts b/frontend/src/openapi/models/ProteinEntry.ts index 95c53a8b..dcfd6f59 100644 --- a/frontend/src/openapi/models/ProteinEntry.ts +++ b/frontend/src/openapi/models/ProteinEntry.ts @@ -11,4 +11,3 @@ export type ProteinEntry = { content?: (string | null); refs?: (string | null); }; - diff --git a/frontend/src/openapi/models/UploadBody.ts b/frontend/src/openapi/models/UploadBody.ts index 2619843c..1b8e388b 100644 --- a/frontend/src/openapi/models/UploadBody.ts +++ b/frontend/src/openapi/models/UploadBody.ts @@ -10,4 +10,3 @@ export type UploadBody = { refs: string; pdbFileStr: string; }; - diff --git a/frontend/src/openapi/models/ValidationError.ts b/frontend/src/openapi/models/ValidationError.ts index 18997ec7..0a3e90e9 100644 --- a/frontend/src/openapi/models/ValidationError.ts +++ b/frontend/src/openapi/models/ValidationError.ts @@ -8,4 +8,3 @@ export type ValidationError = { msg: string; type: string; }; - diff --git a/frontend/src/openapi/services/DefaultService.ts b/frontend/src/openapi/services/DefaultService.ts index b04fc73f..aa3f7c6d 100644 --- a/frontend/src/openapi/services/DefaultService.ts +++ b/frontend/src/openapi/services/DefaultService.ts @@ -4,9 +4,8 @@ /* eslint-disable */ import type { EditBody } from '../models/EditBody'; import type { LoginBody } from '../models/LoginBody'; -import type { LoginError } from '../models/LoginError'; +import type { LoginResponse } from '../models/LoginResponse'; import type { ProteinEntry } from '../models/ProteinEntry'; -import type { ResponseToken } from '../models/ResponseToken'; import type { UploadBody } from '../models/UploadBody'; import type { UploadError } from '../models/UploadError'; @@ -18,13 +17,13 @@ export class DefaultService { /** * Login - * @param requestBody - * @returns any Successful Response + * @param requestBody + * @returns LoginResponse Successful Response * @throws ApiError */ public static login( - requestBody: LoginBody, - ): CancelablePromise<(ResponseToken | LoginError)> { +requestBody: LoginBody, +): CancelablePromise { return __request(OpenAPI, { method: 'POST', url: '/users/login', @@ -38,13 +37,13 @@ export class DefaultService { /** * Get Pdb File - * @param proteinName + * @param proteinName * @returns any Successful Response * @throws ApiError */ public static getPdbFile( - proteinName: string, - ): CancelablePromise { +proteinName: string, +): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/pdb/{protein_name}', @@ -59,13 +58,13 @@ export class DefaultService { /** * Get Fasta File - * @param proteinName + * @param proteinName * @returns any Successful Response * @throws ApiError */ public static getFastaFile( - proteinName: string, - ): CancelablePromise { +proteinName: string, +): CancelablePromise { return __request(OpenAPI, { method: 'GET', url: '/fasta/{protein_name}', @@ -81,7 +80,7 @@ export class DefaultService { /** * Get All Entries * Gets all protein entries from the database - * Returns: list[ProteinEntry] if found | None if not found + * Returns: list[ProteinEntry] if found | None if not found * @returns any Successful Response * @throws ApiError */ @@ -95,14 +94,14 @@ export class DefaultService { /** * Search Entries * Gets a list of protein entries by a search string - * Returns: list[ProteinEntry] if found | None if not found - * @param proteinName + * Returns: list[ProteinEntry] if found | None if not found + * @param proteinName * @returns any Successful Response * @throws ApiError */ public static searchEntries( - proteinName: string, - ): CancelablePromise<(Array | null)> { +proteinName: string, +): CancelablePromise<(Array | null)> { return __request(OpenAPI, { method: 'GET', url: '/search-entries/{protein_name}', @@ -118,14 +117,14 @@ export class DefaultService { /** * Get Protein Entry * Get a single protein entry by its id - * Returns: ProteinEntry if found | None if not found - * @param proteinName + * Returns: ProteinEntry if found | None if not found + * @param proteinName * @returns any Successful Response * @throws ApiError */ public static getProteinEntry( - proteinName: string, - ): CancelablePromise<(ProteinEntry | null)> { +proteinName: string, +): CancelablePromise<(ProteinEntry | null)> { return __request(OpenAPI, { method: 'GET', url: '/protein-entry/{protein_name}', @@ -140,13 +139,13 @@ export class DefaultService { /** * Delete Protein Entry - * @param proteinName + * @param proteinName * @returns any Successful Response * @throws ApiError */ public static deleteProteinEntry( - proteinName: string, - ): CancelablePromise { +proteinName: string, +): CancelablePromise { return __request(OpenAPI, { method: 'DELETE', url: '/protein-entry/{protein_name}', @@ -161,13 +160,13 @@ export class DefaultService { /** * Upload Protein Entry - * @param requestBody + * @param requestBody * @returns any Successful Response * @throws ApiError */ public static uploadProteinEntry( - requestBody: UploadBody, - ): CancelablePromise<(UploadError | null)> { +requestBody: UploadBody, +): CancelablePromise<(UploadError | null)> { return __request(OpenAPI, { method: 'POST', url: '/protein-upload', @@ -181,13 +180,13 @@ export class DefaultService { /** * Edit Protein Entry - * @param requestBody + * @param requestBody * @returns any Successful Response * @throws ApiError */ public static editProteinEntry( - requestBody: EditBody, - ): CancelablePromise<(UploadError | null)> { +requestBody: EditBody, +): CancelablePromise<(UploadError | null)> { return __request(OpenAPI, { method: 'PUT', url: '/protein-edit', diff --git a/frontend/src/routes/login/+page.svelte b/frontend/src/routes/login/+page.svelte index de276f02..9608903c 100644 --- a/frontend/src/routes/login/+page.svelte +++ b/frontend/src/routes/login/+page.svelte @@ -1,30 +1,64 @@
- +
diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 05348b58..e925d6d1 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -330,6 +330,11 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.3.tgz#2be19e759a3dd18c79f9f436bd7363556c1a73dd" integrity sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ== +"@types/js-cookie@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.6.tgz#a04ca19e877687bd449f5ad37d33b104b71fdf95" + integrity sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ== + "@types/json-schema@^7.0.6": version "7.0.14" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.14.tgz#74a97a5573980802f32c8e47b663530ab3b6b7d1" @@ -969,6 +974,11 @@ jiti@^1.19.1: resolved "https://registry.yarnpkg.com/jiti/-/jiti-1.21.0.tgz#7c97f8fe045724e136a397f7340475244156105d" integrity sha512-gFqAIbuKyyso/3G2qhiO2OM6shY6EPP/R0+mkDbyspxKazh8BXDC5FiFsUjlczgdNz/vfra0da2y+aHrusLG/Q== +js-cookie@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc" + integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw== + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"