From 9c6fdfa6c16fcf0ce6be7bab2ea2b1fa2238bdd0 Mon Sep 17 00:00:00 2001 From: Radoslav Irha Date: Mon, 16 Oct 2023 20:16:34 +0200 Subject: [PATCH 1/2] chore: auth basics - not working yet --- .../src/v1/controllers/auth/SignUp.ts | 14 ++++++++ .../src/v1/controllers/index.ts | 1 + .../src/v1/model/user/SignUp.ts | 18 +++++++++++ api/authentication/src/v1/mongo/User.spec.ts | 22 +++++++++++++ api/authentication/src/v1/mongo/User.ts | 32 +++++++++++++++++++ .../src/v1/types/enum/AuthProvider.ts | 3 ++ api/authentication/src/v1/types/enum/index.ts | 5 +++ api/authentication/src/v1/types/index.ts | 5 +++ 8 files changed, 100 insertions(+) create mode 100644 api/authentication/src/v1/controllers/auth/SignUp.ts create mode 100644 api/authentication/src/v1/model/user/SignUp.ts create mode 100644 api/authentication/src/v1/mongo/User.spec.ts create mode 100644 api/authentication/src/v1/mongo/User.ts create mode 100644 api/authentication/src/v1/types/enum/AuthProvider.ts create mode 100644 api/authentication/src/v1/types/enum/index.ts create mode 100644 api/authentication/src/v1/types/index.ts diff --git a/api/authentication/src/v1/controllers/auth/SignUp.ts b/api/authentication/src/v1/controllers/auth/SignUp.ts new file mode 100644 index 0000000..f92f0b2 --- /dev/null +++ b/api/authentication/src/v1/controllers/auth/SignUp.ts @@ -0,0 +1,14 @@ +import { Controller } from '@tsed/di'; +import { BodyParams } from '@tsed/platform-params'; +import { Description, Post, Returns } from '@tsed/schema'; +import { UserSignUp } from '../../model/user/SignUp'; + +@Controller('/auth/sign-up') +export class SwaggerController { + @Post('/') + @Description('Sign up a new user.') + @Returns(200) + signUp(@BodyParams() payload: UserSignUp): UserSignUp { + return payload; + } +} diff --git a/api/authentication/src/v1/controllers/index.ts b/api/authentication/src/v1/controllers/index.ts index 3333dae..2106c67 100644 --- a/api/authentication/src/v1/controllers/index.ts +++ b/api/authentication/src/v1/controllers/index.ts @@ -3,3 +3,4 @@ */ export * from './HelloWorldController'; +export * from './auth/SignUp'; diff --git a/api/authentication/src/v1/model/user/SignUp.ts b/api/authentication/src/v1/model/user/SignUp.ts new file mode 100644 index 0000000..79d6e9d --- /dev/null +++ b/api/authentication/src/v1/model/user/SignUp.ts @@ -0,0 +1,18 @@ +import { Description, Email, Example, MinLength, Property, Required, Title } from '@tsed/schema'; + +export class UserSignUp { + @Title('email') + @Description('Email used for registration.') + @Example('user@email.com') + @Email() + @Property() + @Required() + email!: string; + + @Title('password') + @Description("User's password.") + @Example('8^^3286UhpB$9m') + @MinLength(10) + @Required() + password!: string; +} diff --git a/api/authentication/src/v1/mongo/User.spec.ts b/api/authentication/src/v1/mongo/User.spec.ts new file mode 100644 index 0000000..d49c9e2 --- /dev/null +++ b/api/authentication/src/v1/mongo/User.spec.ts @@ -0,0 +1,22 @@ +import { PlatformTest } from '@tsed/common'; +import { MongooseModel } from '@tsed/mongoose'; +import { TestMongooseContext } from '@tsed/testing-mongoose'; +import { AuthProviderEnum } from '../types'; +import { User } from './User'; + +describe('User model', () => { + beforeEach(TestMongooseContext.create); + afterEach(TestMongooseContext.reset); + + it('Should save', async () => { + const model = PlatformTest.get>(User); + + const user = new model({ email: 'email@test.com', password: 'password' }); + + await user.save(); + + expect(user.email).toEqual('email@test.com'); + expect(user.password).not.toEqual('password'); + expect(user.auth_provider).toEqual(AuthProviderEnum.LOCAL); + }); +}); diff --git a/api/authentication/src/v1/mongo/User.ts b/api/authentication/src/v1/mongo/User.ts new file mode 100644 index 0000000..88e07fe --- /dev/null +++ b/api/authentication/src/v1/mongo/User.ts @@ -0,0 +1,32 @@ +import { argon2CreateHash } from '@hikers-book/cryptography'; +import { Model, MongooseDocument, MongooseNextCB, ObjectID, PreHook, Unique } from '@tsed/mongoose'; +import { Default, Enum, Property, Required } from '@tsed/schema'; +import { AuthProviderEnum } from '../types/enum'; + +@Model({ + schemaOptions: { timestamps: true } +}) +export class User { + @ObjectID('id') + _id!: string; + + @Unique() + @Required() + email!: string; + + @Required() + password!: string; + + @Property() + @Enum(AuthProviderEnum) + @Default(AuthProviderEnum.LOCAL) + auth_provider?: string; + + @PreHook('save') + static async preSave(user: MongooseDocument, next: MongooseNextCB) { + if (user.isModified('password')) { + user.password = await argon2CreateHash(user.password); + } + next(); + } +} diff --git a/api/authentication/src/v1/types/enum/AuthProvider.ts b/api/authentication/src/v1/types/enum/AuthProvider.ts new file mode 100644 index 0000000..35e78f5 --- /dev/null +++ b/api/authentication/src/v1/types/enum/AuthProvider.ts @@ -0,0 +1,3 @@ +export enum AuthProviderEnum { + LOCAL = 'local' +} diff --git a/api/authentication/src/v1/types/enum/index.ts b/api/authentication/src/v1/types/enum/index.ts new file mode 100644 index 0000000..5a24ddb --- /dev/null +++ b/api/authentication/src/v1/types/enum/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './AuthProvider'; diff --git a/api/authentication/src/v1/types/index.ts b/api/authentication/src/v1/types/index.ts new file mode 100644 index 0000000..8b556aa --- /dev/null +++ b/api/authentication/src/v1/types/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './enum/AuthProvider'; From 4505ff952276f8ff6e1cf53db5553668251fe969 Mon Sep 17 00:00:00 2001 From: Radoslav Irha Date: Mon, 16 Oct 2023 20:16:34 +0200 Subject: [PATCH 2/2] chore: auth basics - not working yet --- .../src/v1/controllers/auth/SignUp.ts | 14 ++++++++ .../src/v1/controllers/index.ts | 1 + .../src/v1/model/user/SignUp.ts | 18 +++++++++++ api/authentication/src/v1/mongo/User.spec.ts | 22 +++++++++++++ api/authentication/src/v1/mongo/User.ts | 32 +++++++++++++++++++ .../src/v1/types/enum/AuthProvider.ts | 3 ++ api/authentication/src/v1/types/enum/index.ts | 5 +++ api/authentication/src/v1/types/index.ts | 5 +++ 8 files changed, 100 insertions(+) create mode 100644 api/authentication/src/v1/controllers/auth/SignUp.ts create mode 100644 api/authentication/src/v1/model/user/SignUp.ts create mode 100644 api/authentication/src/v1/mongo/User.spec.ts create mode 100644 api/authentication/src/v1/mongo/User.ts create mode 100644 api/authentication/src/v1/types/enum/AuthProvider.ts create mode 100644 api/authentication/src/v1/types/enum/index.ts create mode 100644 api/authentication/src/v1/types/index.ts diff --git a/api/authentication/src/v1/controllers/auth/SignUp.ts b/api/authentication/src/v1/controllers/auth/SignUp.ts new file mode 100644 index 0000000..f92f0b2 --- /dev/null +++ b/api/authentication/src/v1/controllers/auth/SignUp.ts @@ -0,0 +1,14 @@ +import { Controller } from '@tsed/di'; +import { BodyParams } from '@tsed/platform-params'; +import { Description, Post, Returns } from '@tsed/schema'; +import { UserSignUp } from '../../model/user/SignUp'; + +@Controller('/auth/sign-up') +export class SwaggerController { + @Post('/') + @Description('Sign up a new user.') + @Returns(200) + signUp(@BodyParams() payload: UserSignUp): UserSignUp { + return payload; + } +} diff --git a/api/authentication/src/v1/controllers/index.ts b/api/authentication/src/v1/controllers/index.ts index 3333dae..2106c67 100644 --- a/api/authentication/src/v1/controllers/index.ts +++ b/api/authentication/src/v1/controllers/index.ts @@ -3,3 +3,4 @@ */ export * from './HelloWorldController'; +export * from './auth/SignUp'; diff --git a/api/authentication/src/v1/model/user/SignUp.ts b/api/authentication/src/v1/model/user/SignUp.ts new file mode 100644 index 0000000..79d6e9d --- /dev/null +++ b/api/authentication/src/v1/model/user/SignUp.ts @@ -0,0 +1,18 @@ +import { Description, Email, Example, MinLength, Property, Required, Title } from '@tsed/schema'; + +export class UserSignUp { + @Title('email') + @Description('Email used for registration.') + @Example('user@email.com') + @Email() + @Property() + @Required() + email!: string; + + @Title('password') + @Description("User's password.") + @Example('8^^3286UhpB$9m') + @MinLength(10) + @Required() + password!: string; +} diff --git a/api/authentication/src/v1/mongo/User.spec.ts b/api/authentication/src/v1/mongo/User.spec.ts new file mode 100644 index 0000000..d49c9e2 --- /dev/null +++ b/api/authentication/src/v1/mongo/User.spec.ts @@ -0,0 +1,22 @@ +import { PlatformTest } from '@tsed/common'; +import { MongooseModel } from '@tsed/mongoose'; +import { TestMongooseContext } from '@tsed/testing-mongoose'; +import { AuthProviderEnum } from '../types'; +import { User } from './User'; + +describe('User model', () => { + beforeEach(TestMongooseContext.create); + afterEach(TestMongooseContext.reset); + + it('Should save', async () => { + const model = PlatformTest.get>(User); + + const user = new model({ email: 'email@test.com', password: 'password' }); + + await user.save(); + + expect(user.email).toEqual('email@test.com'); + expect(user.password).not.toEqual('password'); + expect(user.auth_provider).toEqual(AuthProviderEnum.LOCAL); + }); +}); diff --git a/api/authentication/src/v1/mongo/User.ts b/api/authentication/src/v1/mongo/User.ts new file mode 100644 index 0000000..88e07fe --- /dev/null +++ b/api/authentication/src/v1/mongo/User.ts @@ -0,0 +1,32 @@ +import { argon2CreateHash } from '@hikers-book/cryptography'; +import { Model, MongooseDocument, MongooseNextCB, ObjectID, PreHook, Unique } from '@tsed/mongoose'; +import { Default, Enum, Property, Required } from '@tsed/schema'; +import { AuthProviderEnum } from '../types/enum'; + +@Model({ + schemaOptions: { timestamps: true } +}) +export class User { + @ObjectID('id') + _id!: string; + + @Unique() + @Required() + email!: string; + + @Required() + password!: string; + + @Property() + @Enum(AuthProviderEnum) + @Default(AuthProviderEnum.LOCAL) + auth_provider?: string; + + @PreHook('save') + static async preSave(user: MongooseDocument, next: MongooseNextCB) { + if (user.isModified('password')) { + user.password = await argon2CreateHash(user.password); + } + next(); + } +} diff --git a/api/authentication/src/v1/types/enum/AuthProvider.ts b/api/authentication/src/v1/types/enum/AuthProvider.ts new file mode 100644 index 0000000..35e78f5 --- /dev/null +++ b/api/authentication/src/v1/types/enum/AuthProvider.ts @@ -0,0 +1,3 @@ +export enum AuthProviderEnum { + LOCAL = 'local' +} diff --git a/api/authentication/src/v1/types/enum/index.ts b/api/authentication/src/v1/types/enum/index.ts new file mode 100644 index 0000000..5a24ddb --- /dev/null +++ b/api/authentication/src/v1/types/enum/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './AuthProvider'; diff --git a/api/authentication/src/v1/types/index.ts b/api/authentication/src/v1/types/index.ts new file mode 100644 index 0000000..8b556aa --- /dev/null +++ b/api/authentication/src/v1/types/index.ts @@ -0,0 +1,5 @@ +/** + * @file Automatically generated by barrelsby. + */ + +export * from './enum/AuthProvider';