push code len ne
This commit is contained in:
@@ -1,10 +1,61 @@
|
|||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { PothosSchema, SchemaBuilderToken } from '@smatch-corp/nestjs-pothos';
|
import {
|
||||||
|
PothosRef,
|
||||||
|
PothosSchema,
|
||||||
|
SchemaBuilderToken,
|
||||||
|
} from '@smatch-corp/nestjs-pothos';
|
||||||
import { Builder } from 'src/Graphql/graphql.builder';
|
import { Builder } from 'src/Graphql/graphql.builder';
|
||||||
|
import { AppConfigService } from './appconfig.service';
|
||||||
|
import { PrismaService } from 'src/Prisma/prisma.service';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AppConfigSchema extends PothosSchema {
|
export class AppConfigSchema extends PothosSchema {
|
||||||
constructor(@Inject(SchemaBuilderToken) private readonly builder: Builder) {
|
constructor(
|
||||||
|
@Inject(SchemaBuilderToken) private readonly builder: Builder,
|
||||||
|
private readonly appConfigService: AppConfigService,
|
||||||
|
private readonly prisma: PrismaService,
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PothosRef()
|
||||||
|
appConfig() {
|
||||||
|
return this.builder.prismaObject('Config', {
|
||||||
|
description: 'An app config',
|
||||||
|
fields: (t) => ({
|
||||||
|
id: t.exposeID('id', {
|
||||||
|
description: 'The unique identifier for the config',
|
||||||
|
}),
|
||||||
|
name: t.exposeString('name', { description: 'The name of the config' }),
|
||||||
|
key: t.exposeString('key', { description: 'The key of the config' }),
|
||||||
|
value: t.exposeString('value', {
|
||||||
|
description: 'The value of the config',
|
||||||
|
}),
|
||||||
|
visible: t.exposeBoolean('visible', {
|
||||||
|
description: 'Whether the config is visible',
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@PothosRef()
|
||||||
|
init(): void {
|
||||||
|
this.builder.queryFields((t) => ({
|
||||||
|
appConfigs: t.prismaField({
|
||||||
|
type: [this.appConfig()],
|
||||||
|
description: 'Get all app configs',
|
||||||
|
args: this.builder.generator.findManyArgs('Config'),
|
||||||
|
resolve: async (query, root, args, ctx, info) => {
|
||||||
|
return await this.prisma.config.findMany({
|
||||||
|
...query,
|
||||||
|
where: args.filter ?? undefined,
|
||||||
|
orderBy: args.orderBy ?? undefined,
|
||||||
|
cursor: args.cursor ?? undefined,
|
||||||
|
skip: args.skip ?? undefined,
|
||||||
|
take: args.take ?? undefined,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { PrismaService } from 'src/Prisma/prisma.service';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppConfigService {
|
||||||
|
constructor(private readonly prisma: PrismaService) {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
'Retrieve a list of centers with optional filtering, ordering, and pagination.',
|
'Retrieve a list of centers with optional filtering, ordering, and pagination.',
|
||||||
type: [this.center()],
|
type: [this.center()],
|
||||||
args: this.builder.generator.findManyArgs('Center'),
|
args: this.builder.generator.findManyArgs('Center'),
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.findMany({
|
return await this.prisma.center.findMany({
|
||||||
...query,
|
...query,
|
||||||
skip: args.skip ?? undefined,
|
skip: args.skip ?? undefined,
|
||||||
@@ -110,7 +110,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
type: this.center(),
|
type: this.center(),
|
||||||
description: 'Retrieve a single center by its unique identifier.',
|
description: 'Retrieve a single center by its unique identifier.',
|
||||||
args: this.builder.generator.findUniqueArgs('Center'),
|
args: this.builder.generator.findUniqueArgs('Center'),
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.findUnique({
|
return await this.prisma.center.findUnique({
|
||||||
...query,
|
...query,
|
||||||
where: args.where,
|
where: args.where,
|
||||||
@@ -124,7 +124,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
args: {
|
args: {
|
||||||
userId: t.arg({ type: 'String', required: true }),
|
userId: t.arg({ type: 'String', required: true }),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.findFirst({
|
return await this.prisma.center.findFirst({
|
||||||
where: {
|
where: {
|
||||||
centerMentors: {
|
centerMentors: {
|
||||||
@@ -149,7 +149,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.create({
|
return await this.prisma.center.create({
|
||||||
...query,
|
...query,
|
||||||
data: args.input,
|
data: args.input,
|
||||||
@@ -169,7 +169,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.update({
|
return await this.prisma.center.update({
|
||||||
...query,
|
...query,
|
||||||
where: args.where,
|
where: args.where,
|
||||||
@@ -186,7 +186,7 @@ export class CenterSchema extends PothosSchema {
|
|||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.center.delete({
|
return await this.prisma.center.delete({
|
||||||
...query,
|
...query,
|
||||||
where: args.where,
|
where: args.where,
|
||||||
@@ -205,8 +205,12 @@ export class CenterSchema extends PothosSchema {
|
|||||||
type: 'Boolean',
|
type: 'Boolean',
|
||||||
required: true,
|
required: true,
|
||||||
}),
|
}),
|
||||||
|
adminNote: t.arg({
|
||||||
|
type: 'String',
|
||||||
|
required: false,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
resolve: async (query, root, args, ctx, info) => {
|
resolve: async (query, root, args) => {
|
||||||
return await this.prisma.$transaction(async (prisma) => {
|
return await this.prisma.$transaction(async (prisma) => {
|
||||||
const center = await prisma.center.findUnique({
|
const center = await prisma.center.findUnique({
|
||||||
...query,
|
...query,
|
||||||
@@ -254,18 +258,37 @@ export class CenterSchema extends PothosSchema {
|
|||||||
: CenterStatus.REJECTED,
|
: CenterStatus.REJECTED,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
// mail to center owner
|
// mail to center owner if approved
|
||||||
|
if (args.approve) {
|
||||||
try {
|
try {
|
||||||
await this.mailService.sendEmail(
|
await this.mailService.sendTemplateEmail(
|
||||||
centerOwner.email,
|
centerOwner.email,
|
||||||
args.approve
|
'Thông báo phê duyệt đăng ký trung tâm',
|
||||||
? 'Your center has been approved'
|
'CenterApproved',
|
||||||
: 'Your center has been rejected',
|
{
|
||||||
args.approve ? 'center-approved' : 'center-rejected',
|
CENTER_NAME: center.name,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
Logger.error(error, 'CenterSchema');
|
Logger.error(error, 'CenterSchema');
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!args.approve) {
|
||||||
|
// mail to center owner if rejected
|
||||||
|
try {
|
||||||
|
await this.mailService.sendTemplateEmail(
|
||||||
|
centerOwner.email,
|
||||||
|
'Thông báo từ chối đăng ký trung tâm',
|
||||||
|
'CenterRejected',
|
||||||
|
{
|
||||||
|
CENTER_NAME: center.name,
|
||||||
|
ADMIN_NOTE: args.adminNote,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
Logger.error(error, 'CenterSchema');
|
||||||
|
}
|
||||||
|
}
|
||||||
return updatedCenter;
|
return updatedCenter;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -267,7 +267,8 @@ export class CenterMentorSchema extends PothosSchema {
|
|||||||
notedByUserId: ctx.me.id,
|
notedByUserId: ctx.me.id,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const updatedUser = await prisma.user.update({
|
// update user role
|
||||||
|
await prisma.user.update({
|
||||||
where: args.where,
|
where: args.where,
|
||||||
data: {
|
data: {
|
||||||
role: 'CENTER_MENTOR',
|
role: 'CENTER_MENTOR',
|
||||||
|
|||||||
72
src/Mail/templates/CenterApproved.pug
Normal file
72
src/Mail/templates/CenterApproved.pug
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
doctype html
|
||||||
|
html
|
||||||
|
head
|
||||||
|
meta(charset="UTF-8")
|
||||||
|
title Thông báo phê duyệt Trung tâm #{CENTER_NAME}
|
||||||
|
style.
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #457D84; /* Medium teal */
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.content p {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 20px;
|
||||||
|
background-color: #2BD4E2; /* Bright aqua */
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
body
|
||||||
|
.container
|
||||||
|
.header
|
||||||
|
h1 Chúc mừng Trung tâm #{CENTER_NAME} đã được phê duyệt
|
||||||
|
.content
|
||||||
|
p Kính gửi Quý Trung tâm,
|
||||||
|
p Chúng tôi vui mừng thông báo rằng trung tâm #{CENTER_NAME} của bạn đã được phê duyệt trên nền tảng của chúng tôi.
|
||||||
|
p Vui lòng nhấn vào nút dưới đây để truy cập vào trung tâm của bạn:
|
||||||
|
a.button(href="https://center.epess.org") Truy cập Trung tâm
|
||||||
|
p Nếu bạn có bất kỳ thắc mắc nào, đừng ngần ngại liên hệ với chúng tôi.
|
||||||
|
.footer
|
||||||
|
p Trân trọng,
|
||||||
|
p EPESS
|
||||||
|
p Nền tảng hỗ trợ viết luận
|
||||||
84
src/Mail/templates/CenterRejected.pug
Normal file
84
src/Mail/templates/CenterRejected.pug
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
doctype html
|
||||||
|
html
|
||||||
|
head
|
||||||
|
meta(charset="UTF-8")
|
||||||
|
title Thông báo từ chối Trung tâm #{CENTER_NAME}
|
||||||
|
style.
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background-color: #f0f8ff;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 600px;
|
||||||
|
margin: 20px auto;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
background-color: #d9534f; /* Red color for rejection */
|
||||||
|
color: #ffffff;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 8px 8px 0 0;
|
||||||
|
}
|
||||||
|
.header h1 {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 20px;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.content p {
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
background-color: #f8d7da;
|
||||||
|
color: #721c24;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 20px 0;
|
||||||
|
border: 1px solid #f5c6cb;
|
||||||
|
}
|
||||||
|
.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 12px 20px;
|
||||||
|
background-color: #2BD4E2; /* Bright aqua */
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 16px;
|
||||||
|
border-radius: 5px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 14px;
|
||||||
|
color: #555;
|
||||||
|
padding: 10px;
|
||||||
|
border-top: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
body
|
||||||
|
.container
|
||||||
|
.header
|
||||||
|
h1 Thông báo từ chối Trung tâm #{CENTER_NAME}
|
||||||
|
.content
|
||||||
|
p Kính gửi Quý Trung tâm,
|
||||||
|
p Chúng tôi rất tiếc thông báo rằng trung tâm #{CENTER_NAME} của bạn chưa được phê duyệt trên nền tảng của chúng tôi.
|
||||||
|
.note
|
||||||
|
p Lý do từ chối:
|
||||||
|
p #{ADMIN_NOTE}
|
||||||
|
p Chúng tôi khuyến khích bạn xem xét lại thông tin và nộp đơn đăng ký lại trong tương lai.
|
||||||
|
p Bạn có thể truy cập trang web của chúng tôi để biết thêm thông tin:
|
||||||
|
a.button(href="https://center.epess.org") Truy cập Trung tâm
|
||||||
|
p Nếu bạn có bất kỳ thắc mắc nào, đừng ngần ngại liên hệ với chúng tôi.
|
||||||
|
.footer
|
||||||
|
p Trân trọng,
|
||||||
|
p EPESS
|
||||||
|
p Nền tảng hỗ trợ viết luận
|
||||||
10
src/main.ts
10
src/main.ts
@@ -24,8 +24,14 @@ async function bootstrap() {
|
|||||||
process.env.JWT_RS256_PRIVATE_KEY = privateKey;
|
process.env.JWT_RS256_PRIVATE_KEY = privateKey;
|
||||||
process.env.JWT_RS256_PUBLIC_KEY = publicKey;
|
process.env.JWT_RS256_PUBLIC_KEY = publicKey;
|
||||||
|
|
||||||
Logger.log(`Private key: ${privateKey.slice(0, 10)}...`, 'Bootstrap');
|
Logger.log(
|
||||||
Logger.log(`Public key: ${publicKey.slice(0, 10)}...`, 'Bootstrap');
|
`Private key: ${privateKey.slice(0, 10).replace(/\n/g, '')}...`,
|
||||||
|
'Bootstrap',
|
||||||
|
);
|
||||||
|
Logger.log(
|
||||||
|
`Public key: ${publicKey.slice(0, 10).replace(/\n/g, '')}...`,
|
||||||
|
'Bootstrap',
|
||||||
|
);
|
||||||
|
|
||||||
const corsOrigin = (process.env.CORS_ORIGIN ?? '').split(','); // split by comma to array
|
const corsOrigin = (process.env.CORS_ORIGIN ?? '').split(','); // split by comma to array
|
||||||
app.enableCors({
|
app.enableCors({
|
||||||
|
|||||||
Reference in New Issue
Block a user