Skip to content

Commit 398f5c9

Browse files
Refactor team invite handler and update tests
1 parent 72aedd9 commit 398f5c9

6 files changed

Lines changed: 292 additions & 232 deletions

File tree

serverless.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import discord from '@functions/discord';
99
import read from '@functions/read';
1010
import waiver from '@functions/waiver';
1111
import resume from '@functions/resume';
12+
import teamsInvite from '@functions/teams/invite';
1213
import resetPassword from '@functions/reset-password';
1314
import forgotPassword from '@functions/forgot-password';
1415
import leaderboard from '@functions/leaderboard';
@@ -57,6 +58,7 @@ const serverlessConfiguration: AWS = {
5758
attendEvent,
5859
waiver,
5960
resume,
61+
teamsInvite,
6062
read,
6163
discord,
6264
forgotPassword,

src/functions/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export { default as discord } from './discord';
77
export { default as read } from './read';
88
export { default as waiver } from './waiver';
99
export { default as resume } from './resume';
10+
export { default as teamsInvite } from './teams/invite';
1011
export { default as resetPassword } from './reset-password';
1112
export { default as forgotPassword } from './forgot-password';
1213
export { default as leaderboard } from './leaderboard';

src/functions/teams/invite/handler.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,13 @@ import * as path from 'path';
44
import type { ValidatedEventAPIGatewayProxyEvent } from '@libs/api-gateway';
55
import { middyfy } from '@libs/lambda';
66
import schema from './schema';
7+
import type { Failure, TeamInvite, TeamDocument, UserDocument } from '../../../types';
78
import { MongoDB, validateToken, userExistsLogic } from '../../../util';
89

910
dotenv.config({ path: path.resolve(process.cwd(), '.env') });
1011

1112
const MAX_TEAM_SIZE = 4;
1213

13-
interface Failure {
14-
email: string;
15-
reason: string;
16-
}
17-
18-
interface PendingInvite {
19-
team_id: string;
20-
invited_by: string;
21-
invited_at: Date;
22-
}
23-
2414
const teamInvite: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (event) => {
2515
// Alias snake_case request fields to camelCase locals to satisfy naming-convention
2616
const { auth_token: authToken, auth_email: authEmail, team_id: teamId, emails } = event.body;
@@ -37,8 +27,8 @@ const teamInvite: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (eve
3727
const db = MongoDB.getInstance(process.env.MONGO_URI!);
3828
await db.connect();
3929
const client = db.getClient();
40-
const users = db.getCollection('users');
41-
const teams = db.getCollection('teams');
30+
const users = db.getCollection<UserDocument>('users');
31+
const teams = db.getCollection<TeamDocument>('teams');
4232

4333
// verify auth user
4434
const authUser = await users.findOne({ email: authEmail });
@@ -64,8 +54,16 @@ const teamInvite: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (eve
6454
};
6555
}
6656

57+
// check team status
58+
if (team.status !== 'Active') {
59+
return {
60+
statusCode: 400,
61+
body: JSON.stringify({ message: 'Team is not active' }),
62+
};
63+
}
64+
6765
// capacity check
68-
const confirmedCount = Array.isArray(team.members) ? team.members.length : 0;
66+
const confirmedCount = (Array.isArray(team.members) ? team.members.length : 0) + 1; // + 1 for the leader
6967
const pendingCount = await users.countDocuments({
7068
'team_info.pending_invites.team_id': teamId,
7169
});
@@ -114,7 +112,7 @@ const teamInvite: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (eve
114112
}
115113

116114
// prevent duplicate invites (type the pending list instead of using any)
117-
const pending = (user.team_info?.pending_invites ?? []) as PendingInvite[];
115+
const pending = (user.team_info?.pending_invites ?? []) as TeamInvite[];
118116
if (pending.some((inv) => inv.team_id === teamId)) {
119117
failed.push({ email, reason: 'Already invited to this team' });
120118
continue;
@@ -129,7 +127,8 @@ const teamInvite: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (eve
129127
team_id: teamId,
130128
invited_by: authEmail,
131129
invited_at: new Date(),
132-
} as PendingInvite,
130+
team_name: team.team_name,
131+
} as TeamInvite,
133132
},
134133
},
135134
{ session }

src/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ export interface TeamInvite {
55
team_name: string;
66
}
77

8+
export interface Failure {
9+
email: string;
10+
reason: string;
11+
}
12+
813
export interface UserTeamInfo {
914
team_id: string | null;
1015
role: 'leader' | 'member' | null;

tests/team-invite.test.ts

Lines changed: 0 additions & 216 deletions
This file was deleted.

0 commit comments

Comments
 (0)