Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Devcontainer #2

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .devcontainer/backend/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "Backend Node.js & TypeScript",
"dockerComposeFile": [
"../../docker-compose.yml",
"../../docker-compose.devcontainer.yml"
],
"workspaceFolder": "/workspace",
"service": "devcontainer",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
// "image": "mcr.microsoft.com/devcontainers/typescript-node:1-20-bullseye",
"features": {
"ghcr.io/devcontainers-contrib/features/nestjs-cli:2": {}
},
"customizations": {
"vscode": {
"extensions": [
"mongodb.mongodb-vscode",
"github.vscode-github-actions"
]
}
},
"remoteUser": "node",
"postCreateCommand": "sudo chown node node_modules"

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],

// Use 'postCreateCommand' to run commands after the container is created.
// "postCreateCommand": "yarn install",

// Configure tool-specific properties.
// "customizations": {},

// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
}
12 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for more information:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
# https://containers.dev/guide/dependabot

version: 2
updates:
- package-ecosystem: "devcontainers"
directory: "/"
schedule:
interval: weekly
32 changes: 32 additions & 0 deletions .github/workflows/codestyle.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Code Style Check

on: [push, pull_request]

permissions:
actions: read
contents: read
security-events: write

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Use Node.js
uses: actions/setup-node@v4
with:
node-version: '20.11.1'
- name: Install pnpm
uses: pnpm/action-setup@v3
with:
version: '8.15.4'
run_install: false

- name: Install dependencies
run: pnpm install

- name: Lint
run: pnpm run lint
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
.pnpm-store/

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
Expand Down
45 changes: 45 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Gateway: Dev",
"type": "shell",
"command": "pnpm start:dev gateway",
"group": "none",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
}
},
{
"label": "Auth: Dev",
"type": "shell",
"command": "pnpm start:dev auth",
"group": "none",
"presentation": {
"echo": true,
"reveal": "silent",
"focus": false,
"panel": "shared",
"showReuseMessage": true,
"clear": true
},
"problemMatcher": []
},
{
"label": "All: Dev",
"dependsOn": [
"Gateway: Dev",
"Auth: Dev"
],
"group": "none",
"runOptions": {
"runOn": "folderOpen"
}
}
]
}
15 changes: 15 additions & 0 deletions apps/auth/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
version: '3'
services:
mongodb:
image: mongo
restart: always
ports:
- 27017:27017
volumes:
- mongodb_data:/data/db
environment:
- MONGO_INITDB_ROOT_USERNAME=admin
- MONGO_INITDB_ROOT_PASSWORD=secret

volumes:
mongodb_data:
3 changes: 3 additions & 0 deletions apps/auth/src/auth.constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const jwtConstants = {
secret: 'verySecretKey',
};
22 changes: 22 additions & 0 deletions apps/auth/src/auth.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Test, TestingModule } from '@nestjs/testing';
import { AuthController } from './auth.controller';
import { AuthService } from './auth.service';

describe('AuthController', () => {
let authController: AuthController;

beforeEach(async () => {
const app: TestingModule = await Test.createTestingModule({
controllers: [AuthController],
providers: [AuthService],
}).compile();

authController = app.get<AuthController>(AuthController);
});

describe('root', () => {
it('should return "Hello World!"', () => {
expect(authController.getHello()).toBe('Hello World!');
});
});
});
13 changes: 13 additions & 0 deletions apps/auth/src/auth.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Body, Controller, Post, HttpCode, HttpStatus } from '@nestjs/common';
import { AuthService } from './auth.service';

@Controller('auth')
export class AuthController {
constructor(private authService: AuthService) {}

@HttpCode(HttpStatus.OK)
@Post('login')
signIn(@Body() signInDto: Record<string, any>) {
return this.authService.signIn(signInDto.username, signInDto.password);
}
}
25 changes: 25 additions & 0 deletions apps/auth/src/auth.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Module } from '@nestjs/common';
import { AuthService } from './auth.service';
import { UsersModule } from './users/users.module';
import { JwtModule } from '@nestjs/jwt';
import { AuthController } from './auth.controller';
import { jwtConstants } from './auth.constants';
import { MongooseModule } from '@nestjs/mongoose';

@Module({
imports: [
UsersModule,
JwtModule.register({
global: true,
secret: jwtConstants.secret,
signOptions: { expiresIn: '60s' },
}),
MongooseModule.forRoot(
'mongodb://admin:secret@mongodb/nest?authSource=admin',
),
],
providers: [AuthService],
controllers: [AuthController],
exports: [AuthService],
})
export class AuthModule {}
25 changes: 25 additions & 0 deletions apps/auth/src/auth.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { UsersService } from './users/users.service';
import { JwtService } from '@nestjs/jwt';

@Injectable()
export class AuthService {
constructor(
private usersService: UsersService,
private jwtService: JwtService,
) {}

async signIn(
username: string,
pass: string,
): Promise<{ access_token: string }> {
const user = await this.usersService.findOne(username);
if (user?.password !== pass) {
throw new UnauthorizedException();
}
const payload = { sub: user.email, username: user.username };
return {
access_token: await this.jwtService.signAsync(payload),
};
}
}
11 changes: 11 additions & 0 deletions apps/auth/src/dto/sign-in.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { IsString, IsNotEmpty } from 'class-validator';

export class SignInDto {
@IsString()
@IsNotEmpty()
username: string;

@IsString()
@IsNotEmpty()
password: string;
}
13 changes: 13 additions & 0 deletions apps/auth/src/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { NestFactory } from '@nestjs/core';
import { AuthModule } from './auth.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
const app = await NestFactory.create(AuthModule);

app.useGlobalPipes(new ValidationPipe({ whitelist: true }));

await app.listen(3001);
}

bootstrap();
15 changes: 15 additions & 0 deletions apps/auth/src/users/dto/create-user.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { IsEmail, IsNotEmpty, IsString } from 'class-validator';

export class CreateUserDto {
@IsEmail()
email: string;

@IsString()
@IsNotEmpty()
username: string;

// @IsStrongPassword()
@IsNotEmpty()
@IsString()
password: string;
}
13 changes: 13 additions & 0 deletions apps/auth/src/users/users.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Module } from '@nestjs/common';
import { UsersService } from './users.service';
import { MongooseModule } from '@nestjs/mongoose';
import { User, UserSchema } from './users.schema';

@Module({
imports: [
MongooseModule.forFeature([{ name: User.name, schema: UserSchema }]),
],
providers: [UsersService],
exports: [UsersService],
})
export class UsersModule {}
18 changes: 18 additions & 0 deletions apps/auth/src/users/users.schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
import { HydratedDocument } from 'mongoose';

export type UserDocument = HydratedDocument<User>;

@Schema()
export class User {
@Prop()
email: string;

@Prop()
username: string;

@Prop()
password: string;
}

export const UserSchema = SchemaFactory.createForClass(User);
18 changes: 18 additions & 0 deletions apps/auth/src/users/users.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Test, TestingModule } from '@nestjs/testing';
import { UsersService } from './users.service';

describe('UsersService', () => {
let service: UsersService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UsersService],
}).compile();

service = module.get<UsersService>(UsersService);
});

it('should be defined', () => {
expect(service).toBeDefined();
});
});
23 changes: 23 additions & 0 deletions apps/auth/src/users/users.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model } from 'mongoose';
import { User } from './users.schema';
import { CreateUserDto } from './dto/create-user.dto';

@Injectable()
export class UsersService {
constructor(@InjectModel(User.name) private userModel: Model<User>) {}

async create(createUserDto: CreateUserDto): Promise<User> {
const createdUser = new this.userModel(createUserDto);
return createdUser.save();
}

async findOne(emailOrUsername: string): Promise<User> {
return this.userModel
.findOne({
$or: [{ email: emailOrUsername }, { username: emailOrUsername }],
})
.exec();
}
}
6 changes: 3 additions & 3 deletions test/app.e2e-spec.ts → apps/auth/test/app.e2e-spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
import { AuthModule } from './../src/auth.module';

describe('AppController (e2e)', () => {
describe('AuthController (e2e)', () => {
let app: INestApplication;

beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
imports: [AuthModule],
}).compile();

app = moduleFixture.createNestApplication();
Expand Down
9 changes: 9 additions & 0 deletions apps/auth/test/jest-e2e.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"moduleFileExtensions": ["js", "json", "ts"],
"rootDir": ".",
"testEnvironment": "node",
"testRegex": ".e2e-spec.ts$",
"transform": {
"^.+\\.(t|j)s$": "ts-jest"
}
}
Loading