feat: send email to owner after member accepted invitation / leave workspace (#4152)

Co-authored-by: DarkSky <darksky2048@gmail.com>
This commit is contained in:
Qi
2023-09-07 13:08:23 +08:00
committed by GitHub
parent 1301605db5
commit 498683ff4c
15 changed files with 259 additions and 47 deletions
+2 -13
View File
@@ -13,6 +13,7 @@ import { AuthModule } from '../modules/auth';
import { AuthService } from '../modules/auth/service';
import { PrismaModule } from '../prisma';
import { RateLimiterModule } from '../throttler';
import { getCurrentMailMessageCount, getLatestMailMessage } from './utils';
let auth: AuthService;
let module: TestingModule;
@@ -68,23 +69,11 @@ test.afterEach(async () => {
await module.close();
});
const getCurrentMailMessageCount = async () => {
const response = await fetch('http://localhost:8025/api/v2/messages');
const data = await response.json();
return data.total;
};
const getLatestMailMessage = async () => {
const response = await fetch('http://localhost:8025/api/v2/messages');
const data = await response.json();
return data.items[0];
};
test('should include callbackUrl in sending email', async t => {
if (skip) {
return t.pass();
}
await auth.signUp('Alex Yang', 'alexyang@example.org', '123456');
// await auth.signUp('Alex Yang', 'alexyang@example.org', '123456');
for (const fn of [
'sendSetPasswordEmail',
'sendChangeEmail',
+18 -4
View File
@@ -12,6 +12,18 @@ import type { InvitationType, WorkspaceType } from '../modules/workspaces';
const gql = '/graphql';
export async function getCurrentMailMessageCount() {
const response = await fetch('http://localhost:8025/api/v2/messages');
const data = await response.json();
return data.total;
}
export async function getLatestMailMessage() {
const response = await fetch('http://localhost:8025/api/v2/messages');
const data = await response.json();
return data.items[0];
}
async function signUp(
app: INestApplication,
name: string,
@@ -192,7 +204,8 @@ async function inviteUser(
async function acceptInviteById(
app: INestApplication,
workspaceId: string,
inviteId: string
inviteId: string,
sendAcceptMail = false
): Promise<boolean> {
const res = await request(app.getHttpServer())
.post(gql)
@@ -200,7 +213,7 @@ async function acceptInviteById(
.send({
query: `
mutation {
acceptInviteById(workspaceId: "${workspaceId}", inviteId: "${inviteId}")
acceptInviteById(workspaceId: "${workspaceId}", inviteId: "${inviteId}", sendAcceptMail: ${sendAcceptMail})
}
`,
})
@@ -231,7 +244,8 @@ async function acceptInvite(
async function leaveWorkspace(
app: INestApplication,
token: string,
workspaceId: string
workspaceId: string,
sendLeaveMail = false
): Promise<boolean> {
const res = await request(app.getHttpServer())
.post(gql)
@@ -240,7 +254,7 @@ async function leaveWorkspace(
.send({
query: `
mutation {
leaveWorkspace(workspaceId: "${workspaceId}")
leaveWorkspace(workspaceId: "${workspaceId}", workspaceName: "test workspace", sendLeaveMail: ${sendLeaveMail})
}
`,
})
+62 -2
View File
@@ -12,6 +12,8 @@ import {
acceptInvite,
acceptInviteById,
createWorkspace,
getCurrentMailMessageCount,
getLatestMailMessage,
getWorkspace,
inviteUser,
leaveWorkspace,
@@ -100,6 +102,8 @@ test('should leave a workspace', async t => {
await acceptInvite(app, u2.token.token, workspace.id);
const leave = await leaveWorkspace(app, u2.token.token, workspace.id);
t.pass();
t.true(leave, 'failed to leave workspace');
});
@@ -162,13 +166,15 @@ test('should invite a user by link', async t => {
t.is(currMember?.inviteId, invite, 'failed to check invite id');
});
test('should send invite email', async t => {
test('should send email', async t => {
if (mail.hasConfigured()) {
const u1 = await signUp(app, 'u1', 'u1@affine.pro', '1');
const u2 = await signUp(app, 'test', 'production@toeverything.info', '1');
const workspace = await createWorkspace(app, u1.token.token);
await inviteUser(
const primitiveMailCount = await getCurrentMailMessageCount();
const invite = await inviteUser(
app,
u1.token.token,
workspace.id,
@@ -176,6 +182,60 @@ test('should send invite email', async t => {
'Admin',
true
);
const afterInviteMailCount = await getCurrentMailMessageCount();
t.is(
primitiveMailCount + 1,
afterInviteMailCount,
'failed to send invite email'
);
const inviteEmailContent = await getLatestMailMessage();
t.not(
// @ts-expect-error Third part library type mismatch
inviteEmailContent.To.find(item => {
return item.Mailbox === 'production';
}),
undefined,
'invite email address was incorrectly sent'
);
const accept = await acceptInviteById(app, workspace.id, invite, true);
t.true(accept, 'failed to accept invite');
const afterAcceptMailCount = await getCurrentMailMessageCount();
t.is(
afterInviteMailCount + 1,
afterAcceptMailCount,
'failed to send accepted email to owner'
);
const acceptEmailContent = await getLatestMailMessage();
t.not(
// @ts-expect-error Third part library type mismatch
acceptEmailContent.To.find(item => {
return item.Mailbox === 'u1';
}),
undefined,
'accept email address was incorrectly sent'
);
await leaveWorkspace(app, u2.token.token, workspace.id, true);
const afterLeaveMailCount = await getCurrentMailMessageCount();
t.is(
afterAcceptMailCount + 1,
afterLeaveMailCount,
'failed to send leave email to owner'
);
const leaveEmailContent = await getLatestMailMessage();
t.not(
// @ts-expect-error Third part library type mismatch
leaveEmailContent.To.find(item => {
return item.Mailbox === 'u1';
}),
undefined,
'leave email address was incorrectly sent'
);
}
t.pass();
});