mirror of
https://github.com/swissmakers/swiss-datashare.git
synced 2026-04-11 10:27:01 +02:00
feat: invite new user with email
This commit is contained in:
@@ -135,9 +135,27 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
"Hey!\nYou requested a password reset. Click this link to reset your password: {url}\nThe link expires in a hour.\nPingvin Share 🐧",
|
||||
category: "email",
|
||||
},
|
||||
|
||||
{
|
||||
order: 13,
|
||||
key: "INVITE_EMAIL_SUBJECT",
|
||||
description:
|
||||
"Subject of the email which gets sent when an admin invites an user.",
|
||||
type: "string",
|
||||
value: "Pingvin Share invite",
|
||||
category: "email",
|
||||
},
|
||||
{
|
||||
order: 14,
|
||||
key: "INVITE_EMAIL_MESSAGE",
|
||||
description:
|
||||
"Message which gets sent when an admin invites an user. {url} will be replaced with the invite URL and {password} with the password.",
|
||||
type: "text",
|
||||
value:
|
||||
"Hey!\nYou were invited to Pingvin Share. Click this link to accept the invite: {url}\nYour password is: {password}\nPingvin Share 🐧",
|
||||
category: "email",
|
||||
},
|
||||
{
|
||||
order: 15,
|
||||
key: "SMTP_ENABLED",
|
||||
description:
|
||||
"Whether SMTP is enabled. Only set this to true if you entered the host, port, email, user and password of your SMTP server.",
|
||||
@@ -147,7 +165,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
secret: false,
|
||||
},
|
||||
{
|
||||
order: 14,
|
||||
order: 16,
|
||||
key: "SMTP_HOST",
|
||||
description: "Host of the SMTP server",
|
||||
type: "string",
|
||||
@@ -155,7 +173,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
category: "smtp",
|
||||
},
|
||||
{
|
||||
order: 15,
|
||||
order: 17,
|
||||
key: "SMTP_PORT",
|
||||
description: "Port of the SMTP server",
|
||||
type: "number",
|
||||
@@ -163,7 +181,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
category: "smtp",
|
||||
},
|
||||
{
|
||||
order: 16,
|
||||
order: 18,
|
||||
key: "SMTP_EMAIL",
|
||||
description: "Email address which the emails get sent from",
|
||||
type: "string",
|
||||
@@ -171,7 +189,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
category: "smtp",
|
||||
},
|
||||
{
|
||||
order: 17,
|
||||
order: 19,
|
||||
key: "SMTP_USERNAME",
|
||||
description: "Username of the SMTP server",
|
||||
type: "string",
|
||||
@@ -179,7 +197,7 @@ const configVariables: Prisma.ConfigCreateInput[] = [
|
||||
category: "smtp",
|
||||
},
|
||||
{
|
||||
order: 18,
|
||||
order: 20,
|
||||
key: "SMTP_PASSWORD",
|
||||
description: "Password of the SMTP server",
|
||||
type: "string",
|
||||
|
||||
@@ -73,6 +73,20 @@ export class EmailService {
|
||||
});
|
||||
}
|
||||
|
||||
async sendInviteEmail(recipientEmail: string, password: string) {
|
||||
const loginUrl = `${this.config.get("APP_URL")}/auth/signIn`;
|
||||
|
||||
await this.getTransporter().sendMail({
|
||||
from: `"Pingvin Share" <${this.config.get("SMTP_EMAIL")}>`,
|
||||
to: recipientEmail,
|
||||
subject: this.config.get("INVITE_EMAIL_SUBJECT"),
|
||||
text: this.config
|
||||
.get("INVITE_EMAIL_MESSAGE")
|
||||
.replaceAll("{url}", loginUrl)
|
||||
.replaceAll("{password}", password),
|
||||
});
|
||||
}
|
||||
|
||||
async sendTestMail(recipientEmail: string) {
|
||||
try {
|
||||
await this.getTransporter().sendMail({
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
import { Expose, plainToClass } from "class-transformer";
|
||||
import { Allow } from "class-validator";
|
||||
import { plainToClass } from "class-transformer";
|
||||
import { Allow, IsOptional, MinLength } from "class-validator";
|
||||
import { UserDTO } from "./user.dto";
|
||||
|
||||
export class CreateUserDTO extends UserDTO {
|
||||
@Expose()
|
||||
@Allow()
|
||||
isAdmin: boolean;
|
||||
|
||||
@MinLength(8)
|
||||
@IsOptional()
|
||||
password: string;
|
||||
|
||||
from(partial: Partial<CreateUserDTO>) {
|
||||
return plainToClass(CreateUserDTO, partial, {
|
||||
excludeExtraneousValues: true,
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Module } from "@nestjs/common";
|
||||
import { EmailModule } from "src/email/email.module";
|
||||
import { UserController } from "./user.controller";
|
||||
import { UserSevice } from "./user.service";
|
||||
|
||||
@Module({
|
||||
imports:[EmailModule],
|
||||
providers: [UserSevice],
|
||||
controllers: [UserController],
|
||||
})
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { BadRequestException, Injectable } from "@nestjs/common";
|
||||
import { PrismaClientKnownRequestError } from "@prisma/client/runtime";
|
||||
import * as argon from "argon2";
|
||||
import { EmailService } from "src/email/email.service";
|
||||
import { PrismaService } from "src/prisma/prisma.service";
|
||||
import { CreateUserDTO } from "./dto/createUser.dto";
|
||||
import { UpdateUserDto } from "./dto/updateUser.dto";
|
||||
|
||||
@Injectable()
|
||||
export class UserSevice {
|
||||
constructor(private prisma: PrismaService) {}
|
||||
constructor(
|
||||
private prisma: PrismaService,
|
||||
private emailService: EmailService
|
||||
) {}
|
||||
|
||||
async list() {
|
||||
return await this.prisma.user.findMany();
|
||||
@@ -18,7 +22,17 @@ export class UserSevice {
|
||||
}
|
||||
|
||||
async create(dto: CreateUserDTO) {
|
||||
const hash = await argon.hash(dto.password);
|
||||
let hash: string;
|
||||
|
||||
// The password can be undefined if the user is invited by an admin
|
||||
if (!dto.password) {
|
||||
const randomPassword = crypto.randomUUID();
|
||||
hash = await argon.hash(randomPassword);
|
||||
this.emailService.sendInviteEmail(dto.email, randomPassword);
|
||||
} else {
|
||||
hash = await argon.hash(dto.password);
|
||||
}
|
||||
|
||||
try {
|
||||
return await this.prisma.user.create({
|
||||
data: {
|
||||
|
||||
Reference in New Issue
Block a user