Skip to content

Commit

Permalink
Login integration (#156)
Browse files Browse the repository at this point in the history
* Integrated login page with API.

* Added ability for login to store cookie to browser

* Linting pass
  • Loading branch information
ansengarvin authored Feb 3, 2024
1 parent a991c1d commit 03a5c3d
Show file tree
Hide file tree
Showing 15 changed files with 95 additions and 74 deletions.
12 changes: 6 additions & 6 deletions backend/src/api/users.py
Original file line number Diff line number Diff line change
@@ -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:
Expand All @@ -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.")
10 changes: 2 additions & 8 deletions backend/src/api_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand All @@ -39,6 +40,7 @@
"type": "module",
"dependencies": {
"bibtex": "^0.9.0",
"js-cookie": "^3.0.5",
"marked": "^10.0.0"
}
}
3 changes: 1 addition & 2 deletions frontend/src/openapi/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down
1 change: 0 additions & 1 deletion frontend/src/openapi/models/EditBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ export type EditBody = {
newContent?: (string | null);
newRefs?: (string | null);
};

1 change: 0 additions & 1 deletion frontend/src/openapi/models/HTTPValidationError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ import type { ValidationError } from './ValidationError';
export type HTTPValidationError = {
detail?: Array<ValidationError>;
};

1 change: 0 additions & 1 deletion frontend/src/openapi/models/LoginBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ export type LoginBody = {
email: string;
password: string;
};

11 changes: 0 additions & 11 deletions frontend/src/openapi/models/LoginError.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/* tslint:disable */
/* eslint-disable */

export type ResponseToken = {
export type LoginResponse = {
token: string;
error: string;
};

1 change: 0 additions & 1 deletion frontend/src/openapi/models/ProteinEntry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ export type ProteinEntry = {
content?: (string | null);
refs?: (string | null);
};

1 change: 0 additions & 1 deletion frontend/src/openapi/models/UploadBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,3 @@ export type UploadBody = {
refs: string;
pdbFileStr: string;
};

1 change: 0 additions & 1 deletion frontend/src/openapi/models/ValidationError.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,3 @@ export type ValidationError = {
msg: string;
type: string;
};

59 changes: 29 additions & 30 deletions frontend/src/openapi/services/DefaultService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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<LoginResponse> {
return __request(OpenAPI, {
method: 'POST',
url: '/users/login',
Expand All @@ -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<any> {
proteinName: string,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/pdb/{protein_name}',
Expand All @@ -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<any> {
proteinName: string,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'GET',
url: '/fasta/{protein_name}',
Expand All @@ -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
*/
Expand All @@ -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<ProteinEntry> | null)> {
proteinName: string,
): CancelablePromise<(Array<ProteinEntry> | null)> {
return __request(OpenAPI, {
method: 'GET',
url: '/search-entries/{protein_name}',
Expand All @@ -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}',
Expand All @@ -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<any> {
proteinName: string,
): CancelablePromise<any> {
return __request(OpenAPI, {
method: 'DELETE',
url: '/protein-entry/{protein_name}',
Expand All @@ -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',
Expand All @@ -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',
Expand Down
52 changes: 43 additions & 9 deletions frontend/src/routes/login/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,30 +1,64 @@
<script lang="ts">
import { Backend, type LoginResponse } from "$lib/backend";
import { Button, Label, Input } from "flowbite-svelte";
import Cookies from "js-cookie";
let username: string = "";
let email: string = "";
let password: string = "";
$: formValid = username.length > 0 && password.length > 0;
$: formValid = email.length > 0 && password.length > 0;
let error = false;
let token = "";
/**
* Gets run on button "Login" or form submit (pressing enter)
* @todo add login logic with tokens and making a request to the backend
*/
function submitForm() {
let result: LoginResponse | null=null
async function submitForm() {
if (!formValid) return;
console.log("submitted");
console.table({ username, password });
try {
// Attempting to get a valid authentication token from the API
result = await Backend.login({
email,
password
})
if (result==null) {
// If result is null, log to console. Don't expect this would happen.
console.log("Response is null")
} else if (result['error'] != "") {
// User entered wrong username or password, or account doesn't exist.
// @todo Display this error message to the user.
console.log("Response received. Error: " + result['error'])
} else if (result['token'] != "") {
// User entered the correct username / password and got a result.
// @todo Store this in a cookie.
console.log("Response received. Token: " + result['token'])
Cookies.set('auth', result['token'])
} else {
// User got a result, but both fields are null. This should never happen.
console.log("Unexpected edge cage regarding user authentication.")
}
} catch (e){
console.log(e)
}
}
</script>

<form on:submit={submitForm} class="flex gap-5 flex-col p-5">
<div>
<Label for="username">Username</Label>
<Label for="email">Email</Label>
<Input
id="username"
id="email"
style="width: 300px;"
bind:value={username}
placeholder="Enter your username..."
bind:value={email}
placeholder="Enter your email..."
/>
</div>

Expand Down
10 changes: 10 additions & 0 deletions frontend/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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"
Expand Down

0 comments on commit 03a5c3d

Please sign in to comment.