mirror of
https://github.com/michivonah/themepark-assistant.git
synced 2025-12-22 22:16:29 +01:00
add user creation in db & validation
This commit is contained in:
parent
807e2dc408
commit
e097d154de
5 changed files with 102 additions and 7 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { integer, text, sqliteTable, sqliteView } from "drizzle-orm/sqlite-core";
|
||||
import { check, integer, text, sqliteTable, sqliteView } from "drizzle-orm/sqlite-core";
|
||||
import { eq, sql } from "drizzle-orm";
|
||||
|
||||
// Tables
|
||||
|
|
@ -48,9 +48,15 @@ export const themepark = sqliteTable('themepark', {
|
|||
|
||||
export const user = sqliteTable('user', {
|
||||
id: integer().primaryKey({ autoIncrement: true }),
|
||||
username: text().notNull(),
|
||||
isActive: integer({ mode: 'boolean' }).default(false)
|
||||
})
|
||||
mail: text().notNull().unique(),
|
||||
isActive: integer({ mode: 'boolean' }).notNull().default(false),
|
||||
createdAt: integer().notNull(),
|
||||
lastActive: integer().notNull()
|
||||
},
|
||||
(table) => [
|
||||
check("mail_validation", sql`${table.mail} LIKE '%@%'`)
|
||||
]
|
||||
)
|
||||
|
||||
// Views
|
||||
export const subscribedThemeparks = sqliteView('subscribed_themeparks').as((qb) =>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { Hono } from 'hono'
|
||||
import { authHandler, initAuthConfig, verifyAuth } from '@hono/auth-js'
|
||||
import { getUser } from './lib/user-auth'
|
||||
import GitHub from '@auth/core/providers/github'
|
||||
import notification from './routes/notification'
|
||||
import logbook from './routes/logbook'
|
||||
|
|
@ -24,9 +25,9 @@ app.use('/auth/*', authHandler())
|
|||
app.use('/*', verifyAuth())
|
||||
|
||||
// example endpoint
|
||||
app.get('/protected', (c) => {
|
||||
const auth = c.get('authUser')
|
||||
return c.json(auth)
|
||||
app.get('/protected', async (c) => {
|
||||
const user = await getUser(c);
|
||||
return c.json(user);
|
||||
})
|
||||
|
||||
// define routes & export app
|
||||
|
|
|
|||
70
api/src/lib/user-auth.ts
Normal file
70
api/src/lib/user-auth.ts
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
import { getDbContext } from "../db/client";
|
||||
import { Context } from "hono";
|
||||
import { UserSelect } from "../types/user";
|
||||
import { user } from "../db/schema";
|
||||
import { like } from "drizzle-orm";
|
||||
import { DrizzleD1Database } from "drizzle-orm/d1";
|
||||
import { MissingMailError, UserInactiveError } from "../types/error";
|
||||
|
||||
/**
|
||||
* Returns the details of a user from the given context
|
||||
* @param c Request context
|
||||
* @returns Object of the user details as type UserSelect
|
||||
*/
|
||||
export async function getUser(c: Context): Promise<UserSelect>{
|
||||
const db = getDbContext(c);
|
||||
const auth = c.get('authUser');
|
||||
if(!auth.session.user || !auth.session.user.email) throw new MissingMailError();
|
||||
|
||||
const currentUser: UserSelect = c.get('currentUser');
|
||||
if(currentUser) return currentUser;
|
||||
|
||||
const mail = auth.session.user.email;
|
||||
|
||||
let userData: UserSelect[];
|
||||
try{
|
||||
userData = await db.selectDistinct().from(user).limit(1).where(like(user.mail, mail));
|
||||
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Database error: ${e}`);
|
||||
}
|
||||
|
||||
const dbResult = userData[0] ?? await createUser(db, mail);
|
||||
if(!dbResult.isActive) throw new UserInactiveError();
|
||||
|
||||
c.set('currentUser', dbResult);
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new user in the DB from the given context
|
||||
* @param c Request context
|
||||
* @returns The created user as Object of type UserSelect
|
||||
*/
|
||||
async function createUser(db: DrizzleD1Database, userMail: string): Promise<UserSelect>{
|
||||
let userData: UserSelect[];
|
||||
|
||||
try{
|
||||
userData = await db.insert(user).values(
|
||||
{
|
||||
mail: userMail,
|
||||
isActive: true,
|
||||
createdAt: now(),
|
||||
lastActive: now()
|
||||
}
|
||||
).returning();
|
||||
|
||||
}
|
||||
catch(e){
|
||||
throw new Error(`Database error: ${e}`);
|
||||
}
|
||||
|
||||
return userData[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Getting the current time
|
||||
* @returns Current unix timestamp
|
||||
*/
|
||||
const now = () => Math.floor(Date.now() / 1000);
|
||||
13
api/src/types/error.ts
Normal file
13
api/src/types/error.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
import { HTTPException } from "hono/http-exception";
|
||||
|
||||
export class UserInactiveError extends HTTPException{
|
||||
constructor(){
|
||||
super(403, { message: 'User is currently disabled.' })
|
||||
}
|
||||
}
|
||||
|
||||
export class MissingMailError extends HTTPException{
|
||||
constructor(){
|
||||
super(400, { message: 'Mail address is missing in authorizaton header.' })
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue