-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
34 changed files
with
1,081 additions
and
14 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 |
---|---|---|
@@ -0,0 +1,69 @@ | ||
name: publish-auth | ||
|
||
on: | ||
push: | ||
paths: | ||
- apps/auth/** | ||
- libs/** | ||
- package.json | ||
- bun.lockb | ||
- .github/workflows/publish-auth.yml | ||
workflow_dispatch: | ||
|
||
jobs: | ||
testing: | ||
uses: ./.github/workflows/wait-for-tests.yml | ||
with: | ||
test-job-name: test | ||
|
||
docker: | ||
needs: testing | ||
runs-on: ubuntu-latest | ||
steps: | ||
- name: Set up QEMU | ||
uses: docker/setup-qemu-action@v2 | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v2 | ||
|
||
- name: Docker meta | ||
id: meta | ||
uses: docker/metadata-action@v4 | ||
with: | ||
images: | | ||
bitsacco/auth | ||
tags: | | ||
type=ref,event=branch | ||
type=ref,event=pr | ||
type=semver,pattern={{version}} | ||
type=semver,pattern={{major}}.{{minor}} | ||
type=sha | ||
- name: Login to Docker Hub | ||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') | ||
uses: docker/login-action@v2 | ||
with: | ||
username: okjodom | ||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | ||
|
||
- name: Build and push auth | ||
uses: docker/build-push-action@v4 | ||
with: | ||
file: apps/auth/Dockerfile | ||
push: ${{ github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') }} | ||
tags: ${{ steps.meta.outputs.tags }} | ||
labels: ${{ steps.meta.outputs.labels }} | ||
|
||
- name: Checkout repository content | ||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') | ||
uses: actions/checkout@v4 | ||
|
||
# This workflow requires the repository content to be locally available to read the README | ||
- name: Update the Docker Hub description | ||
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v') | ||
uses: peter-evans/dockerhub-description@v3 | ||
with: | ||
username: okjodom | ||
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }} | ||
repository: bitsacco/auth | ||
readme-filepath: ./apps/auth/README.md |
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,6 @@ | ||
NODE_ENV='development' | ||
AUTH_GRPC_URL='auth:4010' | ||
DATABASE_URL=mongodb://bs:password@mongodb:27017 | ||
JWT_SECRET='secret' | ||
JWT_EXPIRATION='3600' | ||
PIN_SALT='BSPN' |
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,32 @@ | ||
FROM oven/bun:latest AS development | ||
|
||
WORKDIR /usr/src/app | ||
|
||
COPY package.json ./ | ||
COPY bun.lockb ./ | ||
COPY tsconfig.json tsconfig.json | ||
COPY nest-cli.json nest-cli.json | ||
|
||
COPY apps/auth apps/auth | ||
COPY libs libs | ||
COPY proto proto | ||
|
||
RUN bun install | ||
RUN bun build:auth | ||
|
||
FROM oven/bun:latest AS production | ||
|
||
ARG NODE_ENV=production | ||
ENV NODE_ENV=${NODE_ENV} | ||
|
||
WORKDIR /usr/src/app | ||
|
||
COPY package.json ./ | ||
COPY bun.lockb ./ | ||
|
||
RUN bun install --production | ||
|
||
COPY --from=development /usr/src/app/dist ./dist | ||
COPY --from=development /usr/src/app/proto ./proto | ||
|
||
CMD ["sh", "-c", "bun run dist/apps/auth/main.js"] |
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,17 @@ | ||
import { TestingModule } from '@nestjs/testing'; | ||
import { createTestingModuleWithValidation } from '@bitsacco/testing'; | ||
import { AuthController } from './auth.controller'; | ||
import { AuthService } from './auth.service'; | ||
|
||
describe('AuthController', () => { | ||
let authController: AuthController; | ||
|
||
beforeEach(async () => { | ||
const app: TestingModule = await createTestingModuleWithValidation({ | ||
controllers: [AuthController], | ||
providers: [AuthService], | ||
}); | ||
|
||
authController = app.get<AuthController>(AuthController); | ||
}); | ||
}); |
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,36 @@ | ||
import { Controller } from '@nestjs/common'; | ||
import { AuthService } from './auth.service'; | ||
import { | ||
AuthRequestDto, | ||
AuthServiceControllerMethods, | ||
LoginUserRequestDto, | ||
RegisterUserRequestDto, | ||
VerifyUserRequestDto, | ||
} from '@bitsacco/common'; | ||
import { GrpcMethod } from '@nestjs/microservices'; | ||
|
||
@Controller() | ||
@AuthServiceControllerMethods() | ||
export class AuthController { | ||
constructor(private readonly authService: AuthService) {} | ||
|
||
@GrpcMethod() | ||
loginUser(req: LoginUserRequestDto) { | ||
return this.authService.loginUser(req); | ||
} | ||
|
||
@GrpcMethod() | ||
registerUser(req: RegisterUserRequestDto) { | ||
return this.authService.registerUser(req); | ||
} | ||
|
||
@GrpcMethod() | ||
verifyuser(req: VerifyUserRequestDto) { | ||
return this.authService.verifyUser(req); | ||
} | ||
|
||
@GrpcMethod() | ||
authenticate(req: AuthRequestDto) { | ||
return this.authService.authenticate(req); | ||
} | ||
} |
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,47 @@ | ||
import * as Joi from 'joi'; | ||
import { Module } from '@nestjs/common'; | ||
import { JwtModule } from '@nestjs/jwt'; | ||
import { ConfigModule, ConfigService } from '@nestjs/config'; | ||
import { | ||
DatabaseModule, | ||
LoggerModule, | ||
UsersDocument, | ||
UsersSchema, | ||
} from '@bitsacco/common'; | ||
import { UsersRepository } from './users/users.repository'; | ||
import { UsersService } from './users/users.service'; | ||
import { AuthController } from './auth.controller'; | ||
import { AuthService } from './auth.service'; | ||
|
||
@Module({ | ||
imports: [ | ||
ConfigModule.forRoot({ | ||
isGlobal: true, | ||
validationSchema: Joi.object({ | ||
NODE_ENV: Joi.string().required(), | ||
AUTH_GRPC_URL: Joi.string().required(), | ||
DATABASE_URL: Joi.string().required(), | ||
JWT_SECRET: Joi.string().required(), | ||
JWT_EXPIRATION: Joi.string().required(), | ||
PIN_SALT: Joi.string().required(), | ||
}), | ||
}), | ||
DatabaseModule, | ||
DatabaseModule.forFeature([ | ||
{ name: UsersDocument.name, schema: UsersSchema }, | ||
]), | ||
JwtModule.registerAsync({ | ||
useFactory: (configService: ConfigService) => ({ | ||
secret: configService.get<string>('JWT_SECRET'), | ||
signOptions: { | ||
expiresIn: `${configService.get('JWT_EXPIRATION')}s`, | ||
}, | ||
}), | ||
inject: [ConfigService], | ||
}), | ||
LoggerModule, | ||
], | ||
controllers: [AuthController], | ||
providers: [AuthService, UsersRepository, UsersService], | ||
}) | ||
export class AuthModule {} |
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,71 @@ | ||
import { JwtService } from '@nestjs/jwt'; | ||
import { ConfigService } from '@nestjs/config'; | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { | ||
AuthRequest, | ||
LoginUserRequestDto, | ||
RegisterUserRequestDto, | ||
User, | ||
VerifyUserRequestDto, | ||
} from '@bitsacco/common'; | ||
import { UsersService } from './users'; | ||
|
||
interface AuthTokenPayload { | ||
user: User; | ||
expires: Date; | ||
} | ||
|
||
@Injectable() | ||
export class AuthService { | ||
private readonly logger = new Logger(AuthService.name); | ||
|
||
constructor( | ||
private readonly configService: ConfigService, | ||
private readonly userService: UsersService, | ||
private readonly jwtService: JwtService, | ||
) { | ||
this.logger.log('AuthService initialized'); | ||
} | ||
|
||
async loginUser(req: LoginUserRequestDto) { | ||
const user = await this.userService.validateUser(req); | ||
|
||
return this.createAuthToken(user); | ||
} | ||
|
||
async registerUser(req: RegisterUserRequestDto) { | ||
return this.userService.registerUser(req); | ||
} | ||
|
||
async verifyUser(req: VerifyUserRequestDto) { | ||
return this.userService.verifyUser(req); | ||
} | ||
|
||
async authenticate({ token }: AuthRequest) { | ||
const { user, expires } = this.jwtService.verify<AuthTokenPayload>(token); | ||
|
||
if (expires < new Date()) { | ||
throw new Error('Token expired. Unauthenticated'); | ||
} | ||
|
||
const u = await this.userService.findUser({ | ||
id: user.id, | ||
}); | ||
|
||
return this.createAuthToken(u); | ||
} | ||
|
||
private createAuthToken(user: User) { | ||
const expires = new Date(); | ||
expires.setSeconds( | ||
expires.getSeconds() + this.configService.get('JWT_EXPIRATION'), | ||
); | ||
|
||
const payload: AuthTokenPayload = { | ||
user, | ||
expires, | ||
}; | ||
|
||
return this.jwtService.sign(payload); | ||
} | ||
} |
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,33 @@ | ||
import { join } from 'path'; | ||
import { Logger } from 'nestjs-pino'; | ||
import { NestFactory } from '@nestjs/core'; | ||
import { ConfigService } from '@nestjs/config'; | ||
import { ReflectionService } from '@grpc/reflection'; | ||
import { MicroserviceOptions, Transport } from '@nestjs/microservices'; | ||
import { AuthModule } from './auth.module'; | ||
|
||
async function bootstrap() { | ||
const app = await NestFactory.create(AuthModule); | ||
|
||
const configService = app.get(ConfigService); | ||
|
||
const auth_url = configService.getOrThrow<string>('AUTH_GRPC_URL'); | ||
const auth = app.connectMicroservice<MicroserviceOptions>({ | ||
transport: Transport.GRPC, | ||
options: { | ||
package: 'auth', | ||
url: auth_url, | ||
protoPath: join(__dirname, '../../../proto/auth.proto'), | ||
onLoadPackageDefinition: (pkg, server) => { | ||
new ReflectionService(pkg).addToServer(server); | ||
}, | ||
}, | ||
}); | ||
|
||
// setup pino logging | ||
app.useLogger(app.get(Logger)); | ||
|
||
await app.startAllMicroservices(); | ||
} | ||
|
||
bootstrap(); |
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,22 @@ | ||
import { Strategy } from 'passport-local'; | ||
import { PassportStrategy } from '@nestjs/passport'; | ||
import { Injectable, UnauthorizedException } from '@nestjs/common'; | ||
import { UsersService } from '../users/users.service'; | ||
|
||
@Injectable() | ||
export class PhoneStategy extends PassportStrategy(Strategy) { | ||
constructor(private readonly usersService: UsersService) { | ||
super({ usernameField: 'phone', passwordField: 'pinHash' }); | ||
} | ||
|
||
async validate(phone: string, pin: string) { | ||
try { | ||
return await this.usersService.validateUser({ | ||
pin, | ||
phone, | ||
}); | ||
} catch (err) { | ||
throw new UnauthorizedException(err); | ||
} | ||
} | ||
} |
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,2 @@ | ||
export * from './users.repository'; | ||
export * from './users.service'; |
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,16 @@ | ||
import { Model } from 'mongoose'; | ||
import { InjectModel } from '@nestjs/mongoose'; | ||
import { Injectable, Logger } from '@nestjs/common'; | ||
import { AbstractRepository, UsersDocument } from '@bitsacco/common'; | ||
|
||
@Injectable() | ||
export class UsersRepository extends AbstractRepository<UsersDocument> { | ||
protected readonly logger = new Logger(UsersRepository.name); | ||
|
||
constructor( | ||
@InjectModel(UsersDocument.name) | ||
userModel: Model<UsersDocument>, | ||
) { | ||
super(userModel); | ||
} | ||
} |
Oops, something went wrong.