Skip to content

Commit 5f844c6

Browse files
Merge branch 'CHAOS-529-email-sending' of https://github.com/devsoc-unsw/chaos into CHAOS-529-email-sending
2 parents fc228ab + 79983e1 commit 5f844c6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1317
-757
lines changed

backend/migrations/20240406023149_create_users.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ CREATE TABLE users (
99
gender TEXT,
1010
degree_name TEXT,
1111
degree_starting_year INTEGER,
12-
role user_role NOT NULL,
12+
role user_role NOT NULL DEFAULT 'User',
1313
created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
1414
updated_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
1515
);

backend/server/src/handler/auth.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ use crate::service::auth::create_or_get_user_id;
1111
use crate::service::jwt::encode_auth_token;
1212
use axum::extract::{Query, State};
1313
use axum::response::IntoResponse;
14-
use axum::Extension;
15-
use oauth2::basic::BasicClient;
1614
use oauth2::reqwest::async_http_client;
1715
use oauth2::{AuthorizationCode, TokenResponse};
1816

@@ -38,9 +36,8 @@ use oauth2::{AuthorizationCode, TokenResponse};
3836
pub async fn google_callback(
3937
State(state): State<AppState>,
4038
Query(query): Query<AuthRequest>,
41-
Extension(oauth_client): Extension<BasicClient>,
4239
) -> Result<impl IntoResponse, ChaosError> {
43-
let token = oauth_client
40+
let token = state.oauth2_client
4441
.exchange_code(AuthorizationCode::new(query.code))
4542
.request_async(async_http_client)
4643
.await?;
@@ -52,16 +49,15 @@ pub async fn google_callback(
5249
.send()
5350
.await?;
5451

55-
let profile = profile.json::<GoogleUserProfile>().await.unwrap();
52+
let profile = profile.json::<GoogleUserProfile>().await?;
5653

5754
let user_id = create_or_get_user_id(
5855
profile.email.clone(),
5956
profile.name,
6057
state.db,
6158
state.snowflake_generator,
6259
)
63-
.await
64-
.unwrap();
60+
.await?;
6561

6662
// TODO: Return JWT as set-cookie header.
6763
let token = encode_auth_token(

backend/server/src/models/app.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,14 @@ use snowflake::SnowflakeIdGenerator;
2121
use sqlx::postgres::PgPoolOptions;
2222
use sqlx::{Pool, Postgres};
2323
use std::env;
24+
use oauth2::basic::BasicClient;
25+
use crate::service::oauth2::build_oauth_client;
2426

2527
#[derive(Clone)]
2628
pub struct AppState {
2729
pub db: Pool<Postgres>,
2830
pub ctx: ReqwestClient,
31+
pub oauth2_client: BasicClient,
2932
pub decoding_key: DecodingKey,
3033
pub encoding_key: EncodingKey,
3134
pub jwt_header: Header,
@@ -61,6 +64,15 @@ pub async fn app() -> Result<Router, ChaosError> {
6164
// Initialise reqwest client
6265
let ctx = reqwest::Client::new();
6366

67+
// Initialise oauth2 client
68+
let client_id = env::var("GOOGLE_CLIENT_ID")
69+
.expect("Error getting GOOGLE_CLIENT_ID")
70+
.to_string();
71+
let client_secret = env::var("GOOGLE_CLIENT_SECRET")
72+
.expect("Error getting GOOGLE_CLIENT_SECRET")
73+
.to_string();
74+
let oauth2_client = build_oauth_client(client_id, client_secret);
75+
6476
// Initialise Snowflake Generator
6577
let snowflake_generator = SnowflakeIdGenerator::new(1, 1);
6678

@@ -74,6 +86,7 @@ pub async fn app() -> Result<Router, ChaosError> {
7486
let state = AppState {
7587
db: pool,
7688
ctx,
89+
oauth2_client,
7790
encoding_key,
7891
decoding_key,
7992
jwt_header,

backend/server/src/service/oauth2.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,7 @@ use std::env;
3737
/// );
3838
/// ```
3939
pub fn build_oauth_client(client_id: String, client_secret: String) -> BasicClient {
40-
let hostname = env::var("CHAOS_HOSTNAME").expect("Could not read CHAOS hostname");
41-
42-
let redirect_url = format!("{}/api/auth/callback/google", hostname);
40+
let redirect_url = env::var("GOOGLE_REDIRECT_URI").expect("Could not read GOOGLE_REDIRECT_URI");
4341

4442
let auth_url = AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string())
4543
.expect("Invalid authorization endpoint URL");

frontend/.eslintrc.json

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@
1414
"plugin:import/typescript",
1515
"plugin:react/jsx-runtime"
1616
],
17+
"ignorePatterns": [
18+
"babel-plugin-macros.config.js",
19+
"tailwind.config.js",
20+
"prettier.config.js",
21+
"postcss.config.js",
22+
"vite.config.ts"
23+
],
1724
"parser": "@typescript-eslint/parser",
1825
"parserOptions": {
1926
"ecmaVersion": 12,
@@ -32,42 +39,43 @@
3239
"@typescript-eslint/no-shadow": "off",
3340
"no-unused-vars": "off",
3441
"@typescript-eslint/no-unused-vars": [
35-
1,
42+
"warn",
3643
{
3744
"varsIgnorePattern": "^_",
3845
"argsIgnorePattern": "^_"
3946
}
4047
],
4148
"@typescript-eslint/naming-convention": [
42-
"error",
43-
{
44-
"selector": "default",
45-
"format": ["camelCase"],
46-
"leadingUnderscore": "allow",
47-
"trailingUnderscore": "allow"
48-
},
49+
"error",
50+
{
51+
"selector": "default",
52+
"format": ["camelCase"],
53+
"leadingUnderscore": "allow",
54+
"trailingUnderscore": "allow"
55+
},
4956

50-
{
51-
"selector": "variable",
52-
"format": ["camelCase", "UPPER_CASE", "PascalCase"],
53-
"leadingUnderscore": "allow",
54-
"trailingUnderscore": "allow"
55-
},
57+
{
58+
"selector": "variable",
59+
"format": ["camelCase", "UPPER_CASE", "PascalCase"],
60+
"leadingUnderscore": "allow",
61+
"trailingUnderscore": "allow"
62+
},
5663

57-
{
58-
"selector": "function",
59-
"format": ["camelCase", "PascalCase"]
60-
},
64+
{
65+
"selector": "function",
66+
"format": ["camelCase", "PascalCase"]
67+
},
6168

62-
{
63-
"selector": "typeLike",
64-
"format": ["PascalCase"]
65-
},
69+
{
70+
"selector": "typeLike",
71+
"format": ["PascalCase"],
72+
"leadingUnderscore": "allow"
73+
},
6674

67-
{
68-
"selector": "objectLiteralProperty",
69-
"format": null
70-
}
75+
{
76+
"selector": "objectLiteralProperty",
77+
"format": null
78+
}
7179
],
7280
"import/prefer-default-export": "off",
7381
"import/no-extraneous-dependencies": ["error", { "devDependencies": true }],
@@ -103,7 +111,7 @@
103111
"custom": "ignore"
104112
}
105113
],
106-
"react/no-unknown-property": [2, { "ignore": ["tw", "css"] }],
114+
"react/no-unknown-property": ["error", { "ignore": ["tw", "css"] }],
107115
"react/require-default-props": "off",
108116
"@typescript-eslint/consistent-type-imports": "error",
109117
"no-void": "off",

frontend/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!DOCTYPE html>
1+
<!doctype html>
22
<html lang="en">
33
<head>
44
<meta charset="utf-8" />

frontend/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,12 @@
7979
"eslint-import-resolver-typescript": "3.5.2",
8080
"eslint-plugin-import": "2.27.5",
8181
"eslint-plugin-jsx-a11y": "6.7.1",
82-
"eslint-plugin-prettier": "4.2.1",
82+
"eslint-plugin-prettier": "5.0.0",
8383
"eslint-plugin-react": "7.32.2",
8484
"eslint-plugin-react-hooks": "4.6.0",
8585
"husky": "8.0.2",
86-
"prettier": "2.8.0",
86+
"prettier": "3.3.2",
87+
"prettier-plugin-tailwindcss": "0.6.4",
8788
"tailwindcss": "3.3.2",
8889
"tailwindcss-gradient": "1.0.1",
8990
"twin.macro": "3.3.1",

frontend/prettier.config.js

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
/**
2+
* @type {import("prettier").Config}
3+
*/
14
module.exports = {
2-
plugins: [],
5+
trailingComma: "es5",
6+
tabWidth: 2,
7+
semi: true,
8+
singleQuote: false,
9+
printWidth: 80,
10+
useTabs: false,
11+
quoteProps: "as-needed",
12+
jsxSingleQuote: false,
13+
bracketSpacing: true,
14+
bracketSameLine: false,
15+
arrowParens: "always",
16+
17+
plugins: ["prettier-plugin-tailwindcss"],
18+
tailwindAttributes: ["className", "class", "tw"],
19+
tailwindFunctions: ["tw"],
320
};

frontend/public/site.webmanifest

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,19 @@
1-
{"name":"","short_name":"","icons":[{"src":"/android-chrome-192x192.png","sizes":"192x192","type":"image/png"},{"src":"/android-chrome-512x512.png","sizes":"512x512","type":"image/png"}],"theme_color":"#ffffff","background_color":"#ffffff","display":"standalone"}
1+
{
2+
"name": "",
3+
"short_name": "",
4+
"icons": [
5+
{
6+
"src": "/android-chrome-192x192.png",
7+
"sizes": "192x192",
8+
"type": "image/png"
9+
},
10+
{
11+
"src": "/android-chrome-512x512.png",
12+
"sizes": "512x512",
13+
"type": "image/png"
14+
}
15+
],
16+
"theme_color": "#ffffff",
17+
"background_color": "#ffffff",
18+
"display": "standalone"
19+
}

frontend/src/api/api.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@ export class FetchError extends Error {
55

66
public statusText: string;
77

8-
constructor(public resp: Response, public data?: unknown) {
8+
constructor(
9+
public resp: Response,
10+
public data?: unknown
11+
) {
912
super(resp.statusText);
1013

1114
this.name = "FetchError";

0 commit comments

Comments
 (0)