Merge branch 'dev' into notifications

This commit is contained in:
Vins 2023-09-07 11:20:00 +02:00
commit c2431bace6
82 changed files with 2592 additions and 883 deletions

View File

@ -21,8 +21,8 @@ jobs:
version: 20.10.12
docker_layer_caching: true
- run: docker login rg.fr-par.scw.cloud/lecoffre -u nologin -p $SCW_SECRET_KEY
- run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:$TAG .
- run: docker push rg.fr-par.scw.cloud/lecoffre/back:$TAG
- run: docker build --tag rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7} .
- run: docker push rg.fr-par.scw.cloud/lecoffre/back:${CIRCLE_SHA1:0:7}
deploy-docker-image:
@ -30,6 +30,10 @@ jobs:
- image: cimg/base:stable
environment:
TAG: << pipeline.git.tag >>
parameters:
env:
type: string
default: stg
steps:
- checkout
- kubernetes/install-kubeconfig:
@ -39,31 +43,63 @@ jobs:
name: Deploy
command: >
helm upgrade
lecoffre-back devops/ -i -f devops/values.yaml
-n lecoffre
lecoffre-back devops/ -i -f devops/<<parameters.env>>.values.yaml
-n lecoffre-<<parameters.env>>
--create-namespace
--set lecoffreBack.image.repository='rg.fr-par.scw.cloud/lecoffre/back'
--set lecoffreBack.image.tag=$TAG
--set lecoffreBack.image.tag=${CIRCLE_SHA1:0:7}
--set lecoffreCron.image.repository='rg.fr-par.scw.cloud/lecoffre/back'
--set lecoffreCron.image.tag=${CIRCLE_SHA1:0:7}
workflows:
version: 2
build-and-register:
build-and-register-stg:
jobs:
- build-push-docker-image:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
only: staging
- deploy-docker-image:
env: stg
requires:
- build-push-docker-image
context:
- staging
- sc-shared-prd
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
only: staging
build-and-register-ppd:
jobs:
- build-push-docker-image:
filters:
branches:
only: preprod
- deploy-docker-image:
env: ppd
requires:
- build-push-docker-image
context:
- sc-shared-prd
filters:
branches:
only: preprod
build-and-register-prd:
jobs:
- build-push-docker-image:
filters:
branches:
only: main
- deploy-docker-image:
env: prd
requires:
- build-push-docker-image
context:
- sc-shared-prd
filters:
branches:
only: main

View File

@ -21,5 +21,5 @@ version: 0.0.1
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: 0.5.6
appVersion: 0.5.7

54
devops/ppd.values.yaml Normal file
View File

@ -0,0 +1,54 @@
dockerPullSecret: docker-pull-secret
scwSecretKey: AgCgjF5QEzxT3GYTS5B6cmQ0e+0/qFWzKaUDSi+Vjc7RoameuvaIJvTXMBkS3he1oy1ulbB34v6vpZI2kxnGNqERA/U5BaYDAyfKSBwMAy4br7HVKhhuwkoF5qoG5JzJXseSmqB1U9vncVIGOZWzJc1Y4/eGlWcvLcLyfw2z/WEpyeNiWJfEhTYpJOB7gv0XnRb2U/JM3jRy1QgEUIk1WR6kgBalF+xaczPQ6uKh+PR2pqkbZa3WaKUrddmzNsgEz4d8PZMWt8IBwR2JOQEHUqCd34p/pJNyLdUgcdDhg02DKwn1oRoAxKTbAio/a7WrMbodjCb3TNWIYGal5mFmItZ7Ok/EBmUf4E85eOkTR+j8ynuuiexld3Q5Kw3o8LsHjgzVL9uP+T2rYaKkjtVt+YQRX1U8l9CrsdUEz0/wEBA0jwCWMfnh1qhD5pM/xwwjsEEAcK4rYV+Q7iAgGZZvZBCQ5aEHzrtn5D95tr1GZCV2hmrW6Seu+LKKLVBS1JmsuEsOuhudYsEK9m2RYVcxbjuS5eokKEjNrGobf2oB8rhBByavfw1JTBixR5JrI8lcYlnCa+oEhxXKJY+4Fx5SAB4YaLCMSo5vw6zsFQ3WKQzlEmCFt+EnapS+a+MGrdlwq07OHTDpvgk/1z39hopoCuhhKckGGfErLXsTYQvDOkFu+EPzgY7m7qDw/d9pSiht5tuSOkAqeOgm7tpNkUufZhaXmP+1aT7i+H5gq1JILGAmXzTI5Wc=
lecoffreBack:
serviceAccountName: lecoffre-back-sa
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run api:start'"
envSecrets: ppd-env
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
ingress:
host: api.stg.lecoffre.smart-chain.fr
tls:
hosts:
- api.stg.lecoffre.smart-chain.fr
secretName: api-tls
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
env:
- key: .env
scwID: "id:a131edea-84e0-49d6-b4a8-20ab417220c9"
lecoffreCron:
serviceAccountName: lecoffre-cron-sa
envSecrets: stg-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run cron'"
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
# key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front
env:
- key: .env
scwID: "id:2be9510b-bb1f-4fbe-ab3e-3dc11fb49051"

54
devops/prd.values.yaml Normal file
View File

@ -0,0 +1,54 @@
dockerPullSecret: docker-pull-secret
scwSecretKey: AgBG2y7uQuap+2akNPGFxpCR+l0INO6Wxez5qljtY6t71GFGhJLYN9ZfefflKcFzD2Nv7DQMXXhpnCCaFti+9JMCMDuN324dDgtMMLTot+Pkxk/bAm+L8t3HfRharFdLz/vvzg77bvypi28TEoNYR/AM0e8VMYxBEgEp2TmP5uXcxZOgPzXMrfQoSdNRyzGTJ5tXZwe3PP7XvXyTNsZzHBtoQQM+nul9nL+VFA7CBRaaOpCmKOXjAlt7TyNXo4X5eYBNlxr+NuQw4dh4E/1zqdU/dDCE1+vx88BDbdydBA1qJaTOUSGTFquSK4kb9qAVAexBAIUqRwpfEW6Li945AXtnxLN42gEGPRsA9tSXL2c20k6thuRCqxwEOZljq2E03qtLAkxdP6WFBcb77o4PIEMZ8AmzPASnI+eW5z2mCoP3L+HZQrTLliDjmF4AMtOfZxRi0CCTrsSabOrimJC6v3y3ve0VcSsjA3rd5vvJ3Va4mZK4JAtYwEUx4PCHCGkUxc0w6jRwKB5tL/auZVT4SV/0z/WgW4Kq4AdvxsU6yGOqflt6e3ePIIuvCgjw+1yOYRpUiSGj36oOqNPMA4smxIB7p7Gi3csqt2TrQoW3TaLv/s7gbCcxHWSor+WT71WGg8AVmLm+FzUINmNop+c2RNo3O/Gj7h1uybX/pj+tRLNOuBQCqa+GQkY2bT2NcT9ifnAZB6K+2zAWXl+tdbMlDGV89P2yMYuRMdHGhuOoyuIUPWeA5i0=
lecoffreBack:
serviceAccountName: lecoffre-back-sa
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run api:start'"
envSecrets: prd-env
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
ingress:
host: api.stg.lecoffre.smart-chain.fr
tls:
hosts:
- api.stg.lecoffre.smart-chain.fr
secretName: api-tls
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
env:
- key: .env
scwID: "id:a131edea-84e0-49d6-b4a8-20ab417220c9"
lecoffreCron:
serviceAccountName: lecoffre-cron-sa
envSecrets: stg-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run cron'"
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
# key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front
env:
- key: .env
scwID: "id:2be9510b-bb1f-4fbe-ab3e-3dc11fb49051"

56
devops/stg.values.yaml Normal file
View File

@ -0,0 +1,56 @@
dockerPullSecret: id:47c1c301-1f02-49cc-9e5c-c1225a770aa8
scwSecretKey: AgChoEnPitXp4Ny/rVMEcevaWKNVpyj2cJYAcq+yFqKwVwnLB+ffDvwqz9XBHu+6d4Nyyjkf37zUAMoaM21lEDWA7x3zfG2/D/j+rvX1qxzZgLD0mjBk7fGElVm332I6JA83oInes8AMMYEDPLElzHnpKRb9KtkIP4NzgOcCeW0ijft3N7Vroez6LEHsBPCA1I9XjKSkGEDvrO0MhWX3iJOlfz+SPMfJAV7rPawOs0ZmohTHrPW8qIvGDn8HCzKyU8zRBoMt+Ogpf5pH4U3JryEFuqD61KAQgablAM8edPIvsgNno9HAEuC2QtRLYA9aUhuKdaKuS58c9P2E80PHWXIlbpFCg6EugQTgNfnYp+3qDUNz8edeCfapYLvF4s9eCMGyMsGnpDR8EDNOyuGy7Y3l7okX8Xqu464gMp9E+hX7bHkcD6a4xfyIgJcWxsku0tm1TH1dpn4M1UXRuyZZif8P08nuE6MTUL67sAR9J1lpn4lVEL4kflk0pP2tZ5ncgPQFafJrRz05krMb0eU5tb2H4gs7ao/LL6idWo8MM9K1yr8lIuT5x2WW5CX+RjA+i50ex114V6vX3PNP5oVyt+DynTUB9QmXzVm3oLfDc3Cae1uqh7X0CFd+xiztJBtg0VtJaD/xUJcuWfY4cV2lERo9fRrykltzlJqiXHO4nowt8OtN0BcViVV8NJhPhYFzyb4ympxpOlTjm3GETuT2TYhUqdgS9nzleEAbOmOHZdIO2COunPE=
lecoffreBack:
serviceAccountName: lecoffre-back-sa
envSecrets: stg-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run api:start'"
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
ingress:
host: api.stg.lecoffre.smart-chain.fr
tls:
hosts:
- api.stg.lecoffre.smart-chain.fr
secretName: api-tls
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
# key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front
env:
- key: .env
scwID: "id:2be9510b-bb1f-4fbe-ab3e-3dc11fb49051"
lecoffreCron:
serviceAccountName: lecoffre-cron-sa
envSecrets: stg-env
command: "'sh', '-c', 'export $(xargs </etc/env/.env) && npm run cron'"
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
resources:
requests:
cpu: 200m
memory: 1Gi
limits:
memory: 2Gi
# key is name of the environment variable, scwID is the secret ID in SCW with "id:" in front
env:
- key: .env
scwID: "id:2be9510b-bb1f-4fbe-ab3e-3dc11fb49051"

View File

@ -5,8 +5,8 @@ metadata:
spec:
refreshInterval: 1h
secretStoreRef:
name: dockerpullsecret-vault-cluster-secret-store
kind: ClusterSecretStore
name: secret-store
kind: SecretStore
target:
template:
type: kubernetes.io/dockerconfigjson
@ -16,4 +16,4 @@ spec:
- secretKey: .dockerconfigjson
remoteRef:
key: {{ .Values.dockerPullSecret }}
property: .dockerconfigjson
version: latest_enabled

View File

@ -3,7 +3,6 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lecoffre-back
namespace: {{ .Values.namespace }}
{{if .Values.lecoffreBack.ingress.annotations}}
annotations:
{{toYaml .Values.lecoffreBack.ingress.annotations | indent 4 }}
@ -28,7 +27,6 @@ apiVersion: v1
kind: Service
metadata:
name: lecoffre-back-svc
namespace: {{ .Values.namespace }}
labels:
spec:
ports:
@ -42,7 +40,6 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: lecoffre-back
namespace: {{ .Values.namespace }}
labels:
app: lecoffre-back
spec:
@ -53,7 +50,6 @@ spec:
template:
metadata:
annotations:
{{toYaml .Values.lecoffreBack.vault.annotations | indent 8 }}
labels:
app: lecoffre-back
spec:
@ -62,10 +58,17 @@ spec:
- name: docker-pull-secret
containers:
- name: lecoffre-back
image: "{{ .Values.lecoffreBack.image.repository }}:v{{ .Chart.AppVersion }}"
image: "{{ .Values.lecoffreBack.image.repository }}:{{ .Values.lecoffreBack.image.tag }}"
{{if .Values.lecoffreBack.resources}}
resources:
{{toYaml .Values.lecoffreBack.resources | indent 10}}
{{end}}
imagePullPolicy: {{ .Values.lecoffreBack.image.pullPolicy }}
command: [{{ .Values.lecoffreBack.command }}]
command: [{{ .Values.lecoffreBack.command }}]
volumeMounts:
- name: secret-volume
mountPath: /etc/env
volumes:
- name: secret-volume
secret:
secretName: {{ .Values.lecoffreBack.envSecrets }}

View File

@ -0,0 +1,37 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lecoffre-cron
labels:
app: lecoffre-cron
spec:
replicas: 1
selector:
matchLabels:
app: lecoffre-cron
template:
metadata:
annotations:
labels:
app: lecoffre-cron
spec:
serviceAccountName: {{ .Values.lecoffreCron.serviceAccountName }}
imagePullSecrets:
- name: docker-pull-secret
containers:
- name: lecoffre-cron
image: "{{ .Values.lecoffreCron.image.repository }}:{{ .Values.lecoffreCron.image.tag }}"
{{if .Values.lecoffreCron.resources}}
resources:
{{toYaml .Values.lecoffreCron.resources | indent 10}}
{{end}}
imagePullPolicy: {{ .Values.lecoffreCron.image.pullPolicy }}
command: [{{ .Values.lecoffreCron.command }}]
volumeMounts:
- name: secret-volume
mountPath: /etc/env
volumes:
- name: secret-volume
secret:
secretName: {{ .Values.lecoffreCron.envSecrets }}

View File

@ -0,0 +1,12 @@
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
creationTimestamp: null
name: scw-secret-key
spec:
encryptedData:
SCW_SECRET_KEY: {{ .Values.scwSecretKey }}
template:
metadata:
creationTimestamp: null
name: scw-secret-key

View File

@ -0,0 +1,15 @@
apiVersion: external-secrets.io/v1beta1
kind: SecretStore
metadata:
name: secret-store
spec:
provider:
scaleway:
region: fr-par
projectId: c0ed1e9e-d945-461f-920c-98c844ef1ad4
accessKey:
value: SCWNCSH22EMVGT3MNX09
secretKey:
secretRef:
name: scw-secret-key
key: SCW_SECRET_KEY

View File

@ -0,0 +1,16 @@
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: {{ .Values.lecoffreBack.envSecrets }}
spec:
refreshInterval: 1h
secretStoreRef:
kind: SecretStore
name: secret-store
data:
{{ range $v := .Values.lecoffreBack.env }}
- secretKey: {{ $v.key }}
remoteRef:
key: {{ $v.scwID}}
version: latest_enabled
{{ end }}

View File

@ -11,4 +11,20 @@ metadata:
name: {{ .Values.lecoffreBack.serviceAccountName }}-token
annotations:
kubernetes.io/service-account.name: {{ .Values.lecoffreBack.serviceAccountName }}
type: kubernetes.io/service-account-token
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ .Values.lecoffreCron.serviceAccountName }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ .Values.lecoffreCron.serviceAccountName }}-token
annotations:
kubernetes.io/service-account.name: {{ .Values.lecoffreCron.serviceAccountName }}
type: kubernetes.io/service-account-token

View File

@ -1,29 +1,17 @@
dockerPullSecret: secret/data/minteed-stg/config/dockerpullsecret
dockerPullSecret: docker-pull-secret
namespace: lecoffre
scwSecretKey: ss
lecoffreBack:
serviceAccountName: lecoffre-back-sa
command: "'sh', '-c', '. /vault/secrets/envs-api && npm run api:start'"
vault:
role : custom_lecoffre-back_injector_rol
server: https://vault-stg.smart-chain.fr
annotations:
vault.hashicorp.com/agent-pre-populate-only: "true"
vault.hashicorp.com/agent-inject: "true"
vault.hashicorp.com/agent-inject-secret-envs-api: secret/data/lecoffre-back-stg/config/envs-api
vault.hashicorp.com/role: custom_lecoffre-back_injector_rol
vault.hashicorp.com/agent-inject-template-envs-api: |
{{ with secret "secret/data/lecoffre-back-stg/config/envs-api" }}
{{ range $k, $v := .Data.data }}
export {{ $k }}="{{ $v }}"
{{ end }}
{{ end }}
command: "npm run api:start"
envSecrets: env-env
imagePullSecrets:
- name: docker-pull-secret
image:
pullPolicy: Always
repository: "rg.fr-par.scw.cloud/lecoffre/back"
tag:
resources:
requests:
cpu: 200m
@ -41,4 +29,8 @@ lecoffreBack:
cert-manager.io/cluster-issuer: letsencrypt-prod
nginx.ingress.kubernetes.io/from-to-www-redirect: "true"
nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
env:
- key: a
scwID: b

1302
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -52,7 +52,7 @@
"cron": "^2.3.1",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.63",
"le-coffre-resources": "git@github.com:smart-chain-fr/leCoffre-resources.git#v2.71",
"module-alias": "^2.2.2",
"multer": "^1.4.5-lts.1",
"next": "^13.1.5",

View File

@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/Admin";
import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -18,7 +19,7 @@ export default class CustomersController extends ApiController {
/**
* @description Get all customers
*/
@Get("/api/v1/admin/customers", [authHandler, ruleHandler])
@Get("/api/v1/admin/customers", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -70,7 +71,7 @@ export default class CustomersController extends ApiController {
/**
* @description Modify a specific customer by uid
*/
@Put("/api/v1/admin/customers/:uid", [authHandler, ruleHandler])
@Put("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -111,7 +112,7 @@ export default class CustomersController extends ApiController {
/**
* @description Get a specific customer by uid
*/
@Get("/api/v1/admin/customers/:uid", [authHandler, ruleHandler])
@Get("/api/v1/admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController {
* @description Get all deedtypes
* @returns Deedtype[] list of deedtypes
*/
@Get("/api/v1/admin/deed-types", [authHandler, ruleHandler])
@Get("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -65,14 +66,19 @@ export default class DeedTypesController extends ApiController {
* @description Create a new deedtype
* @returns Deedtype created
*/
@Post("/api/v1/admin/deed-types", [authHandler, ruleHandler, deedTypeHandler])
@Post("/api/v1/admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async post(req: Request, response: Response) {
try {
//init DeedType resource with request body values
const deedTypeEntity = DeedType.hydrate<DeedType>(req.body);
//validate deed type
//validate deed type
await validateOrReject(deedTypeEntity, { groups: ["createDeedType"], forbidUnknownValues: false });
const doesExist = await this.deedTypesService.get({ where: { name: deedTypeEntity.name } });
if (doesExist.length > 0) {
this.httpBadRequest(response, "Deed type name already used");
return;
}
//call service to get prisma entity
const deedTypeEntityCreated = await this.deedTypesService.create(deedTypeEntity);
@ -84,7 +90,7 @@ export default class DeedTypesController extends ApiController {
//success
this.httpCreated(response, deedType);
} catch (error) {
} catch (error) {
this.httpInternalError(response, error);
return;
}
@ -94,7 +100,7 @@ export default class DeedTypesController extends ApiController {
* @description Modify a specific deedtype by uid
* @returns Deedtype modified
*/
@Put("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler])
@Put("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -136,7 +142,7 @@ export default class DeedTypesController extends ApiController {
* @description Get a specific deedtype by uid
* @returns IDeedtype
*/
@Get("/api/v1/admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler])
@Get("/api/v1/admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DeedsController extends ApiController {
* @description Get all deeds
* @returns Deed[] list of deeds
*/
@Get("/api/v1/admin/deeds", [authHandler, ruleHandler])
@Get("/api/v1/admin/deeds", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -52,7 +53,7 @@ export default class DeedsController extends ApiController {
* @description Get a specific deed by uid
* @returns Deed
*/
@Get("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler])
@Get("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -87,7 +88,7 @@ export default class DeedsController extends ApiController {
/**
* @description Modify a specific deed by uid
*/
@Put("/api/v1/admin/deeds/:uid", [authHandler, ruleHandler, deedHandler])
@Put("/api/v1/admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Get all document-types
*/
@Get("/api/v1/admin/document-types", [authHandler, ruleHandler])
@Get("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -53,7 +54,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Create a new documentType
*/
@Post("/api/v1/admin/document-types", [authHandler, ruleHandler, documentTypeHandler])
@Post("/api/v1/admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler])
protected async post(req: Request, response: Response) {
try {
//init DocumentType resource with request body values
@ -77,7 +78,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Modify a specific documentType by uid
*/
@Put("/api/v1/admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler])
@Put("/api/v1/admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController {
* @description Get all documents
* @returns IDocument[] list of documents
*/
@Get("/api/v1/admin/documents", [authHandler, ruleHandler])
@Get("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -52,7 +53,7 @@ export default class DocumentsController extends ApiController {
* @description Create a new document
* @returns IDocument created
*/
@Post("/api/v1/admin/documents", [authHandler, ruleHandler, documentHandler])
@Post("/api/v1/admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async post(req: Request, response: Response) {
try {
//init Document resource with request body values
@ -80,7 +81,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Update a specific document
*/
@Put("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Put("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async update(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -119,7 +120,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Delete a specific document
*/
@Delete("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Delete("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -152,7 +153,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Get a specific document by uid
*/
@Get("/api/v1/admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Get("/api/v1/admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/Admin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class FilesController extends ApiController {
* @description Get all Files
* @returns File[] list of Files
*/
@Get("/api/v1/admin/files", [authHandler, ruleHandler])
@Get("/api/v1/admin/files", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -49,7 +50,7 @@ export default class FilesController extends ApiController {
/**
* @description Get a specific File by uid
*/
@Get("/api/v1/admin/files/download/:uid", [authHandler, ruleHandler, fileHandler])
@Get("/api/v1/admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async download(req: Request, response: Response) {
const uid = req.params["uid"];
if (!uid) {
@ -77,7 +78,7 @@ export default class FilesController extends ApiController {
/**
* @description Delete a specific File
*/
@Delete("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler])
@Delete("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -115,7 +116,7 @@ export default class FilesController extends ApiController {
/**
* @description Get a specific File by uid
*/
@Get("/api/v1/admin/files/:uid", [authHandler, ruleHandler, fileHandler])
@Get("/api/v1/admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Get all folders
*/
@Get("/api/v1/admin/folders", [authHandler, ruleHandler])
@Get("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -80,7 +81,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Create a new folder
*/
@Post("/api/v1/admin/folders", [authHandler, ruleHandler, folderHandler])
@Post("/api/v1/admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async post(req: Request, response: Response) {
try {
//init OfficeFolder resource with request body values
@ -104,7 +105,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Modify a specific folder by uid
*/
@Put("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Put("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -146,7 +147,7 @@ export default class OfficeFoldersController extends ApiController {
* @description Get a specific folder by uid
* @returns IFolder
*/
@Get("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Get("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -182,7 +183,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Delete a specific folder
*/
@Delete("/api/v1/admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Delete("/api/v1/admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Get all officeRoles
*/
@Get("/api/v1/admin/office-roles", [authHandler, ruleHandler])
@Get("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -63,7 +64,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Create a new officeRole
*/
@Post("/api/v1/admin/office-roles", [authHandler, ruleHandler, officeRoleHandler])
@Post("/api/v1/admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async getAddresses(req: Request, response: Response) {
try {
//init IOfficeRole resource with request body values
@ -91,7 +92,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Modify a specific officeRole by uid
*/
@Put("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler])
@Put("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -132,7 +133,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Get a specific officeRole by uid
*/
@Get("/api/v1/admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler])
@Get("/api/v1/admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -7,6 +7,7 @@ import { Offices } from "@prisma/client";
import { Office as OfficeResource } from "le-coffre-resources/dist/Admin";
import ruleHandler from "@App/middlewares/RulesHandler";
import authHandler from "@App/middlewares/AuthHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -17,7 +18,7 @@ export default class OfficesController extends ApiController {
/**
* @description Get all offices
*/
@Get("/api/v1/admin/offices", [authHandler, ruleHandler])
@Get("/api/v1/admin/offices", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -40,7 +41,7 @@ export default class OfficesController extends ApiController {
/**
* @description Get a specific office by uid
*/
@Get("/api/v1/admin/offices/:uid", [authHandler, ruleHandler])
@Get("/api/v1/admin/offices/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -6,6 +6,7 @@ import { Service } from "typedi";
import { Role } from "le-coffre-resources/dist/Admin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -17,7 +18,7 @@ export default class RolesController extends ApiController {
/**
* @description Get all roles
*/
@Get("/api/v1/admin/roles", [authHandler, ruleHandler])
@Get("/api/v1/admin/roles", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -43,7 +44,7 @@ export default class RolesController extends ApiController {
/**
* @description Get a specific role by uid
*/
@Get("/api/v1/admin/roles/:uid", [authHandler, ruleHandler])
@Get("/api/v1/admin/roles/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -6,6 +6,7 @@ import { Service } from "typedi";
import { Rule } from "le-coffre-resources/dist/Admin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -17,7 +18,7 @@ export default class RulesController extends ApiController {
/**
* @description Get all rules
*/
@Get("/api/v1/admin/rules", [authHandler, ruleHandler])
@Get("/api/v1/admin/rules", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -43,7 +44,7 @@ export default class RulesController extends ApiController {
/**
* @description Get a specific rule by uid
*/
@Get("/api/v1/admin/rules/:uid", [authHandler, ruleHandler])
@Get("/api/v1/admin/rules/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -8,19 +8,21 @@ import { Prisma } from "@prisma/client";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import userHandler from "@App/middlewares/OfficeMembershipHandlers/UserHandler";
import { validateOrReject } from "class-validator";
import roleHandler from "@App/middlewares/RolesHandler";
import RolesService from "@Services/admin/RolesService/RolesService";
import OfficeRolesService from "@Services/admin/OfficeRolesService/OfficeRolesService";
@Controller()
@Service()
export default class UsersController extends ApiController {
constructor(private usersService: UsersService) {
constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) {
super();
}
/**
* @description Get all users
*/
@Get("/api/v1/admin/users", [authHandler, ruleHandler])
@Get("/api/v1/admin/users", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -65,7 +67,7 @@ export default class UsersController extends ApiController {
/**
* @description Modify a specific user by uid
*/
@Put("/api/v1/admin/users/:uid", [authHandler, ruleHandler])
@Put("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -74,7 +76,7 @@ export default class UsersController extends ApiController {
return;
}
const userFound = await this.usersService.getByUid(uid);
const userFound = await this.usersService.getByUidWithRole(uid);
if (!userFound) {
this.httpNotFoundRequest(response, "user not found");
@ -84,9 +86,29 @@ export default class UsersController extends ApiController {
//init IUser resource with request body values
const userEntity = User.hydrate<User>(req.body);
//validate user
await validateOrReject(userEntity, { groups: ["updateUser"] });
if(userEntity.role) {
const role = await this.roleService.getByUid(userEntity.role.uid!);
if(!role) {
this.httpBadRequest(response, "Role not found");
return;
}
if (role.name === "super-admin" || userFound.role.name === "super-admin" ) {
this.httpBadRequest(response, "Cannot assign or remove super-admin role");
return;
}
}
if(userEntity.office_role) {
const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!);
if(!officeRole) {
this.httpBadRequest(response, "Office role not found");
return;
}
if (officeRole.office_uid != userFound.office_uid) {
this.httpBadRequest(response, "Cannot assign an office role from another office");
return;
}
}
//call service to get prisma entity
const userEntityUpdated = await this.usersService.update(uid, userEntity);
@ -106,7 +128,7 @@ export default class UsersController extends ApiController {
/**
* @description Get a specific user by uid
*/
@Get("/api/v1/admin/users/:uid", [authHandler, ruleHandler, userHandler])
@Get("/api/v1/admin/users/:uid", [authHandler, roleHandler, ruleHandler, userHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -0,0 +1,79 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import CustomersService from "@Services/customer/CustomersService/CustomersService";
import { Service } from "typedi";
import Customer from "le-coffre-resources/dist/Customer";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
@Controller()
@Service()
export default class CustomersController extends ApiController {
constructor(private customersService: CustomersService) {
super();
}
/**
* @description Get all customers
*/
@Get("/api/v1/customer/customers")
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const customersEntities = await this.customersService.get(query);
//Hydrate ressource with prisma entity
const customers = Customer.hydrateArray<Customer>(customersEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, customers);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific customer by uid
*/
@Get("/api/v1/customer/customers/:uid", [authHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const customerEntity = await this.customersService.getByUid(uid, query);
if (!customerEntity) {
this.httpNotFoundRequest(response, "customer not found");
return;
}
//Hydrate ressource with prisma entity
const customer = Customer.hydrate<Customer>(customerEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, customer);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -1,5 +1,5 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import { Controller, Get, Post } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
@ -7,6 +7,7 @@ import { Documents, Prisma } from "@prisma/client";
import { Document } from "le-coffre-resources/dist/Customer";
import authHandler from "@App/middlewares/AuthHandler";
import documentHandler from "@App/middlewares/CustomerHandler/DocumentHandler";
import { validateOrReject } from "class-validator";
@Controller()
@Service()
@ -27,12 +28,15 @@ export default class DocumentsController extends ApiController {
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const customerId: string = req.body.user.customerId;
const customerWhereInput: Prisma.DocumentsWhereInput ={ depositor: { uid: customerId } };
query.where = customerWhereInput;
//call service to get prisma entity
const documentEntities: Documents[] = await this.documentsService.get(query);
//Hydrate ressource with prisma entity
const documents = Document.hydrateArray<Document>(documentEntities, { strategy: "excludeAll" });
@ -79,4 +83,35 @@ export default class DocumentsController extends ApiController {
return;
}
}
/**
* @description Create a new File
* @returns File created
*/
@Post("/api/v1/customer/documents", [authHandler])
protected async post(req: Request, response: Response) {
try {
//init Document resource with request body values
const documentEntity = Document.hydrate<Document>(req.body);
console.log(documentEntity);
//validate document
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
//call service to get prisma entity
const documentEntityCreated = await this.documentsService.create(documentEntity);
//Hydrate ressource with prisma entity
const document = Document.hydrate<Document>(documentEntityCreated, {
strategy: "excludeAll",
});
//success
this.httpCreated(response, document);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -10,11 +10,14 @@ import { validateOrReject } from "class-validator";
import DocumentsService from "@Services/customer/DocumentsService/DocumentsService";
import authHandler from "@App/middlewares/AuthHandler";
import fileHandler from "@App/middlewares/CustomerHandler/FileHandler";
import DocumentTypesService from "@Services/super-admin/DocumentTypesService/DocumentTypesService";
import { DocumentType } from "le-coffre-resources/dist/SuperAdmin";
import ObjectHydrate from "@Common/helpers/ObjectHydrate";
@Controller()
@Service()
export default class FilesController extends ApiController {
constructor(private filesService: FilesService, private documentService: DocumentsService) {
constructor(private filesService: FilesService, private documentService: DocumentsService, private documentTypesService : DocumentTypesService) {
super();
}
@ -87,9 +90,10 @@ export default class FilesController extends ApiController {
//init File resource with request body values
const fileEntity = File.hydrate<File>(JSON.parse(req.body["q"]));
console.log(fileEntity);
//validate File
await validateOrReject(fileEntity, { groups: ["createFile"] });
// await validateOrReject(fileEntity, { groups: ["createFile"] });
//call service to get prisma entity
const fileEntityCreated = await this.filesService.create(fileEntity, req.file);
@ -135,9 +139,6 @@ export default class FilesController extends ApiController {
//init File resource with request body values
const fileEntity = File.hydrate<File>(req.body);
//validate file
await validateOrReject(fileEntity, { groups: ["updateFile"] });
//call service to get prisma entity
const fileEntityUpdated: Files = await this.filesService.update(uid, fileEntity);
@ -224,4 +225,52 @@ export default class FilesController extends ApiController {
return;
}
}
/**
* @description Create a new File
* @returns File created
*/
@Post("/api/v1/customer/addPersonalFile", [authHandler, fileHandler])
protected async addPersonalFile(req: Request, response: Response) {
try {
//get file
if (!req.file) throw new Error("No file provided");
//init File resource with request body values
const fileEntity = File.hydrate<File>(JSON.parse(req.body["q"]));
const documentTypeEntities = await this.documentTypesService.get({ where: { name: "Other"} });
const documentTypeEntity = documentTypeEntities[0];
const documentType = ObjectHydrate.hydrate<DocumentType>(new DocumentType(), documentTypeEntity!, { strategy: "excludeAll" });
const documentEntity = Document.hydrate<Document>({document_type: documentType});
await validateOrReject(documentEntity, { groups: ["createDocument"], forbidUnknownValues: false });
const documentEntityCreated = await this.documentService.create(documentEntity);
const document = Document.hydrate<Document>(documentEntityCreated, {
strategy: "excludeAll",
});
fileEntity.document = document;
const fileEntityCreated = await this.filesService.create(fileEntity, req.file);
const documentToUpdate = Document.hydrate<Document>(document!);
documentToUpdate!.document_status = "DEPOSITED";
await this.documentService.update(document!.uid!, documentToUpdate);
//Hydrate ressource with prisma entity
const fileEntityHydrated = File.hydrate<File>(fileEntityCreated, {
strategy: "excludeAll",
});
//success
this.httpCreated(response, fileEntityHydrated);
} catch (error) {
this.httpBadRequest(response, error);
return;
}
}
}

View File

@ -0,0 +1,113 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import OfficeFoldersService from "@Services/customer/OfficeFoldersService/OfficeFoldersService";
import { Service } from "typedi";
import { OfficeFolders, Prisma } from "@prisma/client";
import { OfficeFolder } from "le-coffre-resources/dist/Customer";
// import authHandler from "@App/middlewares/AuthHandler";
// import ruleHandler from "@App/middlewares/RulesHandler";
// import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler";
@Controller()
@Service()
export default class OfficeFoldersController extends ApiController {
constructor(private officeFoldersService: OfficeFoldersService) {
super();
}
/**
* @description Get all folders
*/
@Get("/api/v1/customer/folders")
protected async get(req: Request, response: Response) {
try {
//get query
let query: Prisma.OfficeFoldersFindManyArgs = {};
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
if (req.query["search"] && typeof req.query["search"] === "string") {
const filter = req.query["search"];
query = {
where: {
OR: [
{
name: { contains: filter, mode: "insensitive" },
},
{
folder_number: { contains: filter, mode: "insensitive" },
},
{
customers: {
some: {
contact: {
OR: [
{ first_name: { contains: filter, mode: "insensitive" } },
{ last_name: { contains: filter, mode: "insensitive" } },
],
},
},
},
},
],
},
};
}
const officeWhereInput: Prisma.OfficesWhereInput = {};
if (!query.where) query.where = { office: officeWhereInput };
query.where.office = officeWhereInput;
//call service to get prisma entity
const officeFolderEntities: OfficeFolders[] = await this.officeFoldersService.get(query);
//Hydrate ressource with prisma entity
const officeFolders = OfficeFolder.hydrateArray<OfficeFolder>(officeFolderEntities, {
strategy: "excludeAll",
});
//success
this.httpSuccess(response, officeFolders);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific folder by uid
* @returns IFolder
*/
@Get("/api/v1/customer/folders/:uid")
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const officeFolderEntity = await this.officeFoldersService.getByUid(uid, query);
if (!officeFolderEntity) {
this.httpNotFoundRequest(response, "folder not found");
return;
}
//Hydrate ressource with prisma entity
const officeFolder = OfficeFolder.hydrate<OfficeFolder>(officeFolderEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, officeFolder);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -18,10 +18,9 @@ export default class CustomerController extends ApiController {
const email = req.params["email"];
if (!email) throw new Error("email is required");
const payload = await this.authService.getCustomerJwtPayload(email);
const payload = await this.authService.getCustomerJwtPayload(email);
const accessToken = this.authService.generateAccessToken(payload);
const refreshToken = this.authService.generateRefreshToken(payload);
const refreshToken = this.authService.generateRefreshToken(payload);
//success
this.httpSuccess(response, { accessToken, refreshToken });
} catch (error) {

View File

@ -42,13 +42,14 @@ export default class UserController extends ApiController {
const id = req.params["idnot"];
if (!id) throw new Error("idnot is required");
const payload = await this.authService.getUserJwtPayload(id!);
const payload = await this.authService.getUserJwtPayload(id);
const accessToken = this.authService.generateAccessToken(payload);
const refreshToken = this.authService.generateRefreshToken(payload);
//success
this.httpSuccess(response, { accessToken, refreshToken });
} catch (error) {
console.log(error);
this.httpInternalError(response);
return;
}

View File

@ -175,7 +175,6 @@ export default class OfficeFoldersController extends ApiController {
this.httpInternalError(response, error);
return;
}
this.httpSuccess(response, await this.officeFoldersService.getByUid("uid"));
}
/**

View File

@ -0,0 +1,77 @@
import { Response, Request } from "express";
import { Controller, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import AppointmentsService from "@Services/super-admin/AppointmentsService/AppointmentsService";
import { Service } from "typedi";
import { Appointment } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
export default class AppointmentsController extends ApiController {
constructor(private appointmentsService: AppointmentsService) {
super();
}
/**
* @description Get all appointments
*/
@Get("/api/v1/super-admin/appointments", [authHandler, roleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const appointmentsEntities = await this.appointmentsService.get(query);
//Hydrate ressource with prisma entity
const appointments = Appointment.hydrateArray<Appointment>(appointmentsEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, appointments);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific appointment by uid
*/
@Get("/api/v1/super-admin/appointments/:uid", [authHandler, roleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const appointmentEntity = await this.appointmentsService.getByUid(uid, query);
if (!appointmentEntity) {
this.httpNotFoundRequest(response, "appointment not found");
return;
}
//Hydrate ressource with prisma entity
const appointment = Appointment.hydrate<Appointment>(appointmentEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, appointment);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -7,6 +7,7 @@ import { Customer } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -18,7 +19,7 @@ export default class CustomersController extends ApiController {
/**
* @description Get all customers
*/
@Get("/api/v1/super-admin/customers", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -44,7 +45,7 @@ export default class CustomersController extends ApiController {
/**
* @description Create a new customer
*/
@Post("/api/v1/super-admin/customers", [authHandler, ruleHandler])
@Post("/api/v1/super-admin/customers", [authHandler, roleHandler, ruleHandler])
protected async post(req: Request, response: Response) {
try {
//init IUser resource with request body values
@ -70,7 +71,7 @@ export default class CustomersController extends ApiController {
/**
* @description Modify a specific customer by uid
*/
@Put("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler])
@Put("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -111,7 +112,7 @@ export default class CustomersController extends ApiController {
/**
* @description Get a specific customer by uid
*/
@Get("/api/v1/super-admin/customers/:uid", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/customers/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import deedTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DeedTypeHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DeedTypesController extends ApiController {
* @description Get all deedtypes
* @returns Deedtype[] list of deedtypes
*/
@Get("/api/v1/super-admin/deed-types", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -65,7 +66,7 @@ export default class DeedTypesController extends ApiController {
* @description Create a new deedtype
* @returns Deedtype created
*/
@Post("/api/v1/super-admin/deed-types", [authHandler, ruleHandler, deedTypeHandler])
@Post("/api/v1/super-admin/deed-types", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async post(req: Request, response: Response) {
try {
//init DeedType resource with request body values
@ -94,7 +95,7 @@ export default class DeedTypesController extends ApiController {
* @description Modify a specific deedtype by uid
* @returns Deedtype modified
*/
@Put("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler])
@Put("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -136,7 +137,7 @@ export default class DeedTypesController extends ApiController {
* @description Get a specific deedtype by uid
* @returns IDeedtype
*/
@Get("/api/v1/super-admin/deed-types/:uid", [authHandler, ruleHandler, deedTypeHandler])
@Get("/api/v1/super-admin/deed-types/:uid", [authHandler, roleHandler, ruleHandler, deedTypeHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import deedHandler from "@App/middlewares/OfficeMembershipHandlers/DeedHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DeedsController extends ApiController {
* @description Get all deeds
* @returns Deed[] list of deeds
*/
@Get("/api/v1/super-admin/deeds", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/deeds", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -52,7 +53,7 @@ export default class DeedsController extends ApiController {
* @description Get a specific deed by uid
* @returns Deed
*/
@Get("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler])
@Get("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -87,7 +88,7 @@ export default class DeedsController extends ApiController {
/**
* @description Modify a specific deed by uid
*/
@Put("/api/v1/super-admin/deeds/:uid", [authHandler, ruleHandler, deedHandler])
@Put("/api/v1/super-admin/deeds/:uid", [authHandler, roleHandler, ruleHandler, deedHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -10,6 +10,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import documentTypeHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentTypeHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Get all document-types
*/
@Get("/api/v1/super-admin/document-types", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -53,11 +54,16 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Create a new documentType
*/
@Post("/api/v1/super-admin/document-types", [authHandler, ruleHandler, documentTypeHandler])
@Post("/api/v1/super-admin/document-types", [authHandler, roleHandler, ruleHandler, documentTypeHandler])
protected async post(req: Request, response: Response) {
try {
//init DocumentType resource with request body values
const documentTypeEntity = DocumentType.hydrate<DocumentType>(req.body);
const doesExist = await this.documentTypesService.get({ where: { name: documentTypeEntity.name } });
if (doesExist.length > 0) {
this.httpBadRequest(response, "Document type name already used");
return;
}
//validate user
await validateOrReject(documentTypeEntity, { groups: ["createDocumentType"], forbidUnknownValues: false });
//call service to get prisma entity
@ -77,7 +83,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Modify a specific documentType by uid
*/
@Put("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler])
@Put("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -117,7 +123,7 @@ export default class DocumentTypesController extends ApiController {
/**
* @description Get a specific documentType by uid
*/
@Get("/api/v1/super-admin/document-types/:uid", [authHandler, ruleHandler, documentTypeHandler])
@Get("/api/v1/super-admin/document-types/:uid", [authHandler, roleHandler, ruleHandler, documentTypeHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -1,14 +1,15 @@
import { Response, Request } from "express";
import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Service } from "typedi";
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import { Documents, Prisma } from "@prisma/client";
import { Document } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import documentHandler from "@App/middlewares/OfficeMembershipHandlers/DocumentHandler";
import roleHandler from "@App/middlewares/RolesHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Controller, Delete, Get, Post, Put } from "@ControllerPattern/index";
import { Documents, Prisma } from "@prisma/client";
import DocumentsService from "@Services/super-admin/DocumentsService/DocumentsService";
import { validateOrReject } from "class-validator";
import { Request, Response } from "express";
import { Document } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Controller()
@Service()
@ -21,7 +22,7 @@ export default class DocumentsController extends ApiController {
* @description Get all documents
* @returns IDocument[] list of documents
*/
@Get("/api/v1/super-admin/documents", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -30,12 +31,16 @@ export default class DocumentsController extends ApiController {
query = JSON.parse(req.query["q"] as string);
}
const officeId: string = req.body.user.office_Id;
const officeWhereInput: Prisma.OfficesWhereInput = { uid: officeId } ;
if(!query.where) query.where = { document_type : {office: officeWhereInput}};
query.where.document_type!.office = officeWhereInput;
// query.where.document_type!.office = officeWhereInput;
//call service to get prisma entity
const documentEntities = await this.documentsService.get(query);
const documentEntities = await this.documentsService.get(query);
//Hydrate ressource with prisma entity
const documents = Document.hydrateArray<Document>(documentEntities, { strategy: "excludeAll" });
@ -52,7 +57,7 @@ export default class DocumentsController extends ApiController {
* @description Create a new document
* @returns IDocument created
*/
@Post("/api/v1/super-admin/documents", [authHandler, ruleHandler, documentHandler])
@Post("/api/v1/super-admin/documents", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async post(req: Request, response: Response) {
try {
//init Document resource with request body values
@ -80,7 +85,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Update a specific document
*/
@Put("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Put("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async update(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -119,7 +124,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Delete a specific document
*/
@Delete("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Delete("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -152,7 +157,7 @@ export default class DocumentsController extends ApiController {
/**
* @description Get a specific document by uid
*/
@Get("/api/v1/super-admin/documents/:uid", [authHandler, ruleHandler, documentHandler])
@Get("/api/v1/super-admin/documents/:uid", [authHandler, roleHandler, ruleHandler, documentHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -8,6 +8,7 @@ import { File } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import fileHandler from "@App/middlewares/OfficeMembershipHandlers/FileHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class FilesController extends ApiController {
* @description Get all Files
* @returns File[] list of Files
*/
@Get("/api/v1/super-admin/files", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/files", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -50,7 +51,7 @@ export default class FilesController extends ApiController {
/**
* @description Get a specific File by uid
*/
@Get("/api/v1/super-admin/files/download/:uid", [authHandler, ruleHandler, fileHandler])
@Get("/api/v1/super-admin/files/download/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async download(req: Request, response: Response) {
const uid = req.params["uid"];
if (!uid) {
@ -78,7 +79,7 @@ export default class FilesController extends ApiController {
/**
* @description Delete a specific File
*/
@Delete("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler])
@Delete("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -116,7 +117,7 @@ export default class FilesController extends ApiController {
/**
* @description Get a specific File by uid
*/
@Get("/api/v1/super-admin/files/:uid", [authHandler, ruleHandler, fileHandler])
@Get("/api/v1/super-admin/files/:uid", [authHandler, roleHandler, ruleHandler, fileHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -0,0 +1,95 @@
import authHandler from "@App/middlewares/AuthHandler";
import roleHandler from "@App/middlewares/RolesHandler";
import ApiController from "@Common/system/controller-pattern/ApiController";
import { Controller, Post } from "@ControllerPattern/index";
import { EAppointmentStatus } from "@prisma/client";
import AppointmentService from "@Services/super-admin/AppointmentsService/AppointmentsService";
import LiveVoteService from "@Services/super-admin/LiveVoteService/LiveVoteService";
import UsersService from "@Services/super-admin/UsersService/UsersService";
import VotesService from "@Services/super-admin/VotesService/VotesService";
import { validateOrReject } from "class-validator";
import { Request, Response } from "express";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Controller()
@Service()
export default class LiveVoteController extends ApiController {
constructor(
private liveVoteService: LiveVoteService,
private votesService: VotesService,
private usersService: UsersService,
private appointmentService: AppointmentService,
) {
super();
}
/**
* @description Create a new vote
*/
@Post("/api/v1/super-admin/live-votes", [authHandler, roleHandler])
protected async post(req: Request, response: Response) {
try {
const userId = req.body.user.userId;
//init IUser resource with request body values
const voteEntity = Vote.hydrate<Vote>(req.body);
//validate user
await validateOrReject(voteEntity, { groups: ["createVote"] });
let voteFound = [];
if (voteEntity.appointment.uid) {
const appointment = await this.appointmentService.getByUid(voteEntity.appointment.uid);
if (!appointment) {
this.httpNotFoundRequest(response, "Appointment not found");
return;
}
if (appointment.status === EAppointmentStatus.CLOSED) {
this.httpBadRequest(response, "Appointment is closed");
return;
}
voteFound = await this.votesService.get({
where: { AND: [{ appointment: { uid: voteEntity.appointment.uid } }, { voter: { uid: userId } }] },
});
} else {
voteFound = await this.votesService.get({
where: {
AND: [
{
appointment: {
AND: [{ user_uid: voteEntity.appointment.targeted_user.uid }, { status: EAppointmentStatus.OPEN }],
},
},
{ voter: { uid: userId } },
],
},
});
}
if (voteFound.length) {
this.httpBadRequest(response, "Voter already voted for this appointment");
return;
}
const voter = await this.usersService.getByUid(userId);
voteEntity.voter = voter!;
//call service to get prisma entity
const voteEntityCreated = await this.liveVoteService.create(voteEntity);
if (!voteEntityCreated) {
this.httpBadRequest(response, "Appointment choice is not valid");
return;
}
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(voteEntityCreated, {
strategy: "excludeAll",
});
//success
this.httpCreated(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -9,6 +9,7 @@ import { validateOrReject } from "class-validator";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import folderHandler from "@App/middlewares/OfficeMembershipHandlers/FolderHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Get all folders
*/
@Get("/api/v1/super-admin/folders", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -79,7 +80,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Create a new folder
*/
@Post("/api/v1/super-admin/folders", [authHandler, ruleHandler, folderHandler])
@Post("/api/v1/super-admin/folders", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async post(req: Request, response: Response) {
try {
//init OfficeFolder resource with request body values
@ -103,7 +104,7 @@ export default class OfficeFoldersController extends ApiController {
/**
* @description Modify a specific folder by uid
*/
@Put("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Put("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -145,7 +146,7 @@ export default class OfficeFoldersController extends ApiController {
* @description Get a specific folder by uid
* @returns IFolder
*/
@Get("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Get("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -175,13 +176,12 @@ export default class OfficeFoldersController extends ApiController {
this.httpInternalError(response, error);
return;
}
this.httpSuccess(response, await this.officeFoldersService.getByUid("uid"));
}
/**
* @description Delete a specific folder
*/
@Delete("/api/v1/super-admin/folders/:uid", [authHandler, ruleHandler, folderHandler])
@Delete("/api/v1/super-admin/folders/:uid", [authHandler, roleHandler, ruleHandler, folderHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -9,6 +9,7 @@ import { Prisma } from "@prisma/client";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import officeRoleHandler from "@App/middlewares/OfficeMembershipHandlers/OfficeRoleHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -20,7 +21,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Get all officeRoles
*/
@Get("/api/v1/super-admin/office-roles", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -62,7 +63,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Create a new officeRole
*/
@Post("/api/v1/super-admin/office-roles", [authHandler, ruleHandler, officeRoleHandler])
@Post("/api/v1/super-admin/office-roles", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async getAddresses(req: Request, response: Response) {
try {
//init IOfficeRole resource with request body values
@ -90,7 +91,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Modify a specific officeRole by uid
*/
@Put("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler])
@Put("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -131,7 +132,7 @@ export default class OfficeRolesController extends ApiController {
/**
* @description Get a specific officeRole by uid
*/
@Get("/api/v1/super-admin/office-roles/:uid", [authHandler, ruleHandler, officeRoleHandler])
@Get("/api/v1/super-admin/office-roles/:uid", [authHandler, roleHandler, ruleHandler, officeRoleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -8,6 +8,7 @@ import { Office as OfficeResource } from "le-coffre-resources/dist/SuperAdmin";
import { validateOrReject } from "class-validator";
import ruleHandler from "@App/middlewares/RulesHandler";
import authHandler from "@App/middlewares/AuthHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -18,7 +19,7 @@ export default class OfficesController extends ApiController {
/**
* @description Get all offices
*/
@Get("/api/v1/super-admin/offices", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -53,7 +54,7 @@ export default class OfficesController extends ApiController {
/**
* @description Create a new office
*/
@Post("/api/v1/super-admin/offices", [authHandler, ruleHandler])
@Post("/api/v1/super-admin/offices", [authHandler, roleHandler, ruleHandler])
protected async post(req: Request, response: Response) {
try {
//init IUser resource with request body values
@ -76,7 +77,7 @@ export default class OfficesController extends ApiController {
/**
* @description Modify a specific office by uid
*/
@Put("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler])
@Put("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -93,8 +94,7 @@ export default class OfficesController extends ApiController {
}
//init IUser resource with request body values
const officeEntity = OfficeResource.hydrate<OfficeResource>(req.body);
//validate user
await validateOrReject(officeEntity, { groups: ["updateOffice"] });
//call service to get prisma entity
const officeEntityUpdated = await this.officesService.update(uid, officeEntity);
//Hydrate ressource with prisma entity
@ -111,7 +111,7 @@ export default class OfficesController extends ApiController {
/**
* @description Get a specific office by uid
*/
@Get("/api/v1/super-admin/offices/:uid", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/offices/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator";
import { Role } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -18,7 +19,7 @@ export default class RolesController extends ApiController {
/**
* @description Get all roles
*/
@Get("/api/v1/super-admin/roles", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -44,7 +45,7 @@ export default class RolesController extends ApiController {
/**
* @description Create a new role
*/
@Post("/api/v1/super-admin/roles", [authHandler, ruleHandler])
@Post("/api/v1/super-admin/roles", [authHandler, roleHandler, ruleHandler])
protected async getAddresses(req: Request, response: Response) {
try {
//init IRole resource with request body values
@ -72,7 +73,7 @@ export default class RolesController extends ApiController {
/**
* @description Modify a specific role by uid
*/
@Put("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler])
@Put("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -113,7 +114,7 @@ export default class RolesController extends ApiController {
/**
* @description Get a specific role by uid
*/
@Get("/api/v1/super-admin/roles/:uid", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/roles/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -7,6 +7,7 @@ import { validateOrReject } from "class-validator";
import { Rule } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
@ -18,7 +19,7 @@ export default class RulesController extends ApiController {
/**
* @description Get all rules
*/
@Get("/api/v1/super-admin/rules", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -44,7 +45,7 @@ export default class RulesController extends ApiController {
/**
* @description Create a new rule
*/
@Post("/api/v1/super-admin/rules", [authHandler, ruleHandler])
@Post("/api/v1/super-admin/rules", [authHandler, roleHandler, ruleHandler])
protected async getAddresses(req: Request, response: Response) {
try {
//init IRule resource with request body values
@ -72,7 +73,7 @@ export default class RulesController extends ApiController {
/**
* @description Modify a specific rule by uid
*/
@Put("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler])
@Put("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
@ -91,9 +92,6 @@ export default class RulesController extends ApiController {
//init IRule resource with request body values
const ruleEntity = Rule.hydrate<Rule>(req.body);
//validate rule
await validateOrReject(ruleEntity, { groups: ["updateRule"] });
//call service to get prisma entity
const ruleEntityUpdated = await this.rulesService.update(ruleEntity);
@ -113,7 +111,7 @@ export default class RulesController extends ApiController {
/**
* @description Get a specific rule by uid
*/
@Get("/api/v1/super-admin/rules/:uid", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/rules/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -7,18 +7,21 @@ import { validateOrReject } from "class-validator";
import User from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import ruleHandler from "@App/middlewares/RulesHandler";
import roleHandler from "@App/middlewares/RolesHandler";
import RolesService from "@Services/super-admin/RolesService/RolesService";
import OfficeRolesService from "@Services/super-admin/OfficeRolesService/OfficeRolesService";
@Controller()
@Service()
export default class UsersController extends ApiController {
constructor(private usersService: UsersService) {
constructor(private usersService: UsersService, private roleService: RolesService, private officeRoleService: OfficeRolesService) {
super();
}
/**
* @description Get all users
*/
@Get("/api/v1/super-admin/users", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
@ -58,7 +61,7 @@ export default class UsersController extends ApiController {
/**
* @description Create a new user
*/
@Post("/api/v1/super-admin/users", [authHandler, ruleHandler])
@Post("/api/v1/super-admin/users", [authHandler, roleHandler, ruleHandler])
protected async create(req: Request, response: Response) {
try {
//init IUser resource with request body values
@ -86,16 +89,17 @@ export default class UsersController extends ApiController {
/**
* @description Modify a specific user by uid
*/
@Put("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler])
@Put("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler])
protected async put(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const userFound = await this.usersService.getByUid(uid);
const userFound = await this.usersService.getByUidWithRole(uid);
if (!userFound) {
this.httpNotFoundRequest(response, "user not found");
@ -105,9 +109,30 @@ export default class UsersController extends ApiController {
//init IUser resource with request body values
const userEntity = User.hydrate<User>(req.body);
//validate user
await validateOrReject(userEntity, { groups: ["updateUser"] });
if(userEntity.role) {
const role = await this.roleService.getByUid(userEntity.role.uid!);
if(!role) {
this.httpBadRequest(response, "Role not found");
return;
}
if (role.name === "super-admin" || userFound.role.name === "super-admin" ) {
this.httpBadRequest(response, "Cannot assign or remove super-admin role");
return;
}
}
if(userEntity.office_role) {
const officeRole = await this.officeRoleService.getByUid(userEntity.office_role.uid!);
if(!officeRole) {
this.httpBadRequest(response, "Office role not found");
return;
}
if (officeRole.office_uid != userFound.office_uid) {
this.httpBadRequest(response, "Cannot assign an office role from another office");
return;
}
}
//call service to get prisma entity
const userEntityUpdated = await this.usersService.update(uid, userEntity);
@ -127,7 +152,7 @@ export default class UsersController extends ApiController {
/**
* @description Get a specific user by uid
*/
@Get("/api/v1/super-admin/users/:uid", [authHandler, ruleHandler])
@Get("/api/v1/super-admin/users/:uid", [authHandler, roleHandler, ruleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];

View File

@ -0,0 +1,116 @@
import { Response, Request } from "express";
import { Controller, Delete, Get } from "@ControllerPattern/index";
import ApiController from "@Common/system/controller-pattern/ApiController";
import VotesService from "@Services/super-admin/VotesService/VotesService";
import { Service } from "typedi";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import authHandler from "@App/middlewares/AuthHandler";
import { Votes } from "@prisma/client";
import roleHandler from "@App/middlewares/RolesHandler";
@Controller()
@Service()
export default class VotesController extends ApiController {
constructor(private votesService: VotesService) {
super();
}
/**
* @description Get all votes
*/
@Get("/api/v1/super-admin/votes", [authHandler, roleHandler])
protected async get(req: Request, response: Response) {
try {
//get query
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
//call service to get prisma entity
const votesEntities = await this.votesService.get(query);
//Hydrate ressource with prisma entity
const votes = Vote.hydrateArray<Vote>(votesEntities, { strategy: "excludeAll" });
//success
this.httpSuccess(response, votes);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Get a specific vote by uid
*/
@Get("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler])
protected async getOneByUid(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
let query;
if (req.query["q"]) {
query = JSON.parse(req.query["q"] as string);
}
const voteEntity = await this.votesService.getByUid(uid, query);
if (!voteEntity) {
this.httpNotFoundRequest(response, "vote not found");
return;
}
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(voteEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
/**
* @description Delete a specific vote
*/
@Delete("/api/v1/super-admin/votes/:uid", [authHandler, roleHandler])
protected async delete(req: Request, response: Response) {
try {
const uid = req.params["uid"];
if (!uid) {
this.httpBadRequest(response, "No uid provided");
return;
}
const voteFound = await this.votesService.getByUid(uid);
if (!voteFound) {
this.httpNotFoundRequest(response, "vote not found");
return;
}
if (voteFound.voter_uid !== req.body.user.userId) {
this.httpUnauthorized(response, "Can't delete a vote that's not yours");
return;
}
//call service to get prisma entity
const votetEntity: Votes = await this.votesService.delete(uid);
//Hydrate ressource with prisma entity
const vote = Vote.hydrate<Vote>(votetEntity, { strategy: "excludeAll" });
//success
this.httpSuccess(response, vote);
} catch (error) {
this.httpInternalError(response, error);
return;
}
}
}

View File

@ -40,6 +40,11 @@ import RolesControllerNotary from "./api/notary/RolesController";
import OfficeRolesControllerNotary from "./api/notary/OfficeRolesController";
import FilesControllerCustomer from "./api/customer/FilesController";
import DocumentsControllerCustomer from "./api/customer/DocumentsController";
import OfficeFoldersController from "./api/customer/OfficeFoldersController";
import CustomersController from "./api/customer/CustomersController";
import AppointmentsController from "./api/super-admin/AppointmentsController";
import VotesController from "./api/super-admin/VotesController";
import LiveVoteController from "./api/super-admin/LiveVoteController";
/**
@ -56,6 +61,9 @@ export default {
Container.get(DeedTypesControllerSuperAdmin);
Container.get(DocumentsControllerSuperAdmin);
Container.get(DocumentTypesControllerSuperAdmin);
Container.get(AppointmentsController);
Container.get(VotesController);
Container.get(LiveVoteController);
Container.get(IdNotUserController);
Container.get(FranceConnectCustomerController);
Container.get(FilesControllerSuperAdmin);
@ -89,5 +97,7 @@ export default {
Container.get(OfficeRolesControllerNotary);
Container.get(FilesControllerCustomer);
Container.get(DocumentsControllerCustomer);
Container.get(OfficeFoldersController);
Container.get(CustomersController)
},
};

View File

@ -0,0 +1,22 @@
import HttpCodes from "@Common/system/controller-pattern/HttpCodes";
import { NextFunction, Request, Response } from "express";
export default async function roleHandler(req: Request, response: Response, next: NextFunction) {
try {
const namespace = req.path && req.path.split("/")[3];
const role = req.body.user.role;
if (namespace != "notary" && role != namespace && role != "super-admin") {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role");
return;
}
next();
} catch (error) {
console.log(error);
response.status(HttpCodes.INTERNAL_ERROR).send("Internal server error");
return;
}
}

View File

@ -7,14 +7,7 @@ export default async function ruleHandler(req: Request, response: Response, next
const service = req.path && req.path.split("/")[4];
if (!rules) {
response.status(HttpCodes.UNAUTHORIZED).send("Missing rules in JWT");
return;
}
const namespace = req.path && req.path.split("/")[3];
const role = req.body.user.role;
if (namespace != "notary" && role != namespace && role != "super-admin") {
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized with this role");
response.status(HttpCodes.UNAUTHORIZED).send("Unauthorized without rules");
return;
}

View File

@ -19,6 +19,9 @@ export class BackendVariables {
@IsNotEmpty()
public readonly DATABASE_NAME!: string;
@IsNotEmpty()
public readonly DATABASE_URL!: string;
@IsNotEmpty()
public readonly API_ROOT_URL!: string;
@ -72,6 +75,7 @@ export class BackendVariables {
this.DATABASE_USERNAME = process.env["DATABASE_USERNAME"]!;
this.DATABASE_PASSWORD = process.env["DATABASE_PASSWORD"]!;
this.DATABASE_NAME = process.env["DATABASE_NAME"]!;
this.DATABASE_URL = process.env["DEV_PRISMA_STUDIO_DB_URL"]!;
this.API_ROOT_URL = process.env["API_ROOT_URL"]!;
this.APP_PORT = process.env["APP_PORT"]!;
this.APP_ROOT_URL = process.env["APP_ROOT_URL"]!;

View File

@ -0,0 +1,38 @@
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_contact_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_office_role_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_office_uid_fkey";
-- DropForeignKey
ALTER TABLE "users" DROP CONSTRAINT "users_roles_uid_fkey";
-- CreateTable
CREATE TABLE "votes" (
"uid" TEXT NOT NULL,
"user_uid" VARCHAR(255) NOT NULL,
"voters" TEXT[],
CONSTRAINT "votes_pkey" PRIMARY KEY ("uid")
);
-- CreateIndex
CREATE UNIQUE INDEX "votes_uid_key" ON "votes"("uid");
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_contact_uid_fkey" FOREIGN KEY ("contact_uid") REFERENCES "contacts"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_roles_uid_fkey" FOREIGN KEY ("roles_uid") REFERENCES "roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_office_role_uid_fkey" FOREIGN KEY ("office_role_uid") REFERENCES "office_roles"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "users" ADD CONSTRAINT "users_office_uid_fkey" FOREIGN KEY ("office_uid") REFERENCES "offices"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;

View File

@ -0,0 +1,45 @@
/*
Warnings:
- You are about to drop the column `user_uid` on the `votes` table. All the data in the column will be lost.
- You are about to drop the column `voters` on the `votes` table. All the data in the column will be lost.
- Added the required column `appointment_uid` to the `votes` table without a default value. This is not possible if the table is not empty.
- Added the required column `voter_uid` to the `votes` table without a default value. This is not possible if the table is not empty.
*/
-- CreateEnum
CREATE TYPE "EVote" AS ENUM ('NOMINATE', 'DISMISS');
-- CreateEnum
CREATE TYPE "EAppointmentStatus" AS ENUM ('OPEN', 'CLOSED');
-- DropForeignKey
ALTER TABLE "votes" DROP CONSTRAINT "votes_user_uid_fkey";
-- AlterTable
ALTER TABLE "votes" DROP COLUMN "user_uid",
DROP COLUMN "voters",
ADD COLUMN "appointment_uid" VARCHAR(255) NOT NULL,
ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE',
ADD COLUMN "voter_uid" VARCHAR(255) NOT NULL;
-- CreateTable
CREATE TABLE "appointments" (
"uid" TEXT NOT NULL,
"user_uid" VARCHAR(255) NOT NULL,
"status" "EAppointmentStatus" NOT NULL DEFAULT 'OPEN',
CONSTRAINT "appointments_pkey" PRIMARY KEY ("uid")
);
-- CreateIndex
CREATE UNIQUE INDEX "appointments_uid_key" ON "appointments"("uid");
-- AddForeignKey
ALTER TABLE "appointments" ADD CONSTRAINT "appointments_user_uid_fkey" FOREIGN KEY ("user_uid") REFERENCES "users"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_appointment_uid_fkey" FOREIGN KEY ("appointment_uid") REFERENCES "appointments"("uid") ON DELETE CASCADE ON UPDATE CASCADE;
-- AddForeignKey
ALTER TABLE "votes" ADD CONSTRAINT "votes_voter_uid_fkey" FOREIGN KEY ("voter_uid") REFERENCES "users"("uid") ON DELETE RESTRICT ON UPDATE CASCADE;

View File

@ -0,0 +1,11 @@
/*
Warnings:
- You are about to drop the column `choice` on the `votes` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "appointments" ADD COLUMN "choice" "EVote" NOT NULL DEFAULT 'NOMINATE';
-- AlterTable
ALTER TABLE "votes" DROP COLUMN "choice";

View File

@ -0,0 +1,8 @@
/*
Warnings:
- A unique constraint covering the columns `[user_uid,choice,status]` on the table `appointments` will be added. If there are existing duplicate values, this will fail.
*/
-- CreateIndex
CREATE UNIQUE INDEX "appointments_user_uid_choice_status_key" ON "appointments"("user_uid", "choice", "status");

View File

@ -0,0 +1,12 @@
/*
Warnings:
- Added the required column `label` to the `roles` table without a default value. This is not possible if the table is not empty.
- Added the required column `label` to the `rules` table without a default value. This is not possible if the table is not empty.
*/
-- AlterTable
ALTER TABLE "roles" ADD COLUMN "label" VARCHAR(255) NOT NULL;
-- AlterTable
ALTER TABLE "rules" ADD COLUMN "label" VARCHAR(255) NOT NULL;

View File

@ -65,6 +65,8 @@ model Users {
office_uid String @db.VarChar(255)
notifications Notifications[] @relation("UserHasNotifications")
office_folders OfficeFolders[] @relation("OfficeFolderHasStakeholders")
appointment Appointments[]
votes Votes[]
@@map("users")
}
@ -240,6 +242,7 @@ model DeedTypes {
model Roles {
uid String @id @unique @default(uuid())
name String @db.VarChar(255)
label String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
rules Rules[] @relation("RolesHasRules")
@ -264,6 +267,7 @@ model OfficeRoles {
model Rules {
uid String @id @unique @default(uuid())
name String @db.VarChar(255)
label String @db.VarChar(255)
created_at DateTime? @default(now())
updated_at DateTime? @updatedAt
role Roles[] @relation("RolesHasRules")
@ -288,6 +292,28 @@ model Emails {
@@map("email")
}
model Appointments {
uid String @id @unique @default(uuid())
user Users @relation(fields: [user_uid], references: [uid], onDelete: Cascade)
user_uid String @db.VarChar(255)
choice EVote @default(NOMINATE)
status EAppointmentStatus @default(OPEN)
votes Votes[]
@@unique([user_uid, choice, status])
@@map("appointments")
}
model Votes {
uid String @id @unique @default(uuid())
appointment Appointments @relation(fields: [appointment_uid], references: [uid], onDelete: Cascade)
appointment_uid String @db.VarChar(255)
voter Users @relation(fields: [voter_uid], references: [uid])
voter_uid String @db.VarChar(255)
@@map("votes")
}
enum ECivility {
MALE
FEMALE
@ -322,3 +348,13 @@ enum EDocumentStatus {
ANCHORED
REFUSED
}
enum EVote {
NOMINATE
DISMISS
}
enum EAppointmentStatus {
OPEN
CLOSED
}

View File

@ -1,18 +1,7 @@
import { ECivility, ECustomerStatus, EFolderStatus, EOfficeStatus, Prisma, PrismaClient } from "@prisma/client";
import User, { Address, Contact, Customer, Deed, DeedType, DocumentType, Office, OfficeFolder, OfficeRole, Role, Rule } from "le-coffre-resources/dist/SuperAdmin";
import "module-alias/register";
import { EFolderStatus, EOfficeStatus, ECivility, ECustomerStatus, PrismaClient, Prisma } from "@prisma/client";
import User, {
Address,
Contact,
Customer,
Deed,
DeedType,
Office,
OfficeFolder,
OfficeRole,
Role,
Rule,
DocumentType,
} from "le-coffre-resources/dist/SuperAdmin";
export default async function main() {
try{
@ -526,301 +515,289 @@ export default async function main() {
const rules: Rule[] = [
{
name: "GET users",
label: "Lecture des utilisateurs",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET offices",
label: "Lecture des offices",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET customers",
label: "Lecture des clients",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET deeds",
label: "Lecture des actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET deed-types",
label: "Lecture des types d'actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET documents",
label: "Lecture des documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET document-types",
label: "Lecture des types de documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET files",
label: "Lecture des fichiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET folders",
label: "Lecture des dossiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET roles",
label: "Lecture utilisateurs",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET rules",
label: "Lecture des droits",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "GET office-roles",
label: "Lecture des rôles d'office",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT users",
label: "Modification des utilisateurs",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT offices",
label: "Modification des offices",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT customers",
label: "Modification des clients",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT deeds",
label: "Modification des actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT deedtypes",
name: "PUT deed-types",
label: "Modification des types d'actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT documents",
label: "Modification des documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT document-types",
label: "Modification des types de documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT files",
label: "Modification des fichiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT folders",
label: "Modification des dossiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT roles",
label: "Modification des rôles",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT rules",
label: "Modification des droits",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "PUT office-roles",
label: "Modification des rôles d'office",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST users",
label: "Création des utilisateurs",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST offices",
label: "Création des offices",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST customers",
label: "Création des clients",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST deeds",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST deedtypes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST document-types",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST files",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST folders",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST roles",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST rules",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST office-roles",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST users",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST offices",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST customers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST deeds",
label: "Création des actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST deed-types",
label: "Création des types d'actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST documents",
label: "Création des documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST document-types",
label: "Création des types de documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST files",
label: "Création des fichiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST folders",
label: "Création des dossiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST roles",
label: "Création des rôles",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST rules",
label: "Création des droits",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "POST office-roles",
label: "Création des rôles d'office",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE users",
label: "Suppression des utilisateurs",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE offices",
label: "Suppression des offices",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE customers",
label: "Suppression des clients",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE deeds",
label: "Suppression des actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE deed-types",
label: "Suppression des types d'actes",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE documents",
label: "Suppression des documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE document-types",
label: "Suppression des types de documents",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE files",
label: "Suppression des fichiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE folders",
label: "Suppression des dossiers",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE roles",
label: "Suppression des rôles",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE rules",
label: "Suppression des droits",
created_at: new Date(),
updated_at: new Date(),
},
{
name: "DELETE office-roles",
label: "Suppression des rôles d'office",
created_at: new Date(),
updated_at: new Date(),
},
@ -829,24 +806,28 @@ export default async function main() {
const roles: Role[] = [
{
name: "super-admin",
label: "Super administrateur",
created_at: new Date(),
updated_at: new Date(),
rules: rules,
},
{
name: "admin",
label: "Administrateur",
created_at: new Date(),
updated_at: new Date(),
rules: rules.slice(0, 33),
},
{
name: "notary",
label: "Notaire",
created_at: new Date(),
updated_at: new Date(),
rules: rules.slice(0, 22),
},
{
name: "default",
label: "Utilisateur",
created_at: new Date(),
updated_at: new Date(),
rules: rules.slice(0, 11),
@ -855,33 +836,19 @@ export default async function main() {
const officeRoles: OfficeRole[] = [
{
name: "admin",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 40),
},
{
name: "notary",
name: "Notaire",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 33),
},
{
name: "deputy",
name: "Collaborateur",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 22),
},
{
name: "listener",
created_at: new Date(),
updated_at: new Date(),
office: offices[0]!,
rules: rules.slice(0, 11),
},
}
];
const users: User[] = [
@ -1264,6 +1231,15 @@ export default async function main() {
created_at: new Date(),
updated_at: new Date(),
},
{
archived_at: null,
name: "Other",
office: offices[0],
private_description: "Other",
public_description: "Other",
created_at: new Date(),
updated_at: new Date(),
},
];
const officeFolders: OfficeFolder[] = [
@ -1371,7 +1347,7 @@ export default async function main() {
for (const office of offices) {
const officeCreated = await prisma.offices.create({
data: {
idNot: office.idNot,
idNot: office.idNot!,
name: office.name,
crpcen: office.crpcen,
address: {
@ -1390,6 +1366,7 @@ export default async function main() {
const ruleCreated = await prisma.rules.create({
data: {
name: rule.name,
label: rule.label,
},
});
rule.uid = ruleCreated.uid;
@ -1399,6 +1376,7 @@ export default async function main() {
const roleCreated = await prisma.roles.create({
data: {
name: role.name,
label: role.label,
rules: {
connect: role.rules?.map((rule) => ({
uid: rule.uid!,
@ -1438,7 +1416,7 @@ export default async function main() {
idNot: user.office_membership!.idNot,
},
create: {
idNot: user.office_membership!.idNot,
idNot: user.office_membership!.idNot!,
name: user.office_membership!.name,
crpcen: user.office_membership!.crpcen,
address: {

View File

@ -0,0 +1,76 @@
import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { Appointments, EAppointmentStatus, Prisma } from "@prisma/client";
@Service()
export default class AppointmentsRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().appointments;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many appointments
*/
public async findMany(query: Prisma.AppointmentsFindManyArgs) {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Update data of a appointment
*/
public async update(uid: string, status: EAppointmentStatus): Promise<Appointments> {
const updateArgs: Prisma.AppointmentsUpdateArgs = {
where: {
uid: uid,
},
data: {
status: status,
},
};
return this.model.update(updateArgs);
}
/**
* @description : Find one appointment
*/
public async findOneByUid(uid: string, query?: Prisma.AppointmentsInclude) {
return this.model.findUnique({
where: {
uid: uid,
},
include: query,
});
}
/**
* @description : Find one appointment with votes
*/
public async findOneByUidWithVotes(uid: string) {
return this.model.findUnique({
where: {
uid: uid,
},
include: {votes: true},
});
}
/**
* @description : delete a appointment
*/
public async delete(uid: string): Promise<Appointments> {
return this.model.delete({
where: {
uid: uid,
},
});
}
}

View File

@ -28,7 +28,7 @@ export default class DocumentsRepository extends BaseRepository {
/**
* @description : Create a document
*/
public async create(document: Document): Promise<Documents> {
public async create(document: DocumentCustomer): Promise<Documents> {
const createArgs: Prisma.DocumentsCreateArgs = {
data: {
folder: {

View File

@ -33,7 +33,7 @@ export default class OfficesRepository extends BaseRepository {
public async create(office: OfficeRessource): Promise<Offices> {
const createArgs: Prisma.OfficesCreateArgs = {
data: {
idNot: office.idNot,
idNot: office.idNot!,
name: office.name,
crpcen: office.crpcen,
address: {

View File

@ -31,6 +31,7 @@ export default class RolesRepository extends BaseRepository {
const createArgs: Prisma.RolesCreateArgs = {
data: {
name: role.name,
label: role.label,
rules: {
connect: role.rules?.map((rule) => ({
uid: rule.uid!,
@ -52,6 +53,7 @@ export default class RolesRepository extends BaseRepository {
},
data: {
name: role.name,
label: role.label,
rules: {
set: role.rules?.map((rule) => ({
uid: rule.uid!,

View File

@ -31,6 +31,7 @@ export default class RulesRepository extends BaseRepository {
const createArgs: Prisma.RulesCreateArgs = {
data: {
name: rule.name,
label: rule.label
},
};
@ -47,6 +48,7 @@ export default class RulesRepository extends BaseRepository {
},
data: {
name: rule.name,
label: rule.label
},
};

View File

@ -2,7 +2,7 @@ import Database from "@Common/databases/database";
import BaseRepository from "@Repositories/BaseRepository";
import { Service } from "typedi";
import { ECivility, Prisma, Users } from "@prisma/client";
import User from "le-coffre-resources/dist/SuperAdmin";
import User, { Role } from "le-coffre-resources/dist/SuperAdmin";
@Service()
export default class UsersRepository extends BaseRepository {
@ -37,7 +37,7 @@ export default class UsersRepository extends BaseRepository {
idNot: user.office_membership!.idNot,
},
create: {
idNot: user.office_membership!.idNot,
idNot: user.office_membership!.idNot!,
name: user.office_membership!.name,
crpcen: user.office_membership!.crpcen,
address: {
@ -87,6 +87,7 @@ export default class UsersRepository extends BaseRepository {
/**
* @description : Update data from a user
*/
public async update(uid: string, user: User): Promise<Users> {
const updateArgs: Prisma.UsersUpdateArgs = {
where: {
@ -196,6 +197,18 @@ export default class UsersRepository extends BaseRepository {
});
}
/**
* @description : Find one user with office
*/
public async findOneByUidWithRole(uid: string): Promise<((Users & {role: Role} )| null)> {
return this.model.findUnique({
where: {
uid: uid,
},
include: { role: true },
});
}
/**
* @description : Find one user
*/

View File

@ -0,0 +1,89 @@
import Database from "@Common/databases/database";
import { EAppointmentStatus, EVote, Prisma, Votes } from "@prisma/client";
import BaseRepository from "@Repositories/BaseRepository";
import { Vote } from "le-coffre-resources/dist/SuperAdmin";
import { Service } from "typedi";
@Service()
export default class VotesRepository extends BaseRepository {
constructor(private database: Database) {
super();
}
protected get model() {
return this.database.getClient().votes;
}
protected get instanceDb() {
return this.database.getClient();
}
/**
* @description : Find many votes
*/
public async findMany(query: Prisma.VotesFindManyArgs) {
query.take = Math.min(query.take || this.defaultFetchRows, this.maxFetchRows);
return this.model.findMany(query);
}
/**
* @description : Create new vote
*/
public async create(vote: Vote): Promise<Votes> {
let whereArg: Prisma.AppointmentsWhereUniqueInput;
if(vote.appointment.targeted_user.uid) {
whereArg = {
user_uid_choice_status: {
user_uid: vote.appointment.targeted_user.uid,
choice: EVote[vote.appointment.choice as keyof typeof EVote],
status: EAppointmentStatus.OPEN,
}
};
} else {
whereArg = {
uid: vote.appointment.uid,
};
}
const createArgs: Prisma.VotesCreateArgs = {
data: {
appointment: {
connectOrCreate: {
where: whereArg,
create: {
choice: EVote[vote.appointment.choice as keyof typeof EVote],
user_uid: vote.appointment.targeted_user.uid!,
}
},
},
voter: {
connect: {
uid: vote.voter.uid,
},
},
}
};
return this.model.create({...createArgs, include: {appointment: {include: {votes: true}}}});
}
/**
* @description : Find one vote
*/
public async findOneByUid(uid: string, query?: Prisma.VotesInclude): Promise<Votes | null> {
return this.model.findUnique({
where: {
uid: uid,
},
include: query,
});
}
/**
* @description : delete a vote
*/
public async delete(uid: string): Promise<Votes> {
return this.model.delete({
where: {
uid: uid,
},
});
}
}

View File

@ -9,7 +9,7 @@ dotenv.config();
export default class DbProvider {
protected readonly variables = Container.get(BackendVariables);
protected url = `postgres://${this.variables.DATABASE_USERNAME}:${this.variables.DATABASE_PASSWORD}@${this.variables.DATABASE_HOST}:${this.variables.DATABASE_PORT}/${this.variables.DATABASE_NAME}`;
protected url = this.variables.DATABASE_URL;
protected client = new PrismaClient({
datasources: {
db: {

View File

@ -31,7 +31,7 @@ export default class UsersService extends BaseService {
* @description : Modify a user
* @throws {Error} If user modification failed
*/
public update(uid: string, userEntity: User): Promise<Users> {
public async update(uid: string, userEntity: User): Promise<Users> {
return this.userRepository.updateRole(uid, userEntity);
}
@ -51,6 +51,14 @@ export default class UsersService extends BaseService {
return this.userRepository.findOneByUidWithOffice(uid);
}
/**
* @description : Get a user by uid with office
* @throws {Error} If user cannot be get by uid
*/
public getByUidWithRole(uid: string) {
return this.userRepository.findOneByUidWithRole(uid);
}
/**
* @description : Get a user by uid
* @throws {Error} If user cannot be get by uid

View File

@ -36,16 +36,17 @@ export default class AuthService extends BaseService {
public async getCustomerJwtPayload(email:string): Promise<ICustomerJwtPayload | null> {
const contact = await this.contactService.getByEmail(email);
if (!contact) return null;
const customer = await this.customerService.getByUid(contact.customers!.uid, { contact: true });
if (!customer) return null;
if(contact.customers?.status === ECustomerStatus["PENDING"]) {
contact.customers.status = ECustomerStatus["VALIDATED"];
this.customerService.update(contact.customers.uid, contact.customers);
if(customer.status === ECustomerStatus["PENDING"]) {
customer.status = ECustomerStatus["VALIDATED"];
this.customerService.update(customer.uid, customer);
}
return {
customerId: contact.customers!.uid,
customerId: customer.uid,
email: contact.email,
};
}
@ -56,22 +57,19 @@ export default class AuthService extends BaseService {
if (!user) return null;
const rules: string[] = [];
if (user.office_role) {
user.office_role.rules.forEach((rule) => {
rules.push(rule.name);
});
return {
userId: user.uid,
openId: { providerName: providerName, userId: user.idNot },
office_Id: user.office_membership.uid,
role: user.role.name,
rules: rules,
};
}
user.role.rules.forEach((rule) => {
rules.push(rule.name);
});
if (user.office_role) {
user.office_role.rules.forEach((rule) => {
if(!rules.includes(rule.name)) {
rules.push(rule.name);
}
});
}
return {
userId: user.uid,
openId: { providerName: providerName, userId: user.idNot },
@ -80,7 +78,6 @@ export default class AuthService extends BaseService {
rules: rules,
};
}
public generateAccessToken(user: any): string {
return jwt.sign({ ...user }, this.variables.ACCESS_TOKEN_SECRET, { expiresIn: "1h" });
}

View File

@ -8,7 +8,6 @@ import { BackendVariables } from "@Common/config/variables/Variables";
import { Readable } from "stream";
import { v4 } from "uuid";
import { Files, Prisma } from "@prisma/client";
import fetch from "node-fetch";
@Service()
export default class FilesService extends BaseService {

View File

@ -0,0 +1,35 @@
import { Customers, Prisma } from "@prisma/client";
import CustomersRepository from "@Repositories/CustomersRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
@Service()
export default class CustomersService extends BaseService {
constructor(private customerRepository: CustomersRepository) {
super();
}
/**
* @description : Get all Customers
* @throws {Error} If Customers cannot be get
*/
public async get(query: Prisma.CustomersFindManyArgs): Promise<Customers[]> {
return this.customerRepository.findMany(query);
}
/**
* @description : Get a customer by uid
* @throws {Error} If customer cannot be get by uid
*/
public async getByUid(uid: string, query?: Prisma.CustomersInclude): Promise<Customers | null> {
return this.customerRepository.findOneByUid(uid, query);
}
/**
* @description : Get a customer by contact uid
* @throws {Error} If customer cannot be get by contact uid
*/
public async getByContact(contactUid: string): Promise<Customers | null> {
return this.customerRepository.findOneByContact(contactUid);
}
}

View File

@ -3,10 +3,11 @@ import { Document } from "le-coffre-resources/dist/Customer";
import DocumentsRepository from "@Repositories/DocumentsRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import DocumentTypesService from "@Services/notary/DocumentTypesService/DocumentTypesService";
@Service()
export default class DocumentsService extends BaseService {
constructor(private documentsRepository: DocumentsRepository) {
constructor(private documentsRepository: DocumentsRepository, private documentTypeService: DocumentTypesService) {
super();
}
@ -18,6 +19,21 @@ export default class DocumentsService extends BaseService {
return this.documentsRepository.findMany(query);
}
/**
* @description : Create a new document
* @throws {Error} If document cannot be created
*/
public async create(document: Document): Promise<Documents> {
const otherDocumentType = await this.documentTypeService.get({ where: { name: "Other" } });
if(otherDocumentType.length < 1) throw new Error("Other document type not found");
document.document_type = otherDocumentType[0];
document.document_status = "DEPOSITED";
return this.documentsRepository.create(document);
}
/**
* @description : Modify a document
* @throws {Error} If document cannot be modified

View File

@ -0,0 +1,29 @@
import OfficeFoldersRepository from "@Repositories/OfficeFoldersRepository";
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import { Prisma } from "@prisma/client";
@Service()
export default class OfficeFoldersService extends BaseService {
constructor(
private officeFoldersRepository: OfficeFoldersRepository,
) {
super();
}
/**
* @description : Get all folders
* @throws {Error} If folders cannot be get
*/
public async get(query: Prisma.OfficeFoldersFindManyArgs) {
return this.officeFoldersRepository.findMany(query);
}
/**
* @description : Get a folder by uid
* @throws {Error} If folder cannot be get by uid
*/
public async getByUid(uid: string, query?: Prisma.OfficeFoldersInclude) {
return this.officeFoldersRepository.findOneByUid(uid, query);
}
}

View File

@ -1,5 +1,4 @@
import BaseService from "@Services/BaseService";
import "reflect-metadata";
import { Service } from "typedi";
import RolesRepository from "@Repositories/RolesRepository";
import { Prisma } from "@prisma/client";

View File

@ -1,5 +1,4 @@
import BaseService from "@Services/BaseService";
import "reflect-metadata";
import { Service } from "typedi";
import RulesRepository from "@Repositories/RulesRepository";
import { Prisma } from "@prisma/client";

View File

@ -1,9 +1,7 @@
import BaseService from "@Services/BaseService";
import "reflect-metadata";
import { Service } from "typedi";
import UsersRepository from "@Repositories/UsersRepository";
import User from "le-coffre-resources/dist/Notary";
import { Prisma, Users } from "@prisma/client";
import { Prisma } from "@prisma/client";
@Service()
export default class UsersService extends BaseService {
@ -19,22 +17,6 @@ export default class UsersService extends BaseService {
return this.userRepository.findMany(query);
}
/**
* @description : Create a user
* @throws {Error} If user couldn't be created
*/
public create(userEntity: User): Promise<Users> {
return this.userRepository.create(userEntity);
}
/**
* @description : Modify a user
* @throws {Error} If user modification failed
*/
public update(uid: string, userEntity: User): Promise<Users> {
return this.userRepository.update(uid, userEntity);
}
/**
* @description : Get a user by uid
* @throws {Error} If user cannot be get by uid

View File

@ -0,0 +1,53 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import AppointmentsRepository from "@Repositories/AppointmentsRepository";
import { Prisma, Appointments, EAppointmentStatus } from "@prisma/client";
@Service()
export default class AppointmentService extends BaseService {
constructor(private appointmentRepository: AppointmentsRepository) {
super();
}
/**
* @description : Get all appointments
* @throws {Error} If appointments cannot be get
*/
public get(query: Prisma.AppointmentsFindManyArgs) {
return this.appointmentRepository.findMany(query);
}
/**
* @description : Modify a appointment
* @throws {Error} If appointment cannot be modified
*/
public async update(uid: string, status: EAppointmentStatus): Promise<Appointments> {
return this.appointmentRepository.update(uid, status);
}
/**
* @description : Get a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public getByUid(uid: string, query?: Prisma.AppointmentsInclude): Promise<Appointments | null> {
return this.appointmentRepository.findOneByUid(uid, query);
}
/**
* @description : Get a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public getByUidWithVotes(uid: string) {
return this.appointmentRepository.findOneByUidWithVotes(uid);
}
/**
* @description : delete a appointment by uid
* @throws {Error} If appointment cannot be get by uid
*/
public delete(uid: string) {
return this.appointmentRepository.delete(uid);
}
}

View File

@ -0,0 +1,97 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import User, { Appointment, Role, Vote } from "le-coffre-resources/dist/SuperAdmin";
import VotesRepository from "@Repositories/VotesRepository";
import { Appointments, EAppointmentStatus, EVote, Votes } from "@prisma/client";
import AppointmentService from "../AppointmentsService/AppointmentsService";
import UsersService from "../UsersService/UsersService";
import RolesService from "../RolesService/RolesService";
@Service()
export default class LiveVoteService extends BaseService {
constructor(
private voteRepository: VotesRepository,
private appointmentService: AppointmentService,
private userService: UsersService,
private roleService: RolesService,
) {
super();
}
public async verifyVoterChoice(vote: Vote): Promise<boolean> {
const userWithRole = await this.userService.getByUidWithRole(vote.appointment.targeted_user.uid!);
if (userWithRole!.role.name === "super-admin" && vote.appointment.choice === EVote.DISMISS) {
return true;
}
if (userWithRole!.role.name !== "super-admin" && vote.appointment.choice === EVote.NOMINATE) {
return true;
}
return false;
}
public async getAppointmentWithVotes(vote: Vote): Promise<Appointments | null> {
if (vote.appointment.uid) {
return this.appointmentService.getByUidWithVotes(vote.appointment.uid);
}
const appointmentByUser = await this.appointmentService.get({
where: {
AND: [
{ user_uid: vote.appointment.targeted_user.uid },
{ status: EAppointmentStatus.OPEN },
{ choice: EVote[vote.appointment.choice as keyof typeof EVote] },
],
},
include: { votes: true },
});
if (appointmentByUser.length >= 1) {
return this.appointmentService.getByUidWithVotes(appointmentByUser[0]!.uid);
}
return null;
}
private async closeVote(appointment: Appointments, vote: Votes) {
await this.appointmentService.update(vote.appointment_uid, EAppointmentStatus.CLOSED);
const user = await this.userService.getByUid(appointment.user_uid, { role: true });
const userEntity = User.hydrate<User>(user!, { strategy: "excludeAll" });
return await this.updateRole(appointment, userEntity, vote);
}
private async updateRole(appointment: Appointments, userEntity: User, vote: Votes) {
if (appointment.choice === EVote.DISMISS) {
const roles = await this.roleService.get({ where: { name: "default" } });
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
userEntity.role = roleEntity;
await this.userService.update(appointment!.user_uid, userEntity);
return vote;
} else if (appointment.choice === EVote.NOMINATE) {
const roles = await this.roleService.get({ where: { name: "super-admin" } });
const roleEntity = Role.hydrate<Role>(roles[0]!, { strategy: "excludeAll" });
userEntity!.role = roleEntity;
await this.userService.update(appointment!.user_uid, userEntity);
return vote;
}
return vote;
}
/**
* @description : Create a vote
* @throws {Error} If vote couldn't be created
*/
public async create(vote: Vote): Promise<Votes | null> {
const appointment = await this.getAppointmentWithVotes(vote);
if (appointment) {
const appointmentEntity = Appointment.hydrate<Appointment>(appointment, { strategy: "excludeAll" });
if (appointmentEntity?.votes && appointmentEntity.votes.length >= 2) {
const voteCreated = await this.voteRepository.create(vote);
return this.closeVote(appointment, voteCreated);
}
}
const approvedChoice = await this.verifyVoterChoice(vote);
if(!approvedChoice) return null;
return this.voteRepository.create(vote);
}
}

View File

@ -51,6 +51,14 @@ export default class UsersService extends BaseService {
return this.userRepository.findOneByUidWithOffice(uid);
}
/**
* @description : Get a user by uid with role
* @throws {Error} If user cannot be get by uid
*/
public getByUidWithRole(uid: string) {
return this.userRepository.findOneByUidWithRole(uid);
}
/**
* @description : Get a user by uid
* @throws {Error} If user cannot be get by uid

View File

@ -0,0 +1,35 @@
import BaseService from "@Services/BaseService";
import { Service } from "typedi";
import VotesRepository from "@Repositories/VotesRepository";
import { Prisma } from "@prisma/client";
@Service()
export default class VoteService extends BaseService {
constructor(private voteRepository: VotesRepository) {
super();
}
/**
* @description : Get all votes
* @throws {Error} If votes cannot be get
*/
public get(query: Prisma.VotesFindManyArgs) {
return this.voteRepository.findMany(query);
}
/**
* @description : Get a vote by uid
* @throws {Error} If vote cannot be get by uid
*/
public getByUid(uid: string, query?: Prisma.VotesInclude) {
return this.voteRepository.findOneByUid(uid, query);
}
/**
* @description : delete a vote by uid
* @throws {Error} If vote cannot be get by uid
*/
public delete(uid: string) {
return this.voteRepository.delete(uid);
}
}

View File

@ -18,7 +18,7 @@ const prisma = new PrismaClient();
export const initOffice = (office: Office): Promise<Offices> => {
return prisma.offices.create({
data: {
idNot: office.idNot,
idNot: office.idNot!,
name: office.name,
crpcen: office.crpcen,
address: {
@ -95,6 +95,7 @@ export const initRules = (rule: Rule): Promise<Rules> => {
return prisma.rules.create({
data: {
name: rule.name,
label: rule.label,
},
});
};
@ -103,6 +104,7 @@ export const initRoles = (role: Role): Promise<Roles> => {
return prisma.roles.create({
data: {
name: role.name,
label: role.label,
},
});
};
@ -117,7 +119,7 @@ export const initUsers = (user: User): Promise<Users> => {
idNot: user.office_membership!.idNot,
},
create: {
idNot: user.office_membership!.idNot,
idNot: user.office_membership!.idNot!,
name: user.office_membership!.name,
crpcen: user.office_membership!.crpcen,
address: {
@ -154,6 +156,7 @@ export const initUsers = (user: User): Promise<Users> => {
},
create: {
name: user.role!.name,
label: user.role!.label
},
},
},