Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
P
payment link revamp
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Daffa
payment link revamp
Commits
5152dcd0
Commit
5152dcd0
authored
Oct 01, 2025
by
Daffa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial commit for boiler plate
parent
7d14eb9e
Pipeline
#2158
failed
Changes
18
Pipelines
1
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
295 additions
and
596 deletions
+295
-596
.env.example
.env.example
+6
-9
README.md
README.md
+210
-24
package-lock.json
package-lock.json
+77
-94
20220820080609-create-roles-table.js
src/database/migrations/20220820080609-create-roles-table.js
+0
-50
20220820082820-create-users-table.js
src/database/migrations/20220820082820-create-users-table.js
+1
-7
user.model.ts
src/database/models/user.model.ts
+0
-22
auth.controller.ts
src/modules/auth/auth.controller.ts
+0
-1
auth.service.ts
src/modules/auth/auth.service.ts
+0
-2
assign-permission.dto.ts
src/modules/users/dto/assign-permission.dto.ts
+0
-11
create-role.dto.ts
src/modules/users/dto/create-role.dto.ts
+0
-36
permission.query.dto.ts
src/modules/users/dto/permission.query.dto.ts
+0
-13
role.query.dto.ts
src/modules/users/dto/role.query.dto.ts
+0
-18
update-role-permission.dto.ts
src/modules/users/dto/update-role-permission.dto.ts
+0
-25
update-role.dto.ts
src/modules/users/dto/update-role.dto.ts
+0
-33
roles.controller.ts
src/modules/users/roles.controller.ts
+0
-67
roles.service.ts
src/modules/users/roles.service.ts
+0
-146
users.module.ts
src/modules/users/users.module.ts
+1
-9
is_exist_role.ts
src/modules/users/validators/is_exist_role.ts
+0
-29
No files found.
.env.example
View file @
5152dcd0
# Database
DATABASE_DIALECT="
mysql
"
DATABASE_HOST=
localhost
DATABASE_PORT=
3306
DATABASE_USERNAME=
root
#
#
Database
DATABASE_DIALECT="
postgres
"
DATABASE_HOST=
"localhost"
DATABASE_PORT=
5432
DATABASE_USERNAME=
DATABASE_PASSWORD=
DATABASE_NAME=nestjs_development
DATABASE_TIMEZONE="+07:00"
DATABASE_BENCHMARK=true
# only for managed DB
DATABASE_NAME=
DB_SSL=false
# App
...
...
README.md
View file @
5152dcd0
# NestJS
Starter
# NestJS
Boilerplate
## Requirement
1.
Node.js 16.15.0
2.
Git
3.
PostgreSQL
A production-ready NestJS boilerplate with authentication, PostgreSQL, Sequelize ORM, and Redis integration.
## Features
-
**Authentication**
: JWT-based authentication with refresh tokens
-
**Database**
: PostgreSQL with Sequelize ORM
-
**Caching**
: Redis integration
-
**Validation**
: Class-validator for request validation
-
**API Documentation**
: Swagger/OpenAPI documentation
-
**Email**
: Mailgun integration for sending emails
-
**File Upload**
: Built-in file upload support
-
**Security**
: Helmet, CORS, rate limiting
-
**Code Quality**
: ESLint, Prettier
## Requirements
-
Node.js 16.17.0+
-
npm 8.15.0+
-
PostgreSQL 12+
-
Redis (optional, for caching)
-
Git
## Installation
1.
Clone this project
### 1. Clone the repository
```
bash
git clone <your-repo-url>
cd
nest-boiler-plate
npm
install
```
### 2. Environment Setup
Copy the example environment file and update the configuration:
```
bash
cp
.env.example .env
```
Update the following variables in
`.env`
:
-
**Database**
:
`DATABASE_DIALECT`
,
`DATABASE_HOST`
,
`DATABASE_PORT`
,
`DATABASE_USERNAME`
,
`DATABASE_PASSWORD`
,
`DATABASE_NAME`
-
**Redis**
:
`REDIS_HOST`
,
`REDIS_PORT`
-
**JWT**
: Keys are already generated, but you can replace them
-
**Mail**
:
`MAIL_API_KEY`
,
`MAIL_DOMAIN`
(if using Mailgun)
### 3. Database Setup
Create the database:
```
bash
npm run db:create
```
Run migrations:
```
bash
$
git clone git@git.seni.cloud:nodejs/nestjs-starter.git
$
cd
nestjs-starter
$
npm
install
npm run db:migrate
```
2.
Create Environment (Update Database dan Email Environment)
(Optional) Seed the database:
```
bash
npm run db:seed
```
## Development
Start the development server with hot-reload:
```
bash
npm run start:dev
```
The API will be available at
`http://localhost:3000`
## Production
Build the application:
```
bash
npm run build
```
Start the production server:
```
bash
npm run start:prod
```
## Database Commands
### Migrations
Create a new migration:
```
bash
$
cd
nestjs-starter
$
cp
.env.example .env
npx sequelize migration:generate
--name
create-your-table-name
```
3.
Create Database
Run all pending migrations:
```
bash
$
npm run db:cre
ate
npm run db:migr
ate
```
4.
Migrate Database
Check migration status:
```
bash
$
npm run db:migrate
$
npm run db:seed
npm run db:migrate:status
```
## How To Start Develop
Undo the last migration:
```
bash
npm run db:migrate:undo
```
1.
Run Application
Reset database (undo all migrations and re-run them):
```
bash
$
npm run start:dev
npm run db:reset
```
## How To Start Production
### Seeds
Create a new seed file:
```
bash
npx sequelize seed:generate
--name
seed-name
```
1.
Run Application
Run all seeds:
```
bash
$
npm run start:pro
d
npm run db:see
d
```
## API Documentation
Open the API documentation from browser:
[
http://localhost:3000/api-documentation
](
http://localhost:3000/api-documentation
)
Once the application is running, access the Swagger documentation at:
```
http://localhost:3000/api-documentation
```
## Available Scripts
-
`npm run start:dev`
- Start development server with hot-reload
-
`npm run start:prod`
- Start production server
-
`npm run build`
- Build the application
-
`npm run lint`
- Run ESLint
-
`npm run format`
- Format code with Prettier
-
`npm run test`
- Run unit tests
-
`npm run test:watch`
- Run tests in watch mode
-
`npm run test:cov`
- Run tests with coverage
-
`npm run db:create`
- Create database
-
`npm run db:migrate`
- Run migrations
-
`npm run db:migrate:status`
- Check migration status
-
`npm run db:migrate:undo`
- Undo last migration
-
`npm run db:reset`
- Reset database (undo all and re-run)
-
`npm run db:seed`
- Run seeders
## Project Structure
```
src/
├── common/ # Shared utilities, constants, decorators
├── database/ # Database models, migrations, seeders
│ ├── migrations/ # Sequelize migrations
│ ├── models/ # Sequelize models
│ └── seeders/ # Database seeders
├── interceptors/ # Global interceptors
├── middleware/ # Custom middleware
├── modules/ # Feature modules
│ ├── auth/ # Authentication module
│ └── users/ # Users module
├── share/ # Shared services and guards
├── app.module.ts # Root module
└── main.ts # Application entry point
```
## Creating New Migrations
### Example: Create a products table
1.
Generate migration file:
```
bash
npx sequelize migration:generate
--name
create-products-table
```
2.
Edit the generated file in
`src/database/migrations/`
:
```
javascript
'use strict'
;
module
.
exports
=
{
async
up
(
queryInterface
,
Sequelize
)
{
await
queryInterface
.
createTable
(
'products'
,
{
id
:
{
type
:
Sequelize
.
BIGINT
,
autoIncrement
:
true
,
primaryKey
:
true
,
allowNull
:
false
},
name
:
{
type
:
Sequelize
.
STRING
,
allowNull
:
false
},
description
:
{
type
:
Sequelize
.
TEXT
,
allowNull
:
true
},
price
:
{
type
:
Sequelize
.
DECIMAL
(
10
,
2
),
allowNull
:
false
},
createdAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'created_at'
,
allowNull
:
false
,
defaultValue
:
Sequelize
.
fn
(
'NOW'
)
},
updatedAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'updated_at'
,
allowNull
:
false
,
defaultValue
:
Sequelize
.
fn
(
'NOW'
)
}
});
await
queryInterface
.
addIndex
(
'products'
,
[
'name'
]);
},
async
down
(
queryInterface
)
{
await
queryInterface
.
dropTable
(
'products'
);
}
};
```
3.
Run the migration:
```
bash
npm run db:migrate
```
## Contributors
-
Daffa Praramadhana -
[
daffa.praramadhana@mdd.co.id
](
mailto:daffa.praramadhana@mdd.co.id
)
## License
Copyright © 2025 Multidaya Dinamika. All rights reserved.
package-lock.json
View file @
5152dcd0
This diff is collapsed.
Click to expand it.
src/database/migrations/20220820080609-create-roles-table.js
deleted
100644 → 0
View file @
7d14eb9e
'use strict'
;
module
.
exports
=
{
async
up
(
queryInterface
,
Sequelize
)
{
await
queryInterface
.
createTable
(
'roles'
,
{
id
:
{
type
:
Sequelize
.
BIGINT
,
autoIncrement
:
true
,
primaryKey
:
true
,
allowNull
:
false
},
name
:
{
type
:
Sequelize
.
STRING
(
50
),
allowNull
:
false
},
displayName
:
{
type
:
Sequelize
.
STRING
,
field
:
'display_name'
,
allowNull
:
true
,
},
active
:
{
type
:
Sequelize
.
BOOLEAN
,
allowNull
:
false
,
defaultValue
:
false
,
},
createdAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'created_at'
,
allowNull
:
false
,
defaultValue
:
Sequelize
.
fn
(
'NOW'
),
},
updatedAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'updated_at'
,
allowNull
:
false
,
defaultValue
:
Sequelize
.
fn
(
'NOW'
),
},
deletedAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'deleted_at'
,
allowNull
:
true
,
defaultValue
:
null
}
});
},
async
down
(
queryInterface
)
{
await
queryInterface
.
dropTable
(
'roles'
);
}
};
src/database/migrations/20220820082820-create-users-table.js
View file @
5152dcd0
...
...
@@ -29,11 +29,6 @@ module.exports = {
allowNull
:
false
,
defaultValue
:
false
,
},
roleId
:
{
type
:
Sequelize
.
BIGINT
,
field
:
'role_id'
,
references
:
{
model
:
'roles'
,
key
:
'id'
}
},
emailVerificationSentAt
:
{
type
:
Sequelize
.
DATE
,
field
:
'email_verification_sent_at'
,
...
...
@@ -63,9 +58,8 @@ module.exports = {
});
await
queryInterface
.
addIndex
(
'users'
,
[
'email'
]);
await
queryInterface
.
addIndex
(
'users'
,
[
'phone_number'
]);
await
queryInterface
.
addIndex
(
'users'
,
[
'phone_number'
]);
await
queryInterface
.
addIndex
(
'users'
,
[
'active'
]);
await
queryInterface
.
addIndex
(
'users'
,
[
'role_id'
]);
},
async
down
(
queryInterface
)
{
...
...
src/database/models/user.model.ts
View file @
5152dcd0
...
...
@@ -2,32 +2,17 @@ import {
AllowNull
,
BeforeCreate
,
BeforeUpdate
,
BelongsTo
,
Column
,
DefaultScope
,
DeletedAt
,
ForeignKey
,
HasMany
,
HasOne
,
Scopes
,
Table
,
Unique
,
}
from
"sequelize-typescript"
;
import
{
generateHash
}
from
"src/common/hash"
;
import
{
TimestampModel
}
from
"src/database/models/timestamp.model"
;
import
{
Role
}
from
"./role.model"
;
@
DefaultScope
(()
=>
({
attributes
:
{
exclude
:
[
"password"
,
"deletedAt"
]
},
include
:
[
Role
],
}))
@
Scopes
(()
=>
({
role
:
()
=>
({
include
:
[
{
model
:
Role
.
unscoped
(),
attributes
:
[
'id'
,
'name'
,
'displayName'
,
'active'
]}
],
})
}))
@
Table
({
timestamps
:
true
,
tableName
:
"users"
})
...
...
@@ -54,10 +39,6 @@ export class User extends TimestampModel {
@
Column
({
defaultValue
:
false
})
active
:
boolean
;
@
ForeignKey
(()
=>
Role
)
@
Column
({
field
:
"role_id"
})
roleId
:
number
;
@
Column
({
field
:
"email_verification_sent_at"
})
emailVerificationSentAt
:
Date
;
...
...
@@ -68,9 +49,6 @@ export class User extends TimestampModel {
@
Column
({
field
:
"deleted_at"
})
deletedAt
?:
Date
;
@
BelongsTo
(()
=>
Role
)
role
:
Role
;
@
BeforeCreate
static
hashPassword
(
instance
:
User
)
{
if
(
instance
.
password
)
{
...
...
src/modules/auth/auth.controller.ts
View file @
5152dcd0
...
...
@@ -48,7 +48,6 @@ export class AuthController {
const
token
=
await
this
.
authService
.
createAccessToken
({
user
:
user
.
id
,
role
:
user
.
roleId
,
});
const
data_user
=
await
this
.
userService
.
findOne
(
user
.
id
);
...
...
src/modules/auth/auth.service.ts
View file @
5152dcd0
...
...
@@ -77,7 +77,6 @@ export class AuthService {
}
async
createAccessToken
(
data
:
{
role
:
number
;
user
:
number
;
}):
Promise
<
TokenDto
>
{
...
...
@@ -89,7 +88,6 @@ export class AuthService {
accessToken
:
await
this
.
jwtService
.
signAsync
({
type
:
this
.
appConfigService
.
jwt
().
accessTokenType
,
user
:
data
.
user
,
role
:
data
.
role
,
},
{
expiresIn
:
expiresIn
,
}),
...
...
src/modules/users/dto/assign-permission.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
IsDefined
}
from
"class-validator"
;
export
class
assignPermissionDto
{
@
ApiProperty
({
example
:
[
1
,
2
],
required
:
true
,
})
@
IsDefined
()
permissionIds
:
any
;
}
src/modules/users/dto/create-role.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
IsDefined
,
IsString
,
IsBoolean
,
IsEnum
,
IsOptional
,
}
from
"class-validator"
;
import
{
Transform
}
from
"class-transformer"
;
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
toBoolean
}
from
"src/common/cast"
;
import
{
ROLE_EXCEPT_SUPER_ENUM
}
from
"./../../../common/constant"
;
export
class
CreateRoleDto
{
@
ApiProperty
({
example
:
"Admin"
,
description
:
"The role name"
})
@
IsDefined
()
@
IsString
()
@
IsEnum
(
ROLE_EXCEPT_SUPER_ENUM
,
{
message
:
"Nama role harus bernilai Admin atau Patient"
})
name
:
ROLE_EXCEPT_SUPER_ENUM
;
@
ApiProperty
({
example
:
"Admin"
,
description
:
"The role display name"
})
@
IsDefined
()
@
IsString
()
displayName
:
string
;
@
ApiProperty
({
example
:
true
,
description
:
"Set true if you want to activate this role"
,
required
:
false
,
})
@
Transform
(({
value
})
=>
toBoolean
(
value
))
@
IsOptional
()
@
IsBoolean
()
active
?:
boolean
;
}
src/modules/users/dto/permission.query.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
Transform
}
from
"class-transformer"
;
import
{
IsOptional
}
from
"class-validator"
;
import
{
Op
}
from
"sequelize"
;
import
{
QueryDto
}
from
"src/common/dto/query.dto"
;
export
class
PermissionQueryDto
extends
QueryDto
{
@
ApiProperty
({
required
:
false
})
@
IsOptional
()
@
Transform
(({
value
})
=>
({
[
Op
.
iLike
]:
`%
${
value
}
%`
}))
name
:
string
;
}
src/modules/users/dto/role.query.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
Transform
}
from
"class-transformer"
;
import
{
IsOptional
}
from
"class-validator"
;
import
{
Op
}
from
"sequelize"
;
import
{
toBoolean
}
from
"src/common/cast"
;
import
{
QueryDto
}
from
"src/common/dto/query.dto"
;
export
class
RoleQueryDto
extends
QueryDto
{
@
ApiProperty
({
required
:
false
})
@
IsOptional
()
@
Transform
(({
value
})
=>
({
[
Op
.
iLike
]:
`%
${
value
}
%`
}))
name
:
string
;
@
ApiProperty
({
required
:
false
})
@
Transform
(({
value
})
=>
toBoolean
(
value
))
@
IsOptional
()
active
?:
boolean
;
}
src/modules/users/dto/update-role-permission.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
IsDefined
,
IsInt
,
IsBoolean
,
}
from
"class-validator"
;
import
{
Transform
,
Type
}
from
"class-transformer"
;
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
toBoolean
}
from
"src/common/cast"
;
export
class
UpdateRolePermissionDto
{
@
ApiProperty
({
example
:
"1"
,
description
:
"id of permissions you want add"
})
@
IsDefined
()
@
IsInt
()
permission_id
:
number
;
@
ApiProperty
({
example
:
true
,
description
:
"Set true if you want to activate this role"
,
required
:
false
,
})
@
Transform
(({
value
})
=>
toBoolean
(
value
))
@
IsDefined
()
@
IsBoolean
()
active
?:
boolean
;
}
src/modules/users/dto/update-role.dto.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
IsString
,
IsBoolean
,
IsEnum
,
IsOptional
,
}
from
"class-validator"
;
import
{
Transform
,
Type
}
from
"class-transformer"
;
import
{
ApiProperty
}
from
"@nestjs/swagger"
;
import
{
toBoolean
}
from
"src/common/cast"
;
import
{
ROLE_ENUM
}
from
"./../../../common/constant"
;
export
class
UpdateRoleDto
{
@
ApiProperty
({
example
:
"admin"
,
description
:
"The role name"
})
@
IsOptional
()
@
IsString
()
@
IsEnum
(
ROLE_ENUM
)
name
:
ROLE_ENUM
;
@
ApiProperty
({
example
:
"admin"
,
description
:
"The role display name"
})
@
IsOptional
()
@
IsString
()
displayName
:
string
;
@
ApiProperty
({
example
:
true
,
description
:
"Set true if you want to activate this role"
,
required
:
false
,
})
@
Transform
(({
value
})
=>
toBoolean
(
value
))
@
IsOptional
()
@
IsBoolean
()
active
?:
boolean
;
}
src/modules/users/roles.controller.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
Body
,
Controller
,
Delete
,
Get
,
HttpCode
,
HttpStatus
,
Param
,
Post
,
Put
,
Query
,
UseGuards
}
from
"@nestjs/common"
;
import
{
ApiBearerAuth
,
ApiTags
}
from
"@nestjs/swagger"
;
import
{
JwtAuthGuard
}
from
"../auth/guards/jwt-auth.guard"
;
import
{
IMeta
}
from
"src/common/interfaces/IMeta"
;
import
{
CreateRoleDto
}
from
"./dto/create-role.dto"
;
import
{
RoleQueryDto
}
from
"./dto/role.query.dto"
;
import
{
Roles
}
from
"../../share/decorators/roles.decorator"
;
import
{
RolesGuard
}
from
"../../share/guards/roles.guard"
;
import
{
RolesService
}
from
"./roles.service"
;
import
{
Role
}
from
"src/database/models/role.model"
;
import
{
UpdateRoleDto
}
from
"./dto/update-role.dto"
;
import
{
UpdateRolePermissionDto
}
from
"./dto/update-role-permission.dto"
;
import
{
assignPermissionDto
}
from
"./dto/assign-permission.dto"
;
@
ApiTags
(
"roles"
)
@
ApiBearerAuth
()
@
Controller
(
"roles"
)
export
class
RolesController
{
constructor
(
private
readonly
rolesService
:
RolesService
)
{}
@
UseGuards
(
JwtAuthGuard
,
RolesGuard
)
@
Roles
(
'admin'
)
@
Get
()
@
Roles
(
"role.view"
)
@
HttpCode
(
HttpStatus
.
OK
)
async
findAll
(
@
Query
()
query
:
RoleQueryDto
):
Promise
<
{
meta
:
IMeta
;
data
:
Role
[]
}
>
{
const
data
=
await
this
.
rolesService
.
findAll
(
query
);
const
count
=
await
this
.
rolesService
.
count
(
query
);
const
{
page
,
limit
,
orderBy
,
order
}
=
query
;
return
{
meta
:
{
totalData
:
count
,
totalPage
:
Math
.
ceil
(
count
/
query
.
limit
),
page
,
limit
,
orderBy
,
order
,
},
data
,
};
}
@
UseGuards
(
JwtAuthGuard
,
RolesGuard
)
@
Roles
(
'admin'
)
@
Get
(
":id"
)
@
Roles
(
"role.view"
)
@
HttpCode
(
HttpStatus
.
OK
)
find
(@
Param
(
"id"
)
id
:
number
):
Promise
<
Role
>
{
return
this
.
rolesService
.
findOne
(
+
id
);
}
}
src/modules/users/roles.service.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
BadRequestException
,
Injectable
,
NotFoundException
}
from
"@nestjs/common"
;
import
{
InjectModel
}
from
"@nestjs/sequelize"
;
import
{
Op
}
from
"sequelize"
;
import
*
as
_
from
"lodash"
;
import
{
CreateRoleDto
}
from
"./dto/create-role.dto"
;
import
{
RoleQueryDto
}
from
"./dto/role.query.dto"
;
import
{
UsersService
}
from
"./users.service"
;
import
{
Role
}
from
"src/database/models/role.model"
;
import
{
Permission
}
from
"src/database/models/permission.model"
;
import
{
UpdateRoleDto
}
from
"./dto/update-role.dto"
;
import
{
UpdateRolePermissionDto
}
from
"./dto/update-role-permission.dto"
;
import
{
assignPermissionDto
}
from
"./dto/assign-permission.dto"
;
import
{
ROLE_ENUM
}
from
"./../../common/constant"
;
import
{
error_message
}
from
"src/common/error_message"
;
@
Injectable
()
export
class
RolesService
{
constructor
(
@
InjectModel
(
Role
)
private
readonly
roleModel
:
typeof
Role
,
@
InjectModel
(
Permission
)
private
readonly
permissionModel
:
typeof
Permission
,
private
readonly
usersService
:
UsersService
)
{
}
async
create
(
payload
:
CreateRoleDto
):
Promise
<
Role
>
{
if
(
payload
.
displayName
)
{
await
this
.
validateRole
(
payload
)
}
return
this
.
roleModel
.
create
({
name
:
payload
.
name
,
displayName
:
payload
.
displayName
,
active
:
payload
.
active
,
});
}
async
count
(
query
?:
RoleQueryDto
):
Promise
<
number
>
{
return
this
.
roleModel
.
unscoped
().
count
({
where
:
this
.
createWhere
(
query
)
});
}
findAll
(
query
?:
RoleQueryDto
):
Promise
<
Role
[]
>
{
const
{
page
,
limit
,
order
,
orderBy
}
=
query
;
return
this
.
roleModel
.
findAll
({
where
:
this
.
createWhere
(
query
),
limit
,
offset
:
(
page
-
1
)
*
limit
,
order
:
[[
orderBy
,
order
]],
});
}
async
findOne
(
id
:
number
):
Promise
<
Role
>
{
const
data
=
await
this
.
roleModel
.
findOne
({
where
:
{
id
,
},
});
if
(
!
data
)
throw
new
NotFoundException
(
error_message
.
not_found
);
return
data
;
}
private
async
validateRole
(
payload
)
{
const
whereRole
=
[];
if
(
payload
.
role
)
{
whereRole
[
0
]
=
{
id
:
{[
Op
.
ne
]:
payload
.
role
.
id
}
}
whereRole
[
1
]
=
{
displayName
:
{[
Op
.
eq
]:
payload
.
displayName
}
}
}
else
{
whereRole
[
0
]
=
{
displayName
:
{[
Op
.
eq
]:
payload
.
displayName
}
}
}
const
existRoleByName
=
await
this
.
roleModel
.
count
({
where
:
{
[
Op
.
and
]:
whereRole
,
}
});
if
(
existRoleByName
)
{
throw
new
BadRequestException
(
'Nama display role tidak boleh sama.'
);
}
}
async
update
(
id
:
number
,
payload
:
UpdateRoleDto
):
Promise
<
Role
>
{
const
role
=
await
this
.
findOne
(
id
);
if
(
!
role
)
throw
new
NotFoundException
(
"Role not found"
);
if
(
payload
.
displayName
!=
role
.
displayName
)
{
Object
.
assign
(
payload
,
{
role
:
role
})
await
this
.
validateRole
(
payload
)
}
await
role
.
update
(
payload
);
return
role
;
}
async
assignPermission
(
id
:
number
,
payload
:
assignPermissionDto
):
Promise
<
Role
>
{
const
permissionData
=
await
this
.
permissionModel
.
findAll
({
where
:
{
id
:
payload
.
permissionIds
,
superadmin
:
false
}
}).
then
((
permissions
)
=>
{
const
result
=
[];
permissions
.
forEach
(
async
permission
=>
{
result
.
push
({
permissionId
:
permission
.
id
,
roleId
:
id
})
});
return
result
;
});
return
await
this
.
findOne
(
id
);
}
async
findSuperAdmin
():
Promise
<
Role
>
{
const
superAdmin
=
await
this
.
roleModel
.
findOne
({
where
:
{
name
:
ROLE_ENUM
.
SUPERADMIN
}})
return
superAdmin
;
}
async
delete
(
id
:
number
):
Promise
<
void
>
{
// user
const
users
=
await
this
.
usersService
.
findNoScope
({
where
:
{
roleId
:
id
,
},
});
if
(
users
&&
users
.
length
)
{
throw
new
NotFoundException
(
"Role telah digunakan"
);
}
const
role
=
await
this
.
findOne
(
id
);
if
(
!
role
)
throw
new
NotFoundException
(
"Role not found"
);
await
role
.
destroy
();
}
private
createWhere
(
conditions
)
{
const
{
page
,
limit
,
order
,
orderBy
,
...
rest
}
=
conditions
;
// eslint-disable-line
const
where
=
_
.
isEmpty
(
rest
)
?
{}
:
{
[
Op
.
and
]:
{
...
rest
}
};
return
where
;
}
}
src/modules/users/users.module.ts
View file @
5152dcd0
import
{
Module
}
from
"@nestjs/common"
;
import
{
SequelizeModule
}
from
"@nestjs/sequelize"
;
import
{
Permission
}
from
"src/database/models/permission.model"
;
import
{
Role
}
from
"src/database/models/role.model"
;
import
{
User
}
from
"../../database/models/user.model"
;
import
{
RolesController
}
from
"./roles.controller"
;
import
{
RolesService
}
from
"./roles.service"
;
import
{
UsersController
}
from
"./users.controller"
;
import
{
UsersService
}
from
"./users.service"
;
import
{
IsUserEmailUniqueRule
}
from
"./validators/is_user_email_unique"
;
...
...
@@ -14,21 +10,17 @@ import { IsUserPhoneUniqueRule } from "./validators/is_user_phone_unique";
imports
:
[
SequelizeModule
.
forFeature
([
User
,
Role
,
Permission
,
])
],
providers
:
[
UsersService
,
RolesService
,
// Validator
IsUserEmailUniqueRule
,
IsUserPhoneUniqueRule
],
controllers
:
[
UsersController
,
RolesController
,
UsersController
,
],
exports
:
[
UsersService
],
})
...
...
src/modules/users/validators/is_exist_role.ts
deleted
100644 → 0
View file @
7d14eb9e
import
{
Injectable
}
from
"@nestjs/common"
;
import
{
registerDecorator
,
ValidationOptions
,
ValidatorConstraint
,
ValidatorConstraintInterface
}
from
"class-validator"
;
import
{
Role
}
from
"src/database/models/role.model"
;
@
ValidatorConstraint
({
name
:
'IsExistRole'
,
async
:
true
})
@
Injectable
()
export
class
IsExistRoleRule
implements
ValidatorConstraintInterface
{
async
validate
(
roleId
:
number
):
Promise
<
boolean
>
{
return
await
Role
.
findByPk
(
roleId
).
then
(
role
=>
{
return
role
})
!==
null
}
defaultMessage
()
{
return
`Role tidak ditemukan`
;
}
}
export
function
IsExistRole
(
validationOptions
?:
ValidationOptions
)
{
return
function
(
object
:
any
,
propertyName
:
string
)
{
registerDecorator
({
target
:
object
.
constructor
,
propertyName
:
propertyName
,
options
:
validationOptions
,
constraints
:
[],
validator
:
IsExistRoleRule
,
})
}
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment