Skip to content

Commit 527842f

Browse files
authored
Update userdata validation logic and create a place to trigger bulk-tickets approvals (#243)
1 parent f601d4f commit 527842f

16 files changed

Lines changed: 456 additions & 26 deletions

File tree

src/authz/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,8 +182,8 @@ export class canApproveTicket extends PreExecutionRule {
182182
export class CanSeePersonalData extends PostExecutionRule {
183183
public async execute(
184184
ctx: GraphqlContext,
185-
fieldArgs: any,
186-
_: any,
185+
fieldArgs: unknown,
186+
_: unknown,
187187
parent: {
188188
id: string;
189189
},

src/datasources/db/userTickets.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,7 @@ export const userTicketsRelations = relations(userTicketsSchema, ({ one }) => ({
6565
export const selectUserTicketsSchema = createSelectSchema(userTicketsSchema);
6666

6767
export const insertUserTicketsSchema = createInsertSchema(userTicketsSchema);
68+
69+
export const approveUserTicketsSchema = selectUserTicketsSchema.pick({
70+
approvalStatus: true,
71+
});

src/errors.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { Logger } from "~/logging";
66
export enum ServiceErrors {
77
UNAUTHENTICATED = "UNAUTHENTICATED",
88
FAILED_PRECONDITION = "FAILED_PRECONDITION",
9+
UNAUTHORIZED = "UNAUTHORIZED",
910
FORBIDDEN = "FORBIDDEN",
1011
CONFLICT = "CONFLICT",
1112
NOT_FOUND = "NOT_FOUND",
@@ -21,6 +22,7 @@ builder.enumType(ServiceErrors, {
2122
const error_codes: Record<string, number> = {
2223
[ServiceErrors.INVALID_ARGUMENT]: 400,
2324
[ServiceErrors.UNAUTHENTICATED]: 401,
25+
[ServiceErrors.UNAUTHORIZED]: 403,
2426
[ServiceErrors.FORBIDDEN]: 403,
2527
[ServiceErrors.NOT_FOUND]: 404,
2628
[ServiceErrors.FAILED_PRECONDITION]: 412,

src/generated/schema.gql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,10 @@ type Mutation {
403403
Kickoff the email validation flow. This flow will links an email to a user, create a company if it does not exist, and allows filling data for that email's position
404404
"""
405405
startWorkEmailValidation(email: String!): WorkEmail!
406+
triggerUserTicketApprovalReview(
407+
eventId: String!
408+
userId: String!
409+
): [UserTicket!]!
406410

407411
"""
408412
Update a company
@@ -832,6 +836,7 @@ enum ServiceErrors {
832836
INVALID_ARGUMENT
833837
NOT_FOUND
834838
UNAUTHENTICATED
839+
UNAUTHORIZED
835840
}
836841

837842
"""
@@ -1117,8 +1122,11 @@ Representation of a user's data
11171122
type UserData {
11181123
city: String!
11191124
countryOfResidence: String!
1125+
emergencyPhoneNumber: String
1126+
foodAllergies: String
11201127
organizationName: String
11211128
roleInOrganization: String
1129+
rut: String
11221130
worksInOrganization: Boolean!
11231131
}
11241132

@@ -1238,8 +1246,12 @@ input placeHolderUsersInput {
12381246
input updateUserDataInput {
12391247
city: String!
12401248
countryOfResidence: String!
1249+
emergencyPhoneNumber: String
1250+
eventId: String!
1251+
foodAllergies: String
12411252
organizationName: String
12421253
roleInOrganization: String
1254+
rut: String
12431255
worksInOrganization: Boolean!
12441256
}
12451257

src/generated/types.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ export type Mutation = {
350350
rejectTeamInvitation: TeamRef;
351351
/** Kickoff the email validation flow. This flow will links an email to a user, create a company if it does not exist, and allows filling data for that email's position */
352352
startWorkEmailValidation: WorkEmail;
353+
triggerUserTicketApprovalReview: Array<UserTicket>;
353354
/** Update a company */
354355
updateCompany: Company;
355356
updateMyUserData: User;
@@ -465,6 +466,11 @@ export type MutationStartWorkEmailValidationArgs = {
465466
email: Scalars["String"]["input"];
466467
};
467468

469+
export type MutationTriggerUserTicketApprovalReviewArgs = {
470+
eventId: Scalars["String"]["input"];
471+
userId: Scalars["String"]["input"];
472+
};
473+
468474
export type MutationUpdateCompanyArgs = {
469475
input: UpdateCompanyInput;
470476
};
@@ -882,6 +888,7 @@ export enum ServiceErrors {
882888
InvalidArgument = "INVALID_ARGUMENT",
883889
NotFound = "NOT_FOUND",
884890
Unauthenticated = "UNAUTHENTICATED",
891+
Unauthorized = "UNAUTHORIZED",
885892
}
886893

887894
/** Representation of a Session */
@@ -1142,8 +1149,11 @@ export type UserData = {
11421149
__typename?: "UserData";
11431150
city: Scalars["String"]["output"];
11441151
countryOfResidence: Scalars["String"]["output"];
1152+
emergencyPhoneNumber?: Maybe<Scalars["String"]["output"]>;
1153+
foodAllergies?: Maybe<Scalars["String"]["output"]>;
11451154
organizationName?: Maybe<Scalars["String"]["output"]>;
11461155
roleInOrganization?: Maybe<Scalars["String"]["output"]>;
1156+
rut?: Maybe<Scalars["String"]["output"]>;
11471157
worksInOrganization: Scalars["Boolean"]["output"];
11481158
};
11491159

@@ -1254,8 +1264,12 @@ export type PlaceHolderUsersInput = {
12541264
export type UpdateUserDataInput = {
12551265
city: Scalars["String"]["input"];
12561266
countryOfResidence: Scalars["String"]["input"];
1267+
emergencyPhoneNumber?: InputMaybe<Scalars["String"]["input"]>;
1268+
eventId: Scalars["String"]["input"];
1269+
foodAllergies?: InputMaybe<Scalars["String"]["input"]>;
12571270
organizationName?: InputMaybe<Scalars["String"]["input"]>;
12581271
roleInOrganization?: InputMaybe<Scalars["String"]["input"]>;
1272+
rut?: InputMaybe<Scalars["String"]["input"]>;
12591273
worksInOrganization: Scalars["Boolean"]["input"];
12601274
};
12611275

src/notifications/tickets.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export const sendTicketInvitationEmails = async ({
115115
);
116116
}
117117

118-
await RPC_SERVICE_EMAIL.sendEventTicketInvitationsBatch({
118+
await RPC_SERVICE_EMAIL.bulkSendEventTicketInvitations({
119119
eventName: ticketInformation.event.name,
120120
ticketId: ticketInformation.id,
121121
eventId: ticketInformation.event.id,

src/schema/user/mutations.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { eq } from "drizzle-orm";
22
import { GraphQLError } from "graphql";
33
import slugify from "slugify";
4-
import { z } from "zod";
54

65
import { builder } from "~/builder";
76
import {
@@ -19,6 +18,7 @@ import { applicationError, ServiceErrors } from "~/errors";
1918
import { UserRef } from "~/schema/shared/refs";
2019
import { pronounsEnum } from "~/schema/user/types";
2120
import { usersFetcher } from "~/schema/user/userFetcher";
21+
import { validateUserDataAndApproveUserTickets } from "~/schema/userTickets/helpers";
2222
import {
2323
UserRoleCommunity,
2424
canUpdateUserRoleInCommunity,
@@ -167,6 +167,7 @@ builder.mutationField("updateUserRoleInCommunity", (t) =>
167167

168168
const updateUserDataInput = builder.inputType("updateUserDataInput", {
169169
fields: (t) => ({
170+
eventId: t.string({ required: true }),
170171
countryOfResidence: t.string({ required: true }),
171172
city: t.string({ required: true }),
172173
worksInOrganization: t.boolean({ required: true }),
@@ -206,7 +207,7 @@ builder.mutationField("updateMyUserData", (t) =>
206207
throw new Error("User not found");
207208
}
208209

209-
const valuesToParse: Partial<z.infer<typeof insertUserDataSchema>> = {
210+
const valuesToParse: Partial<typeof insertUserDataSchema._type> = {
210211
userId: USER.id,
211212
countryOfResidence,
212213
city,
@@ -237,6 +238,13 @@ builder.mutationField("updateMyUserData", (t) =>
237238
);
238239
}
239240

241+
await validateUserDataAndApproveUserTickets({
242+
DB: ctx.DB,
243+
userId: USER.id,
244+
eventId: input.eventId,
245+
logger: ctx.logger,
246+
});
247+
240248
const user = await usersFetcher.searchUsers({
241249
DB: ctx.DB,
242250
search: {

src/schema/user/tests/updateMyUserData/updateMyUserData.test.ts

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { faker } from "@faker-js/faker";
22
import { it, describe, assert } from "vitest";
33

4-
import { executeGraphqlOperationAsUser, insertUser } from "~/tests/fixtures";
4+
import {
5+
executeGraphqlOperationAsUser,
6+
insertEvent,
7+
insertUser,
8+
} from "~/tests/fixtures";
59

610
import {
711
UpdateMyUserDataMutationVariables,
@@ -12,12 +16,16 @@ import {
1216
describe("UpdateMyUserData", () => {
1317
it("I Should be able to update my data", async () => {
1418
const user = await insertUser();
19+
const event = await insertEvent();
1520

1621
const city = faker.location.city();
1722
const countryOfResidence = faker.location.country();
1823
const worksInOrganization = true;
1924
const organizationName = faker.company.name();
2025
const roleInOrganization = faker.name.jobTitle();
26+
const rut = faker.lorem.text();
27+
const foodAllergies = faker.lorem.words(3);
28+
const emergencyPhoneNumber = faker.phone.number();
2129

2230
const response = await executeGraphqlOperationAsUser<
2331
UpdateMyUserDataMutation,
@@ -27,11 +35,15 @@ describe("UpdateMyUserData", () => {
2735
document: UpdateMyUserData,
2836
variables: {
2937
input: {
38+
eventId: event.id,
3039
city,
3140
countryOfResidence,
3241
worksInOrganization,
3342
organizationName,
3443
roleInOrganization,
44+
rut,
45+
foodAllergies,
46+
emergencyPhoneNumber,
3547
},
3648
},
3749
},
@@ -67,6 +79,7 @@ describe("UpdateMyUserData", () => {
6779

6880
it("I Should be able to edit my data", async () => {
6981
const user = await insertUser();
82+
const event = await insertEvent();
7083

7184
await executeGraphqlOperationAsUser<
7285
UpdateMyUserDataMutation,
@@ -81,6 +94,10 @@ describe("UpdateMyUserData", () => {
8194
worksInOrganization: true,
8295
organizationName: faker.company.name(),
8396
roleInOrganization: faker.name.jobTitle(),
97+
eventId: event.id,
98+
rut: faker.lorem.text(),
99+
foodAllergies: faker.lorem.words(3),
100+
emergencyPhoneNumber: faker.phone.number(),
84101
},
85102
},
86103
},
@@ -92,6 +109,9 @@ describe("UpdateMyUserData", () => {
92109
const worksInOrganization = true;
93110
const organizationName = faker.company.name();
94111
const roleInOrganization = faker.name.jobTitle();
112+
const rut = faker.lorem.text();
113+
const foodAllergies = faker.lorem.words(3);
114+
const emergencyPhoneNumber = faker.phone.number();
95115

96116
const response = await executeGraphqlOperationAsUser<
97117
UpdateMyUserDataMutation,
@@ -101,11 +121,15 @@ describe("UpdateMyUserData", () => {
101121
document: UpdateMyUserData,
102122
variables: {
103123
input: {
124+
eventId: event.id,
104125
city,
105126
countryOfResidence,
106127
worksInOrganization,
107128
organizationName,
108129
roleInOrganization,
130+
rut,
131+
foodAllergies,
132+
emergencyPhoneNumber,
109133
},
110134
},
111135
},

0 commit comments

Comments
 (0)