Skip to content

Commit

Permalink
Merge pull request #2 from Innovix-Matrix-Systems/IMS-16
Browse files Browse the repository at this point in the history
IMS-16: X-security setup with command and middleware support
  • Loading branch information
AHS12 authored Oct 18, 2024
2 parents 3812ff0 + 3845583 commit 9f9498a
Show file tree
Hide file tree
Showing 10 changed files with 324 additions and 20 deletions.
4 changes: 4 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ APP_URL=http://localhost
JWT_SECRET=your-jwt-secret-key
JWT_EXPIRATION=3600 # 1 hour in seconds

# XSecurity Config
XSECURITY_ENABLED=false
XSECURITY_SECRET=your-XSecurity-secret

# Database Config
DB_HOST=localhost
DB_PORT=5432
Expand Down
38 changes: 37 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@
```bash
docker-compose exec app bash
```

Once inside the container, execute the following commands:

```bash
npm run migration:up
npm run seeder:run
```

This will apply any pending migrations and populate the database with seed data.

4. **Git hook for Check**
Expand All @@ -133,7 +135,6 @@
npx husky install
```


## Health Check

To ensure the health of your application, we have integrated [Terminus](https://docs.nestjs.com/recipes/terminus) for health checks.
Expand Down Expand Up @@ -185,6 +186,37 @@ Run tests using Jest:
npm run test
```

## Xsecurity Setup

IMS introduces an additional layer of security, enhancing the API's reliability and resilience. With this system, only applications possessing a shared XSECURITY_TOKEN can send API requests to the server; others will be blocked. To get started, follow the guide below.
Getting Started
By default, XSecure is disabled! To enable it, set the XSECURITY_ENABLED value to true in your .env file:
```bash
XSECURITY_ENABLED=true
```
Other wise it will be disabled.
Installation
Execute the following command to set up XSECURITY:
```bash
npm run xsecurity:install
```
This command generates a secret for your application and updates your .env file with the `XSECURITY_SECRET` field.
After running the command, you will receive output similar to this:
```bash
Generated secret: N+6WQq7RjqvE+KhMRFDtk1n09M98lBAb/P/8j/I3w/7ibNzgbJeg2a+gBjNpPbMgyXSgq0sebXzYwPwnFSmleg==
XSECURITY_SECRET key has been updated in the .env file.
```
Use this secret in your frontend or mobile app to generate a short-lived XSecure token, which will be verified by the backend server.
For more information on how to use XSECURITY, refer to the [XSECURITY Guide](https://github.com/Innovix-Matrix-Systems/ims-laravel-api-starter/wiki/XSECURE-setup).
## Extra CLI Commands
### Generate MikroORM Entities:
Expand Down Expand Up @@ -226,6 +258,10 @@ You can also run this command to see all the CLI commands available in your proj
nest generate --help
```
You can create custom CLI commands tailored to your specific needs using the [nestjs-command](https://www.npmjs.com/package/nestjs-command) package.
This project already includes integration with [nestjs-command](https://www.npmjs.com/package/nestjs-command) package.
For reference, check out the `xsecurity` command implemented in [src/commands/xsecurity.command.ts](https://github.com/Innovix-Matrix-System/ims-nest-api-starter/blob/master/src/commands/xsecurity.command.ts).
## Authors
- [@AHS12](https://www.github.com/AHS12)
Expand Down
57 changes: 47 additions & 10 deletions ims-nest-api-starter.postman_collection.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@
"info": {
"_postman_id": "0f10bdbf-368f-47c9-8a59-e7d1586fae52",
"name": "ims-nest-api-starter",
"description": "# IMS-NEST-API-STARTER API Documentation\n\n## Introduction\n\nWelcome to the api documentation.\n`ims-nest-api-starter` is a backend API starter template using [NestJS](https://nestjs.com/) and [MikroORM](https://mikro-orm.io/) designed for scalable applications. This starter includes authentication, authorization, user management, role management, and role/permission-based access",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "29444436",
"_collection_link": "https://innovix-matrix-system.postman.co/workspace/Innovix-Matrix-System-Workspace~c0ff4f3a-4d52-490d-81f4-c33d60e51246/collection/29444436-0f10bdbf-368f-47c9-8a59-e7d1586fae52?action=share&source=collection_link&creator=29444436"
"_collection_link": "https://innovix-matrix-system.postman.co/workspace/c0ff4f3a-4d52-490d-81f4-c33d60e51246/collection/29444436-0f10bdbf-368f-47c9-8a59-e7d1586fae52?action=share&source=collection_link&creator=29444436"
},
"item": [
{
"name": "health",
"name": "Health",
"item": [
{
"name": "healthz",
Expand Down Expand Up @@ -46,7 +47,8 @@
},
"response": []
}
]
],
"description": "## Introduction\n\nProvides endpoints to check API app health\n\n## Endpoints\n\nList the available endpoints for this section, along with a brief description of what each endpoint does.\n\n### healthz\n\n| Type | Endpoint | Description |\n| --- | --- | --- |\n| `GET` | `/health` | checks the health of the app |\n| `GET` | `api/v1/ping` | ping the api! |"
},
{
"name": "Auth",
Expand Down Expand Up @@ -86,7 +88,8 @@
},
"response": []
}
]
],
"description": "## Introduction\n\nProvides endpoints to log into the app\n\n## Endpoints\n\nList the available endpoints for this section, along with a brief description of what each endpoint does.\n\n### Login\n\n| Type | Endpoint | Description |\n| --- | --- | --- |\n| `POST` | `/api/v1/login` | traditional login with email and password |"
},
{
"name": "Role & Permissions",
Expand Down Expand Up @@ -123,7 +126,8 @@
},
"response": []
}
]
],
"description": "## Endpoints\n\nList the available endpoints for this section, along with a brief description of what each endpoint does.\n\n### Login\n\n| Type | Endpoint | Description |\n| --- | --- | --- |\n| `GET` | `/api/v1/permission` | get list of all system permission |"
},
{
"name": "Role",
Expand Down Expand Up @@ -236,16 +240,18 @@
"variable": [
{
"key": "id",
"value": "4"
"value": "5"
}
]
}
},
"response": []
}
]
],
"description": "## Endpoints\n\nList the available endpoints for this section, along with a brief description of what each endpoint does.\n\n### Login\n\n| Type | Endpoint | Description |\n| --- | --- | --- |\n| `GET` | `/api/v1/role` | get list of all roles |\n| `POST` | `/api/v1/role` | insert role |\n| `DELETE` | `/api/v1/role/:id` | Delete role |"
}
]
],
"description": "## Introduction\n\nProvides endpoints of Role and Permission Management"
},
{
"name": "User",
Expand Down Expand Up @@ -590,6 +596,36 @@
},
"response": []
},
{
"name": "get permissions",
"request": {
"auth": {
"type": "bearer",
"bearer": [
{
"key": "token",
"value": "{{auth_token}}",
"type": "string"
}
]
},
"method": "GET",
"header": [],
"url": {
"raw": "{{base_url}}/api/v1/user/permissions",
"host": [
"{{base_url}}"
],
"path": [
"api",
"v1",
"user",
"permissions"
]
}
},
"response": []
},
{
"name": "Update Profile",
"request": {
Expand Down Expand Up @@ -669,7 +705,7 @@
"response": []
},
{
"name": "change use password",
"name": "change user password",
"request": {
"auth": {
"type": "bearer",
Expand Down Expand Up @@ -714,7 +750,8 @@
},
"response": []
}
]
],
"description": "## Introduction\n\nProvides endpoints of User management Management\n\n## Endpoints\n\nList the available endpoints for this section, along with a brief description of what each endpoint does.\n\n### Login\n\n| Type | Endpoint | Description |\n| --- | --- | --- |\n| `GET` | `/api/v1/user` | get list of all users |\n| `POST` | `/api/v1/user` | insert user |\n| `GET` | `/api/v1/user/:id` | get user details |\n| `PATCH` | `/api/v1/user/:id` | update user |\n| `DELETE` | `/api/v1/user/:id` | Delete user |\n| `POST` | `/api/v1/user/:id/roles` | assign user roles |\n| `POST` | `/api/v1/user/:id/permissions` | assign user permissions |\n| `GET` | `/api/v1/user/profile` | get logged in user profile |\n| `GET` | `/api/v1/user/permissions` | get logged in user permissions |\n| `PATCH` | `/api/v1/user/profile` | update logged in user profile |\n| `PATCH` | `/api/v1/user/change-password` | update/reset logged in user password |\n| `PATCH` | `/api/v1/user/:id/change-password` | update/reset a user password |"
}
],
"event": [
Expand Down
52 changes: 51 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"migration:fresh": "npx mikro-orm migration:fresh --seed",
"seeder:create": "npx mikro-orm seeder:create",
"seeder:run": "npx mikro-orm seeder:run",
"xsecurity:install": "cross-env CLI_PATH=./dist/cli.js npx nestjs-command xsecurity:install",
"prepare": "husky"
},
"dependencies": {
Expand All @@ -50,12 +51,14 @@
"class-validator": "^0.14.1",
"dotenv": "^16.4.5",
"ims-nest-api-starter": "file:",
"nestjs-command": "^3.1.4",
"passport": "^0.7.0",
"passport-jwt": "^4.0.1",
"passport-local": "^1.0.0",
"pg": "^8.13.0",
"reflect-metadata": "^0.2.0",
"rxjs": "^7.8.1"
"rxjs": "^7.8.1",
"yargs": "^17.7.2"
},
"devDependencies": {
"@nestjs/cli": "^10.0.0",
Expand All @@ -68,8 +71,10 @@
"@types/passport-jwt": "^4.0.1",
"@types/passport-local": "^1.0.38",
"@types/supertest": "^6.0.0",
"@types/yargs": "^17.0.33",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"cross-env": "^7.0.3",
"eslint": "^8.42.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-prettier": "^5.0.0",
Expand Down
21 changes: 15 additions & 6 deletions src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { MikroOrmModule } from '@mikro-orm/nestjs';
import { Module } from '@nestjs/common';
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { CommandModule } from 'nestjs-command';
import { AppController } from './app.controller';
import { AuthModule } from './auth/auth.module';
import { XSecureInstallCommand } from './commands/xsecurity.command';
import mikroOrmConfig from './config/mikro-orm.config';
import { HealthModule } from './health/health.module';
import { XSecurityMiddleware } from './middlewares/xsecurity.middleware';
import { MiscModule } from './misc/misc.module';
import { PermissionModule } from './permission/permission.module';
import { RoleModule } from './role/role.module';
Expand All @@ -23,14 +26,20 @@ import { UserModule } from './user/user.module';
mikroOrmConfig(configService),
inject: [ConfigService],
}),
UserModule,
CommandModule,
HealthModule,
MiscModule,
AuthModule,
PermissionModule,
RoleModule,
HealthModule,
UserModule,
AuthModule,
],
controllers: [AppController],
providers: [],
providers: [XSecureInstallCommand],
})
export class AppModule {}
// export class AppModule {}
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer.apply(XSecurityMiddleware).forRoutes('*');
}
}
19 changes: 19 additions & 0 deletions src/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { NestFactory } from '@nestjs/core';
import { CommandModule, CommandService } from 'nestjs-command';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.createApplicationContext(AppModule, {
logger: false,
});
try {
await app.select(CommandModule).get(CommandService).exec();
await app.close();
} catch (error) {
console.error(error);
await app.close();
process.exit(1);
}
}

bootstrap();
Loading

0 comments on commit 9f9498a

Please sign in to comment.