mirror of
https://github.com/BradNut/AdelieStack
synced 2025-09-08 17:40:20 +00:00
Fixing api client path, signup api on server and kit server side.
This commit is contained in:
parent
64f0e10715
commit
ae21011b3f
7 changed files with 42 additions and 25 deletions
|
|
@ -11,11 +11,13 @@ import { browserSessions } from './common/middleware/browser-session.middleware'
|
||||||
import { IamController } from './iam/iam.controller';
|
import { IamController } from './iam/iam.controller';
|
||||||
import configureOpenAPI from './configure-open-api';
|
import configureOpenAPI from './configure-open-api';
|
||||||
import { pinoLogger } from './common/middleware/pino-logger.middleware';
|
import { pinoLogger } from './common/middleware/pino-logger.middleware';
|
||||||
|
import { SignupController } from './signup/signup.controller';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class ApplicationController extends RootController {
|
export class ApplicationController extends RootController {
|
||||||
constructor(
|
constructor(
|
||||||
private iamController = inject(IamController),
|
private iamController = inject(IamController),
|
||||||
|
private signupController = inject(SignupController),
|
||||||
private usersController = inject(UsersController)
|
private usersController = inject(UsersController)
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
@ -48,7 +50,8 @@ export class ApplicationController extends RootController {
|
||||||
.use(pinoLogger())
|
.use(pinoLogger())
|
||||||
.route('/', this.routes())
|
.route('/', this.routes())
|
||||||
.route('/iam', this.iamController.routes())
|
.route('/iam', this.iamController.routes())
|
||||||
.route('/users', this.usersController.routes());
|
.route('/users', this.usersController.routes())
|
||||||
|
.route('/signup', this.signupController.routes());
|
||||||
|
|
||||||
configureOpenAPI(app);
|
configureOpenAPI(app);
|
||||||
return app;
|
return app;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { Hono } from 'hono';
|
import { Hono } from 'hono';
|
||||||
import type { SessionDto } from '../../iam/sessions/dtos/session.dto';
|
import type { SessionDto } from '../../iam/sessions/dtos/session.dto';
|
||||||
|
import type { PinoLogger } from 'hono-pino';
|
||||||
|
|
||||||
export type HonoEnv = {
|
export type HonoEnv = {
|
||||||
Variables: {
|
Variables: {
|
||||||
|
logger: PinoLogger;
|
||||||
session: SessionDto | null;
|
session: SessionDto | null;
|
||||||
browserSessionId: string;
|
browserSessionId: string;
|
||||||
requestId: string;
|
requestId: string;
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,16 @@
|
||||||
import { limiter } from '$lib/server/api/common/middleware/rate-limit.middleware';
|
import { rateLimit } from '$lib/server/api/common/middleware/rate-limit.middleware';
|
||||||
import { cookieExpiresAt, createSessionTokenCookie, setSessionCookie } from '$lib/server/api/common/utils/cookies';
|
|
||||||
import { signupUsernameEmailDto } from '$lib/server/api/dtos/signup-username-email.dto';
|
|
||||||
import { SessionsService } from '$lib/server/api/iam/sessions/sessions.service';
|
import { SessionsService } from '$lib/server/api/iam/sessions/sessions.service';
|
||||||
import { LoginRequestsService } from '$lib/server/api/login/loginrequest.service';
|
|
||||||
import { UsersService } from '$lib/server/api/users/users.service';
|
import { UsersService } from '$lib/server/api/users/users.service';
|
||||||
import { zValidator } from '@hono/zod-validator';
|
import { zValidator } from '@hono/zod-validator';
|
||||||
import { inject, injectable } from '@needle-di/core';
|
import { inject, injectable } from '@needle-di/core';
|
||||||
import { authState } from '../common/middleware/auth.middleware';
|
import { authState } from '../common/middleware/auth.middleware';
|
||||||
import { Controller } from '../common/factories/controllers.factory';
|
import { Controller } from '../common/factories/controllers.factory';
|
||||||
|
import { signupUsernameEmailDto } from './dtos/signup-username-email.dto';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class SignupController extends Controller {
|
export class SignupController extends Controller {
|
||||||
constructor(
|
constructor(
|
||||||
private usersService = inject(UsersService),
|
private usersService = inject(UsersService),
|
||||||
private loginRequestService = inject(LoginRequestsService),
|
|
||||||
private sessionsService = inject(SessionsService),
|
private sessionsService = inject(SessionsService),
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
@ -25,25 +22,19 @@ export class SignupController extends Controller {
|
||||||
'/',
|
'/',
|
||||||
authState('none'),
|
authState('none'),
|
||||||
zValidator('json', signupUsernameEmailDto),
|
zValidator('json', signupUsernameEmailDto),
|
||||||
limiter({ limit: 10, minutes: 60 }),
|
rateLimit({ limit: 10, minutes: 60 }),
|
||||||
async (c) => {
|
async (c) => {
|
||||||
const { email, username, password, confirm_password } = await c.req.valid('json');
|
const { email, username, password } = await c.req.valid('json');
|
||||||
const existingUser = await this.usersService.findOneByUsername(username);
|
c.var.logger.info(`Signup with email: ${email} username: ${username}`);
|
||||||
|
const user = await this.usersService.createWithPassword(username, password, email);
|
||||||
if (existingUser) {
|
|
||||||
return c.body('User already exists', 400);
|
|
||||||
}
|
|
||||||
|
|
||||||
const user = await this.usersService.createWithPassword({ email, username, password, confirm_password });
|
|
||||||
|
|
||||||
|
c.var.logger.info(`Created user: ${user?.id}`);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return c.body('Failed to create user', 500);
|
return c.body('Failed to create user', 500);
|
||||||
}
|
}
|
||||||
|
|
||||||
const session = await this.loginRequestService.createUserSession(user.id, c.req, false, false);
|
const session = await this.sessionsService.createSession(user.id);
|
||||||
const sessionCookie = createSessionTokenCookie(session.id, cookieExpiresAt);
|
await this.sessionsService.setSessionCookie(session);
|
||||||
console.log('set cookie', sessionCookie);
|
|
||||||
setSessionCookie(c, sessionCookie);
|
|
||||||
return c.json({ message: 'ok' });
|
return c.json({ message: 'ok' });
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@ export class UsersRepository extends DrizzleRepository {
|
||||||
return db.select().from(users_table).where(eq(users_table.email, email)).then(takeFirst);
|
return db.select().from(users_table).where(eq(users_table.email, email)).then(takeFirst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findOneByUsername(username: string, db = this.drizzle.db) {
|
||||||
|
return db.select().from(users_table).where(eq(users_table.username, username)).then(takeFirst);
|
||||||
|
}
|
||||||
|
|
||||||
async findOneByIdOrThrow(id: string, db = this.drizzle.db) {
|
async findOneByIdOrThrow(id: string, db = this.drizzle.db) {
|
||||||
const user = await this.findOneById(id, db);
|
const user = await this.findOneById(id, db);
|
||||||
if (!user) throw NotFound('User not found');
|
if (!user) throw NotFound('User not found');
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { CredentialsType } from './tables/credentials.table';
|
||||||
import { UsersRepository } from './users.repository';
|
import { UsersRepository } from './users.repository';
|
||||||
import { UserRolesService } from './user_roles.service';
|
import { UserRolesService } from './user_roles.service';
|
||||||
import { RoleName } from '../roles/tables/roles.table';
|
import { RoleName } from '../roles/tables/roles.table';
|
||||||
|
import { BadRequest } from '../common/utils/exceptions';
|
||||||
|
|
||||||
@injectable()
|
@injectable()
|
||||||
export class UsersService {
|
export class UsersService {
|
||||||
|
|
@ -31,8 +32,18 @@ export class UsersService {
|
||||||
return this.usersRepository.create({ avatar: null, email, username: email });
|
return this.usersRepository.create({ avatar: null, email, username: email });
|
||||||
}
|
}
|
||||||
|
|
||||||
async createWithPassword(username: string, password: string, email?: string) {
|
async createWithPassword(username: string, password: string, email?: string | undefined) {
|
||||||
const hashedPassword = await this.tokenService.createHashedToken(password);
|
const existingUsername = await this.usersRepository.findOneByUsername(username);
|
||||||
|
if (existingUsername) {
|
||||||
|
throw BadRequest('Could not create user');
|
||||||
|
}
|
||||||
|
if (email) {
|
||||||
|
const existingEmail = await this.usersRepository.findOneByEmail(email);
|
||||||
|
if (existingUsername || existingEmail) {
|
||||||
|
throw BadRequest('Could not create user');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return await this.drizzleService.db.transaction(async (trx) => {
|
return await this.drizzleService.db.transaction(async (trx) => {
|
||||||
const createdUser = await this.usersRepository.create(
|
const createdUser = await this.usersRepository.create(
|
||||||
{ username, email: email || '', avatar: null },
|
{ username, email: email || '', avatar: null },
|
||||||
|
|
@ -43,6 +54,8 @@ export class UsersService {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hashedPassword = await this.tokenService.createHashedToken(password);
|
||||||
|
|
||||||
const credentials = await this.credentialsRepository.create(
|
const credentials = await this.credentialsRepository.create(
|
||||||
{
|
{
|
||||||
user_id: createdUser.id,
|
user_id: createdUser.id,
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import type { ApiRoutes } from "../server/api";
|
import type { ApiRoutes } from "../server/api";
|
||||||
import { hc, type ClientRequestOptions, type ClientResponse } from "hono/client";
|
import { hc, type ClientRequestOptions, type ClientResponse } from "hono/client";
|
||||||
|
|
||||||
export const honoClient = (options?: ClientRequestOptions) => hc<ApiRoutes>('/', options).api;
|
export const honoClient = (options?: ClientRequestOptions) => hc<ApiRoutes>('/', options);
|
||||||
|
|
||||||
export async function parseClientResponse<T>(response: ClientResponse<T>) {
|
export async function parseClientResponse<T>(response: ClientResponse<T>) {
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
|
|
|
||||||
|
|
@ -44,10 +44,14 @@ export const actions: Actions = {
|
||||||
|
|
||||||
const form = await superValidate(event, zod(signupUsernameEmailDto));
|
const form = await superValidate(event, zod(signupUsernameEmailDto));
|
||||||
|
|
||||||
|
console.log('form data', form.data);
|
||||||
|
|
||||||
const { error } = await locals.api.signup.$post({ json: form.data }).then(locals.parseApiResponse);
|
const { error } = await locals.api.signup.$post({ json: form.data }).then(locals.parseApiResponse);
|
||||||
if (error) {
|
if (error) {
|
||||||
|
console.log('error', error);
|
||||||
form.data.password = '';
|
form.data.password = '';
|
||||||
return setError(form, 'username', 'Unable to log in.');
|
form.data.confirm_password = '';
|
||||||
|
return setError(form, 'username', 'Unable to sign up.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!form.valid) {
|
if (!form.valid) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue