eh-commons 0.0.1-testing.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/.eslintrc.js +25 -0
  2. package/.prettierrc +4 -0
  3. package/README.md +0 -0
  4. package/devops.md +15 -0
  5. package/dist/clients/logger.client.d.ts +10 -0
  6. package/dist/clients/logger.client.js +42 -0
  7. package/dist/clients/logger.client.js.map +1 -0
  8. package/dist/clients/session.client.d.ts +10 -0
  9. package/dist/clients/session.client.js +37 -0
  10. package/dist/clients/session.client.js.map +1 -0
  11. package/dist/constraints/is-map-of-strings.constraint.d.ts +5 -0
  12. package/dist/constraints/is-map-of-strings.constraint.js +34 -0
  13. package/dist/constraints/is-map-of-strings.constraint.js.map +1 -0
  14. package/dist/constraints/is-route.constraint.d.ts +5 -0
  15. package/dist/constraints/is-route.constraint.js +24 -0
  16. package/dist/constraints/is-route.constraint.js.map +1 -0
  17. package/dist/decorators/is-map-of-strings.decorator.d.ts +1 -0
  18. package/dist/decorators/is-map-of-strings.decorator.js +14 -0
  19. package/dist/decorators/is-map-of-strings.decorator.js.map +1 -0
  20. package/dist/decorators/is-route.decorator.d.ts +1 -0
  21. package/dist/decorators/is-route.decorator.js +12 -0
  22. package/dist/decorators/is-route.decorator.js.map +1 -0
  23. package/dist/exceptions/custom.exception.d.ts +10 -0
  24. package/dist/exceptions/custom.exception.js +18 -0
  25. package/dist/exceptions/custom.exception.js.map +1 -0
  26. package/dist/factories/exception.factory.d.ts +4 -0
  27. package/dist/factories/exception.factory.js +15 -0
  28. package/dist/factories/exception.factory.js.map +1 -0
  29. package/dist/filters/base-exception.filter.d.ts +6 -0
  30. package/dist/filters/base-exception.filter.js +113 -0
  31. package/dist/filters/base-exception.filter.js.map +1 -0
  32. package/dist/functions/escape-regex.function.d.ts +1 -0
  33. package/dist/functions/escape-regex.function.js +8 -0
  34. package/dist/functions/escape-regex.function.js.map +1 -0
  35. package/dist/functions/generate-uuid.function.d.ts +1 -0
  36. package/dist/functions/generate-uuid.function.js +12 -0
  37. package/dist/functions/generate-uuid.function.js.map +1 -0
  38. package/dist/functions/json-size.function.d.ts +1 -0
  39. package/dist/functions/json-size.function.js +10 -0
  40. package/dist/functions/json-size.function.js.map +1 -0
  41. package/dist/functions/random-range.function.d.ts +1 -0
  42. package/dist/functions/random-range.function.js +11 -0
  43. package/dist/functions/random-range.function.js.map +1 -0
  44. package/dist/functions/transliterate-geo-to-latin.d.ts +1 -0
  45. package/dist/functions/transliterate-geo-to-latin.js +46 -0
  46. package/dist/functions/transliterate-geo-to-latin.js.map +1 -0
  47. package/dist/index.d.ts +38 -0
  48. package/dist/index.js +79 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/models/dtos/record.dto.d.ts +5 -0
  51. package/dist/models/dtos/record.dto.js +28 -0
  52. package/dist/models/dtos/record.dto.js.map +1 -0
  53. package/dist/models/dtos/state-params.dto.d.ts +5 -0
  54. package/dist/models/dtos/state-params.dto.js +26 -0
  55. package/dist/models/dtos/state-params.dto.js.map +1 -0
  56. package/dist/models/embedded/address.embedded.d.ts +39 -0
  57. package/dist/models/embedded/address.embedded.js +34 -0
  58. package/dist/models/embedded/address.embedded.js.map +1 -0
  59. package/dist/models/embedded/contact.embedded.d.ts +39 -0
  60. package/dist/models/embedded/contact.embedded.js +38 -0
  61. package/dist/models/embedded/contact.embedded.js.map +1 -0
  62. package/dist/models/embedded/geo-location.embedded.d.ts +38 -0
  63. package/dist/models/embedded/geo-location.embedded.js +33 -0
  64. package/dist/models/embedded/geo-location.embedded.js.map +1 -0
  65. package/dist/models/embedded/i18n.embedded.d.ts +38 -0
  66. package/dist/models/embedded/i18n.embedded.js +33 -0
  67. package/dist/models/embedded/i18n.embedded.js.map +1 -0
  68. package/dist/models/embedded/person.embedded.d.ts +38 -0
  69. package/dist/models/embedded/person.embedded.js +33 -0
  70. package/dist/models/embedded/person.embedded.js.map +1 -0
  71. package/dist/models/embedded/record.embedded.d.ts +41 -0
  72. package/dist/models/embedded/record.embedded.js +47 -0
  73. package/dist/models/embedded/record.embedded.js.map +1 -0
  74. package/dist/models/enums/contact-type.enum.d.ts +4 -0
  75. package/dist/models/enums/contact-type.enum.js +9 -0
  76. package/dist/models/enums/contact-type.enum.js.map +1 -0
  77. package/dist/models/enums/env.enum.d.ts +5 -0
  78. package/dist/models/enums/env.enum.js +10 -0
  79. package/dist/models/enums/env.enum.js.map +1 -0
  80. package/dist/models/enums/fail-keyword.enum.d.ts +5 -0
  81. package/dist/models/enums/fail-keyword.enum.js +10 -0
  82. package/dist/models/enums/fail-keyword.enum.js.map +1 -0
  83. package/dist/models/enums/http-method.enum.d.ts +7 -0
  84. package/dist/models/enums/http-method.enum.js +12 -0
  85. package/dist/models/enums/http-method.enum.js.map +1 -0
  86. package/dist/models/enums/permission-include-strategy.enum.d.ts +5 -0
  87. package/dist/models/enums/permission-include-strategy.enum.js +10 -0
  88. package/dist/models/enums/permission-include-strategy.enum.js.map +1 -0
  89. package/dist/models/enums/record-state.enum.d.ts +5 -0
  90. package/dist/models/enums/record-state.enum.js +10 -0
  91. package/dist/models/enums/record-state.enum.js.map +1 -0
  92. package/dist/models/interfaces/address.interface.d.ts +6 -0
  93. package/dist/models/interfaces/address.interface.js +3 -0
  94. package/dist/models/interfaces/address.interface.js.map +1 -0
  95. package/dist/models/interfaces/contact.interface.d.ts +6 -0
  96. package/dist/models/interfaces/contact.interface.js +3 -0
  97. package/dist/models/interfaces/contact.interface.js.map +1 -0
  98. package/dist/models/interfaces/geo-location.interface.d.ts +5 -0
  99. package/dist/models/interfaces/geo-location.interface.js +3 -0
  100. package/dist/models/interfaces/geo-location.interface.js.map +1 -0
  101. package/dist/models/interfaces/i18n.interface.d.ts +5 -0
  102. package/dist/models/interfaces/i18n.interface.js +3 -0
  103. package/dist/models/interfaces/i18n.interface.js.map +1 -0
  104. package/dist/models/interfaces/person.interface.d.ts +5 -0
  105. package/dist/models/interfaces/person.interface.js +3 -0
  106. package/dist/models/interfaces/person.interface.js.map +1 -0
  107. package/dist/models/interfaces/record.interface.d.ts +8 -0
  108. package/dist/models/interfaces/record.interface.js +3 -0
  109. package/dist/models/interfaces/record.interface.js.map +1 -0
  110. package/dist/models/interfaces/session/session-data.interface.d.ts +11 -0
  111. package/dist/models/interfaces/session/session-data.interface.js +3 -0
  112. package/dist/models/interfaces/session/session-data.interface.js.map +1 -0
  113. package/dist/models/interfaces/session/session.interface.d.ts +8 -0
  114. package/dist/models/interfaces/session/session.interface.js +3 -0
  115. package/dist/models/interfaces/session/session.interface.js.map +1 -0
  116. package/dist/models/wrappers/client-permissions.wrapper.d.ts +4 -0
  117. package/dist/models/wrappers/client-permissions.wrapper.js +7 -0
  118. package/dist/models/wrappers/client-permissions.wrapper.js.map +1 -0
  119. package/dist/models/wrappers/permission-guard-config.wrapper.d.ts +6 -0
  120. package/dist/models/wrappers/permission-guard-config.wrapper.js +10 -0
  121. package/dist/models/wrappers/permission-guard-config.wrapper.js.map +1 -0
  122. package/dist/models/wrappers/rest-wrapper.class.d.ts +58 -0
  123. package/dist/models/wrappers/rest-wrapper.class.js +162 -0
  124. package/dist/models/wrappers/rest-wrapper.class.js.map +1 -0
  125. package/dist/modules/cache/cache.module.d.ts +2 -0
  126. package/dist/modules/cache/cache.module.js +25 -0
  127. package/dist/modules/cache/cache.module.js.map +1 -0
  128. package/dist/modules/cache/guards/permission.guard.d.ts +14 -0
  129. package/dist/modules/cache/guards/permission.guard.js +101 -0
  130. package/dist/modules/cache/guards/permission.guard.js.map +1 -0
  131. package/dist/modules/cache/reflector/permission.reflector.d.ts +2 -0
  132. package/dist/modules/cache/reflector/permission.reflector.js +6 -0
  133. package/dist/modules/cache/reflector/permission.reflector.js.map +1 -0
  134. package/dist/modules/cache/services/redis.service.d.ts +11 -0
  135. package/dist/modules/cache/services/redis.service.js +70 -0
  136. package/dist/modules/cache/services/redis.service.js.map +1 -0
  137. package/dist/modules/cache/services/session.service.d.ts +6 -0
  138. package/dist/modules/cache/services/session.service.js +27 -0
  139. package/dist/modules/cache/services/session.service.js.map +1 -0
  140. package/dist/modules/log/log.module.d.ts +2 -0
  141. package/dist/modules/log/log.module.js +23 -0
  142. package/dist/modules/log/log.module.js.map +1 -0
  143. package/dist/modules/log/services/log.service.d.ts +6 -0
  144. package/dist/modules/log/services/log.service.js +32 -0
  145. package/dist/modules/log/services/log.service.js.map +1 -0
  146. package/dist/pipes/validate-mongo-id.pipe.d.ts +4 -0
  147. package/dist/pipes/validate-mongo-id.pipe.js +28 -0
  148. package/dist/pipes/validate-mongo-id.pipe.js.map +1 -0
  149. package/dist/tsconfig.tsbuildinfo +1 -0
  150. package/dist/utils/config-util.class.d.ts +5 -0
  151. package/dist/utils/config-util.class.js +18 -0
  152. package/dist/utils/config-util.class.js.map +1 -0
  153. package/dist/utils/console-logger.class.d.ts +9 -0
  154. package/dist/utils/console-logger.class.js +39 -0
  155. package/dist/utils/console-logger.class.js.map +1 -0
  156. package/package.json +35 -0
  157. package/src/clients/logger.client.ts +57 -0
  158. package/src/clients/session.client.ts +42 -0
  159. package/src/constraints/is-map-of-strings.constraint.ts +26 -0
  160. package/src/constraints/is-route.constraint.ts +14 -0
  161. package/src/decorators/is-map-of-strings.decorator.ts +10 -0
  162. package/src/decorators/is-route.decorator.ts +8 -0
  163. package/src/exceptions/custom.exception.ts +16 -0
  164. package/src/factories/exception.factory.ts +14 -0
  165. package/src/filters/base-exception.filter.ts +192 -0
  166. package/src/functions/escape-regex.function.ts +5 -0
  167. package/src/functions/generate-uuid.function.ts +7 -0
  168. package/src/functions/json-size.function.ts +9 -0
  169. package/src/functions/random-range.function.ts +6 -0
  170. package/src/functions/transliterate-geo-to-latin.ts +42 -0
  171. package/src/index.ts +96 -0
  172. package/src/models/dtos/record.dto.ts +12 -0
  173. package/src/models/dtos/state-params.dto.ts +10 -0
  174. package/src/models/embedded/address.embedded.ts +17 -0
  175. package/src/models/embedded/contact.embedded.ts +22 -0
  176. package/src/models/embedded/geo-location.embedded.ts +17 -0
  177. package/src/models/embedded/i18n.embedded.ts +16 -0
  178. package/src/models/embedded/person.embedded.ts +16 -0
  179. package/src/models/embedded/record.embedded.ts +30 -0
  180. package/src/models/enums/contact-type.enum.ts +4 -0
  181. package/src/models/enums/env.enum.ts +5 -0
  182. package/src/models/enums/fail-keyword.enum.ts +6 -0
  183. package/src/models/enums/http-method.enum.ts +7 -0
  184. package/src/models/enums/permission-include-strategy.enum.ts +5 -0
  185. package/src/models/enums/record-state.enum.ts +5 -0
  186. package/src/models/interfaces/address.interface.ts +7 -0
  187. package/src/models/interfaces/contact.interface.ts +7 -0
  188. package/src/models/interfaces/geo-location.interface.ts +5 -0
  189. package/src/models/interfaces/i18n.interface.ts +5 -0
  190. package/src/models/interfaces/person.interface.ts +5 -0
  191. package/src/models/interfaces/record.interface.ts +9 -0
  192. package/src/models/interfaces/session/session-data.interface.ts +11 -0
  193. package/src/models/interfaces/session/session.interface.ts +9 -0
  194. package/src/models/wrappers/client-permissions.wrapper.ts +4 -0
  195. package/src/models/wrappers/permission-guard-config.wrapper.ts +7 -0
  196. package/src/models/wrappers/rest-wrapper.class.ts +172 -0
  197. package/src/modules/cache/cache.module.ts +12 -0
  198. package/src/modules/cache/guards/permission.guard.ts +166 -0
  199. package/src/modules/cache/reflector/permission.reflector.ts +4 -0
  200. package/src/modules/cache/services/redis.service.ts +37 -0
  201. package/src/modules/cache/services/session.service.ts +11 -0
  202. package/src/modules/log/log.module.ts +10 -0
  203. package/src/modules/log/services/log.service.ts +20 -0
  204. package/src/pipes/validate-mongo-id.pipe.ts +17 -0
  205. package/src/utils/config-util.class.ts +15 -0
  206. package/src/utils/console-logger.class.ts +42 -0
  207. package/tsconfig.build.json +9 -0
  208. package/tsconfig.json +26 -0
@@ -0,0 +1,10 @@
1
+ import { IsEnum, IsString } from 'class-validator';
2
+ import { RecordState } from '../enums/record-state.enum';
3
+
4
+ export class StateParamDTO {
5
+ @IsString()
6
+ id: string;
7
+
8
+ @IsEnum(RecordState)
9
+ state: RecordState;
10
+ }
@@ -0,0 +1,17 @@
1
+ import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
2
+ import { IAddress } from "../interfaces/address.interface";
3
+ import { GeoLocation } from "./geo-location.embedded";
4
+ import { HydratedDocument } from "mongoose";
5
+
6
+ @Schema({ _id: false })
7
+ export class Address implements IAddress{
8
+ @Prop({ type: String, required: false })
9
+ city: string;
10
+ @Prop({ type: String, required: false })
11
+ address: string;
12
+ @Prop({ type: GeoLocation, required: false })
13
+ location: GeoLocation;
14
+ }
15
+
16
+ export const AddressSchema = SchemaFactory.createForClass(Address);
17
+ export type AddressDocument = HydratedDocument<Address>;
@@ -0,0 +1,22 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import { ContactType } from '../enums/contact-type.enum';
3
+ import { IContact } from '../interfaces/contact.interface';
4
+ import { HydratedDocument } from 'mongoose';
5
+
6
+ @Schema({ _id: false })
7
+ export class Contact implements IContact {
8
+ @Prop({
9
+ type: String,
10
+ enum: ContactType,
11
+ required: true,
12
+ })
13
+ type: ContactType;
14
+
15
+ @Prop({ type: String, required: true })
16
+ value: string;
17
+ @Prop({ type: Boolean, required: true, default: false })
18
+ verified: boolean;
19
+ }
20
+
21
+ export const ContactSchema = SchemaFactory.createForClass(Contact);
22
+ export type ContactDocument = HydratedDocument<Contact>;
@@ -0,0 +1,17 @@
1
+ import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
2
+ import { IGeoLocation } from "../interfaces/geo-location.interface";
3
+ import { HydratedDocument } from "mongoose";
4
+
5
+
6
+ @Schema({ _id: false })
7
+ export class GeoLocation implements IGeoLocation{
8
+ @Prop({ type: Number, required: false })
9
+ lat: number;
10
+ @Prop({ type: Number, required: false })
11
+ lng: number;
12
+ @Prop({ type: String, required: false })
13
+ system: string;
14
+ }
15
+
16
+ export const GeoLocationSchema = SchemaFactory.createForClass(GeoLocation);
17
+ export type GeoLocationDocument = HydratedDocument<GeoLocation>;
@@ -0,0 +1,16 @@
1
+ import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
2
+ import { II18n } from "../interfaces/i18n.interface";
3
+ import { HydratedDocument } from "mongoose";
4
+
5
+ @Schema({ _id: false })
6
+ export class I18n implements II18n{
7
+ @Prop({ type: String, required: false })
8
+ ge: string;
9
+ @Prop({ type: String, required: false })
10
+ en: string;
11
+ @Prop({ type: String, required: false })
12
+ ua: string;
13
+ }
14
+
15
+ export const I18nSchema = SchemaFactory.createForClass(I18n);
16
+ export type I18nDocument = HydratedDocument<I18n>;
@@ -0,0 +1,16 @@
1
+ import { Prop, Schema, SchemaFactory } from "@nestjs/mongoose";
2
+ import { IPerson } from "../interfaces/person.interface";
3
+ import { HydratedDocument } from "mongoose";
4
+
5
+ @Schema({ _id: false })
6
+ export class Person implements IPerson{
7
+ @Prop({ type: String, required: false })
8
+ pid: string;
9
+ @Prop({ type: String, required: false })
10
+ firstName: string;
11
+ @Prop({ type: String, required: false })
12
+ lastName: string;
13
+ }
14
+
15
+ export const PersonSchema = SchemaFactory.createForClass(Person);
16
+ export type PersonDocument = HydratedDocument<Person>;
@@ -0,0 +1,30 @@
1
+ import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose';
2
+ import { RecordState } from '../enums/record-state.enum';
3
+ import { HydratedDocument } from 'mongoose';
4
+ import { IRecord } from '../interfaces/record.interface';
5
+
6
+ @Schema({ _id: false })
7
+ export class Record implements IRecord {
8
+ @Prop({
9
+ type: String,
10
+ enum: RecordState,
11
+ required: true,
12
+ default: RecordState.DRAFT,
13
+ })
14
+ state: RecordState;
15
+
16
+ @Prop({ type: Boolean, required: true, default: false })
17
+ deleted: boolean;
18
+
19
+ @Prop({ type: Date, required: true, default: Date.now })
20
+ createdAt: Date;
21
+
22
+ @Prop({ type: Date, required: false })
23
+ updatedAt: Date;
24
+
25
+ @Prop({ type: Date, required: false })
26
+ deletedAt: Date;
27
+ }
28
+
29
+ export const RecordSchema = SchemaFactory.createForClass(Record);
30
+ export type RecordDocument = HydratedDocument<Record>;
@@ -0,0 +1,4 @@
1
+ export enum ContactType {
2
+ EMAIL = 'email',
3
+ PHONE = 'phone',
4
+ }
@@ -0,0 +1,5 @@
1
+ export enum Env {
2
+ MAIN = 'main',
3
+ STAGING = 'staging',
4
+ TESTING = 'testing',
5
+ }
@@ -0,0 +1,6 @@
1
+ export enum FailKeywords {
2
+ SYSTEM = 'SYSTEM',
3
+ THROTTLE = 'THROTTLE',
4
+ UNKNOWN = 'UNKNOWN',
5
+ //todo add more keywords
6
+ }
@@ -0,0 +1,7 @@
1
+ export enum HTTPMethod {
2
+ POST = 'post',
3
+ GET = 'get',
4
+ PUT = 'put',
5
+ PATCH = 'patch',
6
+ DELETE = 'delete',
7
+ }
@@ -0,0 +1,5 @@
1
+ export enum PermissionsIncludeStrategy {
2
+ ONLY_CHECK = 'ONLY_CHECK',
3
+ CHECK_AND_INCLUDE_SELECTED = 'CHECK_AND_INCLUDE_SELECTED',
4
+ CHECK_AND_INCLUDE_ALL = 'CHECK_AND_INCLUDE_ALL',
5
+ }
@@ -0,0 +1,5 @@
1
+ export enum RecordState {
2
+ DRAFT = 'draft',
3
+ ACTIVE = 'active',
4
+ INACTIVE = 'inactive',
5
+ }
@@ -0,0 +1,7 @@
1
+ import { IGeoLocation } from "./geo-location.interface";
2
+
3
+ export interface IAddress{
4
+ city: string;
5
+ address: string;
6
+ location: IGeoLocation;
7
+ }
@@ -0,0 +1,7 @@
1
+ import { ContactType } from "../enums/contact-type.enum";
2
+
3
+ export interface IContact{
4
+ type: ContactType;
5
+ value: string;
6
+ verified: boolean;
7
+ }
@@ -0,0 +1,5 @@
1
+ export interface IGeoLocation{
2
+ lat: number;
3
+ lng: number;
4
+ system: string;
5
+ }
@@ -0,0 +1,5 @@
1
+ export interface II18n{
2
+ ge: string;
3
+ en: string;
4
+ ua: string;
5
+ }
@@ -0,0 +1,5 @@
1
+ export interface IPerson{
2
+ pid: string;
3
+ firstName: string;
4
+ lastName: string;
5
+ }
@@ -0,0 +1,9 @@
1
+ import { RecordState } from "../enums/record-state.enum";
2
+
3
+ export interface IRecord {
4
+ state: RecordState;
5
+ deleted: boolean;
6
+ createdAt: Date;
7
+ updatedAt: Date;
8
+ deletedAt: Date;
9
+ }
@@ -0,0 +1,11 @@
1
+ export interface ISessionUserData {
2
+ id: number;
3
+ primaryEmail: string;
4
+ primaryPhone: string;
5
+ personInfo: {
6
+ pid: string;
7
+ firstName: string;
8
+ lastName: string;
9
+ birthDate: Date;
10
+ }
11
+ }
@@ -0,0 +1,9 @@
1
+ import { ISessionUserData } from "./session-data.interface";
2
+
3
+ export interface ISession {
4
+ token: string;
5
+ userAgent: string;
6
+ createdAt: Date;
7
+ expiresAt: Date;
8
+ data: ISessionUserData
9
+ }
@@ -0,0 +1,4 @@
1
+ export class ClientPermissions {
2
+ clientId: number;
3
+ permissions: string[];
4
+ }
@@ -0,0 +1,7 @@
1
+ import { PermissionsIncludeStrategy } from '../enums/permission-include-strategy.enum';
2
+
3
+ export class PermissionGuardConfig {
4
+ appAbbr?: string = 'EH';
5
+ includeStrategy?: PermissionsIncludeStrategy;
6
+ keyword?: string;
7
+ }
@@ -0,0 +1,172 @@
1
+ import { HttpStatus } from '@nestjs/common';
2
+ import { Type } from 'class-transformer';
3
+ import { IsArray, IsEnum, IsNotEmpty, IsNumber, IsOptional, IsString, ValidateNested } from 'class-validator';
4
+
5
+ export enum SortDirection {
6
+ asc = 1,
7
+ desc = -1,
8
+ }
9
+
10
+ export abstract class RESTSort {
11
+ @IsNotEmpty()
12
+ @IsString()
13
+ property: string;
14
+
15
+ @IsNotEmpty()
16
+ @IsNumber()
17
+ @IsEnum(SortDirection)
18
+ direction: SortDirection;
19
+ }
20
+
21
+ export abstract class RESTPaging {
22
+ @IsNotEmpty()
23
+ @IsNumber()
24
+ page: number;
25
+
26
+ @IsNotEmpty()
27
+ @IsNumber()
28
+ size: number;
29
+
30
+ public extract() {
31
+ const skip = (this.page - 1) * this.size;
32
+ return { skip, limit: this.size };
33
+ }
34
+ }
35
+
36
+ export abstract class RESTRequestBody {
37
+ @IsNotEmpty()
38
+ @ValidateNested()
39
+ abstract data: any;
40
+
41
+ @IsOptional()
42
+ @ValidateNested()
43
+ @Type(() => RESTPaging)
44
+ paging: RESTPaging;
45
+
46
+ @IsOptional()
47
+ @IsArray()
48
+ @ValidateNested()
49
+ @Type(() => RESTSort)
50
+ sort: RESTSort[];
51
+
52
+ public isPagingPresent() {
53
+ if (this.paging && this.paging.page) {
54
+ return true;
55
+ } else {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ public isSortPresent() {
61
+ if (this.sort && this.sort.length) {
62
+ return true;
63
+ } else {
64
+ return false;
65
+ }
66
+ }
67
+
68
+ public extractPaging() {
69
+ if (this.isPagingPresent()) {
70
+ return this.paging.extract();
71
+ }
72
+ return null;
73
+ }
74
+
75
+ public extractSort() {
76
+ const sort = {};
77
+ if (this.isSortPresent()) {
78
+ for (let item of this.sort) {
79
+ sort[item.property] = item.direction;
80
+ }
81
+ }
82
+ return sort;
83
+ }
84
+ }
85
+
86
+ export class RESTPage {
87
+ // გვერდი
88
+ page: number;
89
+
90
+ // ჩანაწერების რაოდენობა გვერდზე
91
+ size: number;
92
+
93
+ // გვერდების ჯამური რაოდენობა
94
+ number: number;
95
+
96
+ // ჩანაწერების ჯამური რაოდენობა
97
+ total: number;
98
+
99
+ public static create(count: number, paging: RESTPaging): RESTPage {
100
+ const page = new RESTPage();
101
+ page.page = paging.page;
102
+ page.size = paging.size;
103
+ page.number = (count - (count % paging.size)) / paging.size;
104
+ if (count % paging.size > 0) {
105
+ page.number += 1;
106
+ }
107
+ page.total = count;
108
+ return page;
109
+ }
110
+ }
111
+
112
+ export class RESTResult<T> {
113
+ data: T;
114
+ page: RESTPage;
115
+ sort: RESTSort[];
116
+ }
117
+
118
+ export class RESTError {
119
+ keyword: string;
120
+ debug?: any;
121
+ validation?: any;
122
+ statusCode?: HttpStatus;
123
+
124
+ constructor(keyword: string, debug?: any) {
125
+ this.keyword = keyword;
126
+ this.debug = debug;
127
+ }
128
+
129
+ public static throw(keyword: string, statusCode?: HttpStatus, debug?: any) {
130
+ const error = new RESTError(keyword, debug);
131
+ error.statusCode = statusCode || HttpStatus.BAD_REQUEST;
132
+ throw error;
133
+ }
134
+
135
+ public static dataValidation(validation: any) {
136
+ const error = new RESTError('body_validation_error', null);
137
+ error.validation = validation;
138
+ return error;
139
+ }
140
+ }
141
+
142
+ export class RESTResponseBody<T> {
143
+ public statusCode: number;
144
+ public result: RESTResult<T>;
145
+ public errors: RESTError[];
146
+
147
+ public addError(error: RESTError): void {
148
+ if (!this.errors) {
149
+ this.errors = [];
150
+ }
151
+ this.errors.push(error);
152
+ }
153
+
154
+ public static success<T>(data: T, page?: RESTPage, sort?: RESTSort[]): RESTResponseBody<T> {
155
+ const response = new RESTResponseBody<T>();
156
+
157
+ response.statusCode = 200;
158
+ response.result = new RESTResult<T>();
159
+ response.result.data = data;
160
+ response.result.page = page;
161
+ response.result.sort = sort;
162
+
163
+ return response;
164
+ }
165
+
166
+ public static fail(errors: RESTError[], statusCode?: number): RESTResponseBody<any> {
167
+ const response = new RESTResponseBody<any>();
168
+ response.statusCode = statusCode;
169
+ response.errors = errors;
170
+ return response;
171
+ }
172
+ }
@@ -0,0 +1,12 @@
1
+ import { Module } from '@nestjs/common';
2
+ import { RedisService } from './services/redis.service';
3
+ import { SessionService } from './services/session.service';
4
+ import { PermissionGuard } from './guards/permission.guard';
5
+
6
+ @Module({
7
+ imports: [],
8
+ controllers: [],
9
+ providers: [RedisService, SessionService, PermissionGuard],
10
+ exports: [],
11
+ })
12
+ export class CacheModule {}
@@ -0,0 +1,166 @@
1
+ import {
2
+ Injectable,
3
+ CanActivate,
4
+ ExecutionContext,
5
+ HttpStatus,
6
+ } from '@nestjs/common';
7
+ import { SessionService } from '../services/session.service';
8
+ import { Reflector } from '@nestjs/core';
9
+ import { Permission } from '../reflector/permission.reflector';
10
+ import { PermissionsIncludeStrategy } from '../../../models/enums/permission-include-strategy.enum';
11
+ import { ISessionUserData } from '../../../models/interfaces/session/session-data.interface';
12
+ import { ClientPermissions } from '../../../models/wrappers/client-permissions.wrapper';
13
+ import { RESTError } from '../../../models/wrappers/rest-wrapper.class';
14
+
15
+ @Injectable()
16
+ export class PermissionGuard implements CanActivate {
17
+ constructor(
18
+ private sessionService: SessionService,
19
+ private reflector: Reflector,
20
+ ) { }
21
+
22
+ async canActivate(context: ExecutionContext): Promise<boolean> {
23
+ const config = this.reflector.get(Permission, context.getHandler());
24
+ const request = context.switchToHttp().getRequest();
25
+ const queryParameters = request.query;
26
+ const headers = request.headers;
27
+ const token: string = this.getTokenFromHeaders(headers);
28
+ if (!token) RESTError.throw('unauthorized', HttpStatus.UNAUTHORIZED);
29
+
30
+ const userData = {};
31
+ // await this.sessionService.getUserByToken(token);
32
+ if (!userData) {
33
+ RESTError.throw('unauthorized', HttpStatus.UNAUTHORIZED);
34
+ return false;
35
+ }
36
+ const abbr = config.appAbbr;
37
+ const clientId: number = this.getClientIdFromQuery(queryParameters);
38
+ let clientPermissionsArray: ClientPermissions[];
39
+ switch (config.includeStrategy) {
40
+ case PermissionsIncludeStrategy.ONLY_CHECK:
41
+ break;
42
+ case PermissionsIncludeStrategy.CHECK_AND_INCLUDE_ALL:
43
+ // clientPermissionsArray = await this.getAllClientPermissions(
44
+ // userData,
45
+ // abbr,
46
+ // );
47
+ break;
48
+ case PermissionsIncludeStrategy.CHECK_AND_INCLUDE_SELECTED:
49
+ if (!clientId) {
50
+ RESTError.throw('CLIENT_ID_REQUIRED', HttpStatus.FORBIDDEN);
51
+ }
52
+ // clientPermissionsArray = await this.getSelectedClientPermissions(
53
+ // clientId,
54
+ // userData,
55
+ // abbr,
56
+ // );
57
+ break;
58
+ }
59
+
60
+ // this.setUserData(userData, clientPermissionsArray, request);
61
+
62
+ if (config.includeStrategy) {
63
+ if (!clientId) {
64
+ RESTError.throw('CLIENT_ID_REQUIRED', HttpStatus.FORBIDDEN);
65
+ }
66
+ if (!clientPermissionsArray || clientPermissionsArray.length <= 0) {
67
+ // clientPermissionsArray = await this.getSelectedClientPermissions(
68
+ // clientId,
69
+ // userData,
70
+ // abbr,
71
+ // );
72
+ }
73
+ const selectedPermissions = clientPermissionsArray.find(
74
+ (clientPermissions) => clientPermissions.clientId === clientId,
75
+ );
76
+ return this.checkPerrmission(
77
+ ((selectedPermissions || {}).permissions || []),
78
+ config.keyword,
79
+ );
80
+ } else {
81
+ return true;
82
+ }
83
+ }
84
+
85
+ private getTokenFromHeaders(headers: any) {
86
+ let token = headers.authorization;
87
+ if (token) {
88
+ token = token.replace('bearer ', '');
89
+ token = token.replace('Bearer ', '');
90
+ }
91
+ return token;
92
+ }
93
+
94
+ private getClientIdFromQuery(queryParameters: any) {
95
+ return +queryParameters.clientId;
96
+ }
97
+
98
+ private getPermissionAbbr(inputString: string): string {
99
+ const parts: string[] = inputString.split('.');
100
+ if (parts.length > 1) {
101
+ return parts[0];
102
+ } else {
103
+ return inputString;
104
+ }
105
+ }
106
+
107
+ private checkPerrmission(
108
+ userPermissions: string[],
109
+ allowedPermission: string,
110
+ ): boolean {
111
+ return !allowedPermission || userPermissions.includes(allowedPermission);
112
+ }
113
+
114
+ // private async getAllClientPermissions(
115
+ // userData: ISessionUserData,
116
+ // abbr: string,
117
+ // ) {
118
+ // const clients = await this.sessionService.getUserClientsById(userData.id);
119
+ // let permissionPromises: {
120
+ // clientId: number;
121
+ // promise: Promise<string[]>;
122
+ // }[] = [];
123
+ // clients.forEach((client) => {
124
+ // const permissions = this.sessionService.getUserPermissions(
125
+ // userData.id,
126
+ // client,
127
+ // abbr,
128
+ // );
129
+ // permissionPromises.push({ clientId: client, promise: permissions });
130
+ // });
131
+ // const results = await Promise.all(
132
+ // permissionPromises.map(({ promise }) => promise),
133
+ // );
134
+
135
+ // const combinedResults = permissionPromises.map(({ clientId }, index) => ({
136
+ // clientId,
137
+ // permissions: results[index],
138
+ // }));
139
+ // return combinedResults;
140
+ // }
141
+
142
+ // private async getSelectedClientPermissions(
143
+ // clientId: number,
144
+ // userData: ISessionUserData,
145
+ // abbr: string,
146
+ // ) {
147
+ // const userPermissions = await this.sessionService.getUserPermissions(
148
+ // userData.id,
149
+ // clientId,
150
+ // abbr,
151
+ // );
152
+ // return [{ clientId, permissions: userPermissions }];
153
+ // }
154
+
155
+ private setUserData(
156
+ userData: ISessionUserData,
157
+ clientPermissions: ClientPermissions[],
158
+ request: Request,
159
+ ) {
160
+ const userInfo = {
161
+ ...userData,
162
+ clientPermissions,
163
+ };
164
+ request['user'] = userInfo;
165
+ }
166
+ }
@@ -0,0 +1,4 @@
1
+ import { Reflector } from '@nestjs/core';
2
+ import { PermissionGuardConfig } from '../../../models/wrappers/permission-guard-config.wrapper';
3
+
4
+ export const Permission = Reflector.createDecorator<PermissionGuardConfig>();
@@ -0,0 +1,37 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { ConfigService } from '@nestjs/config';
3
+ import * as IORedis from 'ioredis';
4
+
5
+ @Injectable()
6
+ export class RedisService {
7
+ private client: IORedis.Redis;
8
+
9
+ constructor(private configService: ConfigService) {
10
+ const redisConnectionString = this.configService.get(
11
+ 'REDIS__CONNECTION_STRING',
12
+ );
13
+ this.client = new IORedis.Redis(redisConnectionString);
14
+ }
15
+
16
+ async set(key: string, value: string, ttl?: number): Promise<string> {
17
+ let result: string | PromiseLike<string>;
18
+ if (ttl) {
19
+ result = await this.client.set(key, value, 'EX', ttl);
20
+ } else {
21
+ result = await this.client.set(key, value);
22
+ }
23
+ return result;
24
+ }
25
+
26
+ async get(key: string): Promise<string> {
27
+ return await this.client.get(key);
28
+ }
29
+
30
+ async del(key: string): Promise<number> {
31
+ return await this.client.del(key);
32
+ }
33
+
34
+ getRedisClient() {
35
+ return this.client;
36
+ }
37
+ }
@@ -0,0 +1,11 @@
1
+ import { Injectable } from '@nestjs/common';
2
+ import { RedisService } from './redis.service';
3
+ import { SessionClient } from '../../../clients/session.client';
4
+
5
+ @Injectable()
6
+ export class SessionService {
7
+ private sessionClient: SessionClient;
8
+ constructor(private redisService: RedisService) {
9
+ this.sessionClient = new SessionClient(this.redisService.getRedisClient());
10
+ }
11
+ }