This repository has been archived by the owner on Apr 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* add base auth * lint * upd * return null back * fix: случайно удалил * fixes * fixes * lint * improve auth * add more tests & config * feat: add middleware * feat: add middleware * chore: fix type error * chore: fix type error * feat: upgrade logic * feat: update tests * chore: lint * chore: lint * chore: add @description
- Loading branch information
Showing
35 changed files
with
420 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
POSTGRES_USER=postgres | ||
POSTGRES_PASSWORD=12345678 | ||
POSTGRES_DB=diary-db | ||
JWT_SECRET=itssecret | ||
|
||
DATABASE_URL=postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@localhost:5432/${POSTGRES_DB}?schema=public |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { afterAll, beforeEach, describe, expect, it } from 'bun:test' | ||
import { PrismaClient } from '@prisma/client' | ||
import { authenticateUser, isUserExist } from '@services' | ||
import { getTestUser } from '@utils' | ||
|
||
const testDb = new PrismaClient() | ||
|
||
describe('authenticationService', () => { | ||
afterAll(async () => { | ||
await testDb.$disconnect() | ||
}) | ||
|
||
beforeEach(async () => { | ||
await testDb.user.deleteMany() | ||
}) | ||
|
||
it('should fail authentication for a non-existent user', async () => { | ||
const user = await isUserExist(1, 'nonexistent@example.com') | ||
|
||
expect(user).toBe(null) | ||
}) | ||
|
||
it('should fail authentication for an invalid password', async () => { | ||
const id = 1 | ||
const testUser = await getTestUser(id) | ||
await testDb.user.create({ | ||
data: testUser | ||
}) | ||
|
||
const result = await authenticateUser( | ||
testUser, | ||
testUser.email, | ||
'wrongpassword' | ||
) | ||
expect(result).toBe(false) | ||
}) | ||
|
||
it('should authenticate a user with valid credentials', async () => { | ||
const id = 1 | ||
const testUser = await getTestUser(id) | ||
await testDb.user.create({ | ||
data: testUser | ||
}) | ||
|
||
/** | ||
* В getTestUser пароль хешируется, но по задумке authenticateUser мы передаем туда пароль в чистом виде. | ||
*/ | ||
const result = await authenticateUser(testUser, testUser.email, 'password') | ||
expect(result).toBe(true) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// @ts-nocheck В тестах нам не важны лишние параметры для handleErrors | ||
import { describe, expect, it } from 'bun:test' | ||
import { handleErrors } from '@utils' | ||
|
||
describe('handleErrors', () => { | ||
it('should handle VALIDATION error', () => { | ||
const result = handleErrors({ | ||
code: 'VALIDATION', | ||
error: new Error('Validation failed') | ||
}) | ||
|
||
expect(result.message).toBe('Validation error') | ||
expect(result.error).toBeInstanceOf(Error) | ||
}) | ||
|
||
it('should handle INTERNAL_SERVER_ERROR', () => { | ||
const result = handleErrors({ | ||
code: 'INTERNAL_SERVER_ERROR', | ||
error: new Error('Server error') | ||
}) | ||
|
||
expect(result.message).toBe('Internal Server Error') | ||
expect(result.error).toBeInstanceOf(Error) | ||
}) | ||
|
||
it('should handle NOT_FOUND error', () => { | ||
const result = handleErrors({ | ||
code: 'NOT_FOUND', | ||
error: new Error('Resource not found') | ||
}) | ||
|
||
expect(result.message).toBe('Not found') | ||
expect(result.error).toBeInstanceOf(Error) | ||
}) | ||
|
||
it('should handle unknown error', () => { | ||
const result = handleErrors({ | ||
code: 'UNKNOWN_ERROR', | ||
error: new Error('Unknown error occurred') | ||
}) | ||
|
||
expect(result.message).toBe('Unknown error') | ||
expect(result.error).toBeInstanceOf(Error) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { describe, expect, it } from 'bun:test' | ||
import { hashPassword, pbkdf2Hash } from '@utils' | ||
|
||
describe('hashPassword', () => { | ||
it('should hash password with random salt', async () => { | ||
const result = await hashPassword('password') | ||
const expectedHash = await pbkdf2Hash('password', result.salt) | ||
|
||
expect(result.hash).toMatch(expectedHash) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"formatter": { | ||
"ignore": ["./dist"] | ||
}, | ||
"linter": { | ||
"ignore": ["./dist"] | ||
}, | ||
"extends": ["../../biome.json"] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
apps/api/prisma/migrations/20231209175553_init/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
/* | ||
Warnings: | ||
- Added the required column `password` to the `User` table without a default value. This is not possible if the table is not empty. | ||
- Added the required column `salt` to the `User` table without a default value. This is not possible if the table is not empty. | ||
*/ | ||
-- AlterTable | ||
ALTER TABLE "User" ADD COLUMN "password" TEXT NOT NULL, | ||
ADD COLUMN "salt" TEXT NOT NULL; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export const POSTGRES_PASSWORD = Bun.env.POSTGRES_PASSWORD |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import { authenticateUser, isUserExist } from '@services' | ||
import { ApiResponse, ContextWith } from '@types' | ||
|
||
interface Body { | ||
password: string | ||
login: string | ||
id: number | ||
} | ||
|
||
export const postAuth = async ({ | ||
body, | ||
jwt, | ||
set | ||
}: ContextWith<never, Body>): Promise<ApiResponse<string>> => { | ||
const { login, password, id } = body | ||
|
||
const user = await isUserExist(id, login) | ||
|
||
if (!user) { | ||
set.status = 'Bad Request' | ||
|
||
return { | ||
success: false, | ||
data: 'Bad Request' | ||
} | ||
} | ||
|
||
const isAuth = await authenticateUser(user, login, password) | ||
|
||
if (!isAuth || !jwt) { | ||
set.status = 'Bad Request' | ||
|
||
return { | ||
success: false | ||
} | ||
} | ||
|
||
/** | ||
* @description jwt.sign() будет возвращать одну и ту же куку в течении даты ее жизни | ||
* | ||
* Если хочется генерировать новую на каждую авторизацию (например), то можно использовать такой код | ||
* | ||
* setCookie('auth', await jwt.sign(body), { | ||
* httpOnly: true, | ||
* maxAge: 7 * 86400, | ||
* }) | ||
* | ||
* @see https://elysiajs.com/plugins/jwt.html#jwt-plugin | ||
*/ | ||
await jwt.sign(body) | ||
|
||
return { | ||
success: true | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
export * from './userHandler' | ||
export * from './user/userHandler' | ||
export * from './auth/authHandler' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
import { ContextWith } from '@types' | ||
|
||
/** | ||
* @description Посредник для проверки авторизирован ли юзер | ||
* | ||
* Есть два метода: | ||
* 1. Сделать кастомный плагин на основе интанса от Элизии. | ||
* @see https://elysiajs.com/concept/plugin.html#plugin | ||
* | ||
* 2. Сделать функцию и добавить ее в 'onBeforeHandle' для нужной группы роутов | ||
* | ||
* P.S. Пока используем второй способ. | ||
*/ | ||
|
||
export const auth = async ({ set, jwt, cookie }: ContextWith) => { | ||
if (!jwt || !cookie.auth) { | ||
set.status = 'Internal Server Error' | ||
return | ||
} | ||
|
||
const isCookieValid = await jwt.verify(cookie.auth) | ||
|
||
if (!isCookieValid) { | ||
set.status = 'Unauthorized' | ||
return | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './auth' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import cookie from '@elysiajs/cookie' | ||
import jwt, { JWTOption } from '@elysiajs/jwt' | ||
import { postAuth } from '@handlers' | ||
import Elysia, { t } from 'elysia' | ||
import { authBody } from './authSchema' | ||
|
||
const authConfig: JWTOption<string> = { | ||
name: 'jwt', | ||
secret: Bun.env.JWT_SECRET ?? 'secret', | ||
exp: '7d' | ||
} | ||
|
||
const app = new Elysia() | ||
.use(cookie()) | ||
.use(jwt(authConfig)) | ||
.post('/auth', postAuth, { | ||
body: t.Object(authBody) | ||
}) | ||
|
||
export default app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import { t } from 'elysia' | ||
|
||
export const authBody = { | ||
id: t.Number(), | ||
password: t.String(), | ||
login: t.String() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.