Skip to content

Commit 2f2ac7b

Browse files
api key add start date and end date (expiration), add endpoint update name, add endpoint update date, make difference port and port expose for docker
1 parent f552eef commit 2f2ac7b

27 files changed

+629
-44
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ DEBUGGER_HTTP_WRITE_INTO_CONSOLE=false
1313
DEBUGGER_SYSTEM_WRITE_INTO_FILE=true
1414
DEBUGGER_SYSTEM_WRITE_INTO_CONSOLE=true
1515

16-
JOB_ENABLE=false
16+
JOB_ENABLE=true
1717

1818
DATABASE_HOST=mongodb://localhost:30001,localhost:30002,localhost:30003
1919
DATABASE_NAME=ack

.github/workflows/cd.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ jobs:
1515
env:
1616
APP_NAME: ${{ github.event.repository.name }}
1717
APP_PORT: 3000
18+
APP_PORT_EXPOSE: 3000
1819
APP_NETWORK: app-network
1920

2021
steps:
@@ -58,7 +59,7 @@ jobs:
5859
docker network create ${{ env.APP_NETWORK }} --driver=bridge
5960
docker run -itd \
6061
--hostname ${{ env.APP_NAME}} \
61-
--publish ${{ env.APP_PORT }}:${{ env.APP_PORT }} \
62+
--publish ${{ env.APP_PORT_EXPOSE }}:${{ env.APP_PORT }} \
6263
--network ${{ env.APP_NETWORK }} \
6364
--volume /app/${{ env.APP_NAME}}/logs/:/app/logs/ \
6465
--volume /app/${{ env.APP_NAME}}/.env:/app/.env \

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ Next development
8888
* [x] Fix automation testing
8989
* [x] Pagination move from decorator to service pagination -> make pipe transformer -> wrap into group decorator ResponsePaging
9090
* [x] Check Swagger for pagination
91+
* [x] ApiKey add startDate and endDate
92+
* [x] Make docker port expose be difference with port app
9193
* [ ] SSO
9294
* [ ] Google
9395
* [ ] Apple
@@ -465,7 +467,6 @@ If your code behind commit with the original, please update your code and resolv
465467

466468
[![Github][github-shield]][author-github]
467469
[![LinkedIn][linkedin-shield]][author-linkedin]
468-
[![Instagram][instagram-shield]][author-instagram]
469470

470471
<!-- BADGE LINKS -->
471472
[ack-contributors-shield]: https://img.shields.io/github/contributors/andrechristikan/ack-nestjs-boilerplate?style=for-the-badge
@@ -485,11 +486,9 @@ If your code behind commit with the original, please update your code and resolv
485486

486487
[github-shield]: https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white
487488
[linkedin-shield]: https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white
488-
[instagram-shield]: https://img.shields.io/badge/Instagram-E4405F?style=for-the-badge&logo=instagram&logoColor=white
489489

490490
<!-- CONTACTS -->
491491
[author-linkedin]: https://linkedin.com/in/andrechristikan
492-
[author-instagram]: https://www.instagram.com/___ac.k
493492
[author-email]: mailto:[email protected]
494493
[author-github]: https://github.com/andrechristikan
495494

@@ -510,7 +509,6 @@ If your code behind commit with the original, please update your code and resolv
510509

511510
<!-- Reference -->
512511
[ref-nestjs]: http://nestjs.com
513-
[ref-nestjs-cqrs]: https://docs.nestjs.com/recipes/cqrs
514512
[ref-mongoose]: https://mongoosejs.com
515513
[ref-mongodb]: https://docs.mongodb.com/
516514
[ref-nodejs]: https://nodejs.org/

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ack-nestjs-boilerplate",
3-
"version": "4.0.3",
3+
"version": "4.1.0",
44
"description": "Ack NestJs Boilerplate",
55
"repository": {
66
"type": "git",

scripts/jenkinsfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pipeline {
99
APP_NAME = 'ack' // this will be container name
1010
APP_NETWORK = 'app-network' // this network name
1111
APP_PORT = 3000 // this project will serve in port 0.0.0.0:3000
12+
APP_EXPOSE_PORT = 3000 // this project will expose at port 0.0.0.0:3000
1213

1314
NODE_JS = 'lts' // depends with our jenkins setting
1415

@@ -184,7 +185,7 @@ pipeline {
184185

185186
sshCommand remote: remote, command: "docker run -itd \
186187
--hostname ${APP_NAME} \
187-
--publish ${APP_PORT}:${APP_PORT} \
188+
--publish ${APP_EXPOSE_PORT}:${APP_PORT} \
188189
--network ${APP_NETWORK} \
189190
--volume /app/${APP_NAME}/logs/:/app/logs/ \
190191
--volume /app/${APP_NAME}/.env:/app/.env \

src/common/api-key/constants/api-key.status-code.constant.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@ export enum ENUM_API_KEY_STATUS_CODE_ERROR {
22
API_KEY_NEEDED_ERROR = 5120,
33
API_KEY_NOT_FOUND_ERROR = 5121,
44
API_KEY_IS_ACTIVE_ERROR = 5122,
5-
API_KEY_INACTIVE_ERROR = 5123,
6-
API_KEY_INVALID_ERROR = 5124,
7-
API_KEY_PREFIX_INVALID_ERROR = 5125,
8-
API_KEY_WRONG_ERROR = 5126,
5+
API_KEY_EXPIRED_ERROR = 5123,
6+
API_KEY_INACTIVE_ERROR = 5124,
7+
API_KEY_INVALID_ERROR = 5125,
8+
API_KEY_PREFIX_INVALID_ERROR = 5126,
9+
API_KEY_WRONG_ERROR = 5127,
910
}

src/common/api-key/controllers/api-key.admin.controller.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import {
1818
import {
1919
ApiKeyGetGuard,
2020
ApiKeyUpdateActiveGuard,
21+
ApiKeyUpdateGuard,
2122
ApiKeyUpdateInactiveGuard,
2223
ApiKeyUpdateResetGuard,
2324
} from 'src/common/api-key/decorators/api-key.admin.decorator';
@@ -29,9 +30,12 @@ import {
2930
ApiKeyInactiveDoc,
3031
ApiKeyListDoc,
3132
ApiKeyResetDoc,
33+
ApiKeyUpdateDoc,
3234
} from 'src/common/api-key/docs/api-key.admin.doc';
3335
import { ApiKeyCreateDto } from 'src/common/api-key/dtos/api-key.create.dto';
3436
import { ApiKeyRequestDto } from 'src/common/api-key/dtos/api-key.request.dto';
37+
import { ApiKeyUpdateDateDto } from 'src/common/api-key/dtos/api-key.update-date.dto';
38+
import { ApiKeyUpdateNameDto } from 'src/common/api-key/dtos/api-key.update-name.dto';
3539
import { IApiKeyEntity } from 'src/common/api-key/interfaces/api-key.interface';
3640
import { ApiKeyEntity } from 'src/common/api-key/repository/entities/api-key.entity';
3741
import { ApiKeyCreateSerialization } from 'src/common/api-key/serializations/api-key.create.serialization';
@@ -58,6 +62,7 @@ import {
5862
IResponse,
5963
IResponsePaging,
6064
} from 'src/common/response/interfaces/response.interface';
65+
import { ResponseIdSerialization } from 'src/common/response/serializations/response.id.serialization';
6166

6267
@ApiTags('admin.apiKey')
6368
@Controller({
@@ -225,7 +230,7 @@ export class ApiKeyAdminController {
225230
ENUM_AUTH_PERMISSIONS.API_KEY_RESET
226231
)
227232
@AuthJwtAdminAccessProtected()
228-
@Put('/update/:apiKey/reset')
233+
@Patch('/update/:apiKey/reset')
229234
async reset(@GetApiKey() apiKey: ApiKeyEntity): Promise<IResponse> {
230235
try {
231236
const updated: IApiKeyEntity = await this.apiKeyService.reset(
@@ -245,4 +250,59 @@ export class ApiKeyAdminController {
245250
});
246251
}
247252
}
253+
254+
@ApiKeyUpdateDoc()
255+
@Response('apiKey.update', { serialization: ResponseIdSerialization })
256+
@ApiKeyUpdateGuard()
257+
@RequestParamGuard(ApiKeyRequestDto)
258+
@AuthPermissionProtected(
259+
ENUM_AUTH_PERMISSIONS.API_KEY_READ,
260+
ENUM_AUTH_PERMISSIONS.API_KEY_UPDATE
261+
)
262+
@AuthJwtAdminAccessProtected()
263+
@Put('/update/:apiKey')
264+
async updateName(
265+
@Body() body: ApiKeyUpdateNameDto,
266+
@GetApiKey() apiKey: ApiKeyEntity
267+
): Promise<IResponse> {
268+
try {
269+
await this.apiKeyService.updateName(apiKey._id, body);
270+
} catch (err: any) {
271+
throw new InternalServerErrorException({
272+
statusCode: ENUM_ERROR_STATUS_CODE_ERROR.ERROR_UNKNOWN,
273+
message: 'http.serverError.internalServerError',
274+
error: err.message,
275+
});
276+
}
277+
278+
return { _id: apiKey._id };
279+
}
280+
281+
@ApiKeyUpdateDoc()
282+
@Response('apiKey.updateDate', { serialization: ResponseIdSerialization })
283+
@ApiKeyUpdateGuard()
284+
@RequestParamGuard(ApiKeyRequestDto)
285+
@AuthPermissionProtected(
286+
ENUM_AUTH_PERMISSIONS.API_KEY_READ,
287+
ENUM_AUTH_PERMISSIONS.API_KEY_UPDATE,
288+
ENUM_AUTH_PERMISSIONS.API_KEY_UPDATE_DATE
289+
)
290+
@AuthJwtAdminAccessProtected()
291+
@Put('/update/:apiKey/date')
292+
async updateDate(
293+
@Body() body: ApiKeyUpdateDateDto,
294+
@GetApiKey() apiKey: ApiKeyEntity
295+
): Promise<IResponse> {
296+
try {
297+
await this.apiKeyService.updateDate(apiKey._id, body);
298+
} catch (err: any) {
299+
throw new InternalServerErrorException({
300+
statusCode: ENUM_ERROR_STATUS_CODE_ERROR.ERROR_UNKNOWN,
301+
message: 'http.serverError.internalServerError',
302+
error: err.message,
303+
});
304+
}
305+
306+
return { _id: apiKey._id };
307+
}
248308
}

src/common/api-key/decorators/api-key.admin.decorator.ts

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common';
22
import { API_KEY_ACTIVE_META_KEY } from 'src/common/api-key/constants/api-key.constant';
33
import { ApiKeyActiveGuard } from 'src/common/api-key/guards/api-key.active.guard';
4+
import { ApiKeyExpiredGuard } from 'src/common/api-key/guards/api-key.expired.guard';
45
import { ApiKeyNotFoundGuard } from 'src/common/api-key/guards/api-key.not-found.guard';
56
import { ApiKeyPutToRequestGuard } from 'src/common/api-key/guards/api-key.put-to-request.guard';
67

@@ -10,12 +11,25 @@ export function ApiKeyGetGuard(): MethodDecorator {
1011
);
1112
}
1213

14+
export function ApiKeyUpdateGuard(): MethodDecorator {
15+
return applyDecorators(
16+
UseGuards(
17+
ApiKeyPutToRequestGuard,
18+
ApiKeyNotFoundGuard,
19+
ApiKeyActiveGuard,
20+
ApiKeyExpiredGuard
21+
),
22+
SetMetadata(API_KEY_ACTIVE_META_KEY, [true])
23+
);
24+
}
25+
1326
export function ApiKeyUpdateResetGuard(): MethodDecorator {
1427
return applyDecorators(
1528
UseGuards(
1629
ApiKeyPutToRequestGuard,
1730
ApiKeyNotFoundGuard,
18-
ApiKeyActiveGuard
31+
ApiKeyActiveGuard,
32+
ApiKeyExpiredGuard
1933
),
2034
SetMetadata(API_KEY_ACTIVE_META_KEY, [true])
2135
);
@@ -26,7 +40,8 @@ export function ApiKeyUpdateActiveGuard(): MethodDecorator {
2640
UseGuards(
2741
ApiKeyPutToRequestGuard,
2842
ApiKeyNotFoundGuard,
29-
ApiKeyActiveGuard
43+
ApiKeyActiveGuard,
44+
ApiKeyExpiredGuard
3045
),
3146
SetMetadata(API_KEY_ACTIVE_META_KEY, [false])
3247
);
@@ -37,7 +52,8 @@ export function ApiKeyUpdateInactiveGuard(): MethodDecorator {
3752
UseGuards(
3853
ApiKeyPutToRequestGuard,
3954
ApiKeyNotFoundGuard,
40-
ApiKeyActiveGuard
55+
ApiKeyActiveGuard,
56+
ApiKeyExpiredGuard
4157
),
4258
SetMetadata(API_KEY_ACTIVE_META_KEY, [true])
4359
);

src/common/api-key/docs/api-key.admin.doc.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { ApiKeyCreateSerialization } from 'src/common/api-key/serializations/api
1111
import { ApiKeyGetSerialization } from 'src/common/api-key/serializations/api-key.get.serialization';
1212
import { ApiKeyListSerialization } from 'src/common/api-key/serializations/api-key.list.serialization';
1313
import { Doc, DocPaging } from 'src/common/doc/decorators/doc.decorator';
14+
import { ResponseIdSerialization } from 'src/common/response/serializations/response.id.serialization';
1415

1516
export function ApiKeyListDoc(): MethodDecorator {
1617
return applyDecorators(
@@ -99,3 +100,19 @@ export function ApiKeyResetDoc(): MethodDecorator {
99100
})
100101
);
101102
}
103+
104+
export function ApiKeyUpdateDoc(): MethodDecorator {
105+
return applyDecorators(
106+
Doc<ResponseIdSerialization>('apiKey.update', {
107+
auth: {
108+
jwtAccessToken: true,
109+
},
110+
request: {
111+
params: ApiKeyDocParamsGet,
112+
},
113+
response: {
114+
serialization: ResponseIdSerialization,
115+
},
116+
})
117+
);
118+
}

src/common/api-key/dtos/api-key.create.dto.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
import { faker } from '@faker-js/faker';
12
import { ApiProperty, PartialType } from '@nestjs/swagger';
2-
import { IsNotEmpty, IsOptional, IsString, MaxLength } from 'class-validator';
3+
import { Type } from 'class-transformer';
4+
import {
5+
IsDate,
6+
IsNotEmpty,
7+
IsOptional,
8+
IsString,
9+
MaxLength,
10+
} from 'class-validator';
311

412
export class ApiKeyCreateDto {
513
@ApiProperty({
@@ -12,6 +20,28 @@ export class ApiKeyCreateDto {
1220
@MaxLength(50)
1321
name: string;
1422

23+
@ApiProperty({
24+
description: 'Api Key start date',
25+
example: faker.date.recent(),
26+
required: false,
27+
nullable: true,
28+
})
29+
@IsOptional()
30+
@Type(() => Date)
31+
@IsDate()
32+
startDate?: Date;
33+
34+
@ApiProperty({
35+
description: 'Api Key end date',
36+
example: faker.date.recent(),
37+
required: false,
38+
nullable: true,
39+
})
40+
@IsOptional()
41+
@Type(() => Date)
42+
@IsDate()
43+
endDate?: Date;
44+
1545
@ApiProperty({
1646
description: 'Description of api key',
1747
example: 'blabla description',

0 commit comments

Comments
 (0)