Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/api/functions/mobileWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ export async function issueAppleWalletMembershipCard(
pkpass.backFields.push({ label: "Membership ID", key: "id", value: email });
const buffer = pkpass.getAsBuffer();
logger.info(
{ type: "audit", actor: initiator, target: email },
{ type: "audit", module: "mobileWallet", actor: initiator, target: email },
"Created membership verification pass",
);
return buffer;
Expand Down
14 changes: 12 additions & 2 deletions src/api/routes/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,12 @@ const eventsPlugin: FastifyPluginAsync = async (fastify, _options) => {
resource: `/api/v1/events/${entryUUID}`,
});
request.log.info(
{ type: "audit", actor: request.username, target: entryUUID },
{
type: "audit",
module: "events",
actor: request.username,
target: entryUUID,
},
`${verb} event "${entryUUID}"`,
);
} catch (e: unknown) {
Expand Down Expand Up @@ -388,7 +393,12 @@ const eventsPlugin: FastifyPluginAsync = async (fastify, _options) => {
false,
);
request.log.info(
{ type: "audit", actor: request.username, target: id },
{
type: "audit",
module: "events",
actor: request.username,
target: id,
},
`deleted event "${id}"`,
);
},
Expand Down
25 changes: 22 additions & 3 deletions src/api/routes/iam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,12 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
}
reply.send({ message: "OK" });
request.log.info(
{ type: "audit", actor: request.username, target: groupId },
{
type: "audit",
module: "iam",
actor: request.username,
target: groupId,
},
`set target roles to ${request.body.roles.toString()}`,
);
},
Expand Down Expand Up @@ -241,13 +246,23 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
const result = results[i];
if (result.status === "fulfilled") {
request.log.info(
{ type: "audit", actor: request.username, target: emails[i] },
{
type: "audit",
module: "iam",
actor: request.username,
target: emails[i],
},
"invited user to Entra ID tenant.",
);
response.success.push({ email: emails[i] });
} else {
request.log.info(
{ type: "audit", actor: request.username, target: emails[i] },
{
type: "audit",
module: "iam",
actor: request.username,
target: emails[i],
},
"failed to invite user to Entra ID tenant.",
);
if (result.reason instanceof EntraInvitationError) {
Expand Down Expand Up @@ -345,6 +360,7 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
request.log.info(
{
type: "audit",
module: "iam",
actor: request.username,
target: request.body.add[i],
},
Expand All @@ -354,6 +370,7 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
request.log.info(
{
type: "audit",
module: "iam",
actor: request.username,
target: request.body.add[i],
},
Expand All @@ -379,6 +396,7 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
request.log.info(
{
type: "audit",
module: "iam",
actor: request.username,
target: request.body.remove[i],
},
Expand All @@ -388,6 +406,7 @@ const iamRoutes: FastifyPluginAsync = async (fastify, _options) => {
request.log.info(
{
type: "audit",
module: "iam",
actor: request.username,
target: request.body.add[i],
},
Expand Down
1 change: 1 addition & 0 deletions src/api/routes/stripe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ const stripeRoutes: FastifyPluginAsync = async (fastify, _options) => {
request.log.info(
{
type: "audit",
module: "stripe",
actor: request.username,
target: `Link ${linkId} | Invoice ${invoiceId}`,
},
Expand Down
90 changes: 32 additions & 58 deletions src/api/routes/tickets.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FastifyPluginAsync } from "fastify";
import { z } from "zod";
import {
ConditionalCheckFailedException,
QueryCommand,
ScanCommand,
UpdateItemCommand,
Expand Down Expand Up @@ -300,14 +301,17 @@ const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => {
stripe_pi: { S: ticketId },
},
UpdateExpression: "SET fulfilled = :true_val",
ConditionExpression: "#email = :email_val",
ConditionExpression:
"#email = :email_val AND (attribute_not_exists(fulfilled) OR fulfilled = :false_val) AND (attribute_not_exists(refunded) OR refunded = :false_val)",
ExpressionAttributeNames: {
"#email": "email",
},
ExpressionAttributeValues: {
":true_val": { BOOL: true },
":false_val": { BOOL: false },
":email_val": { S: request.body.email },
},
ReturnValuesOnConditionCheckFailure: "ALL_OLD",
ReturnValues: "ALL_OLD",
});
break;
Expand All @@ -319,12 +323,16 @@ const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => {
ticket_id: { S: ticketId },
},
UpdateExpression: "SET #used = :trueValue",
ConditionExpression:
"(attribute_not_exists(#used) OR #used = :falseValue) AND (attribute_not_exists(refunded) OR refunded = :falseValue)",
ExpressionAttributeNames: {
"#used": "used",
},
ExpressionAttributeValues: {
":trueValue": { BOOL: true },
":falseValue": { BOOL: false },
},
ReturnValuesOnConditionCheckFailure: "ALL_OLD",
ReturnValues: "ALL_OLD",
});
break;
Expand All @@ -342,16 +350,6 @@ const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => {
});
}
const attributes = unmarshall(ticketEntry.Attributes);
if (attributes["refunded"]) {
throw new TicketNotValidError({
message: "Ticket was already refunded.",
});
}
if (attributes["used"] || attributes["fulfilled"]) {
throw new TicketNotValidError({
message: "Ticket has already been used.",
});
}
if (request.body.type === "ticket") {
const rawData = attributes["ticketholder_netid"];
const isEmail = validateEmail(attributes["ticketholder_netid"]);
Expand All @@ -376,65 +374,41 @@ const ticketsPlugin: FastifyPluginAsync = async (fastify, _options) => {
if (e instanceof BaseError) {
throw e;
}
if (e.name === "ConditionalCheckFailedException") {
if (e instanceof ConditionalCheckFailedException) {
if (e.Item) {
const unmarshalled = unmarshall(e.Item);
if (unmarshalled["fulfilled"] || unmarshalled["used"]) {
throw new TicketNotValidError({
message: "Ticket has already been used.",
});
}
if (unmarshalled["refunded"]) {
throw new TicketNotValidError({
message: "Ticket was already refunded.",
});
}
}
throw new TicketNotFoundError({
message: "Ticket does not exist",
message: "Ticket does not exist.",
});
}
throw new DatabaseFetchError({
message: "Could not set ticket to used - database operation failed",
});
}
const response = {
reply.send({
valid: true,
type: request.body.type,
ticketId,
purchaserData,
};
switch (request.body.type) {
case "merch":
ticketId = request.body.stripePi;
command = new UpdateItemCommand({
TableName: genericConfig.MerchStorePurchasesTableName,
Key: {
stripe_pi: { S: ticketId },
},
UpdateExpression:
"SET scannerEmail = :scanner_email, scanISOTimestamp = :scan_time",
ConditionExpression: "email = :email_val",
ExpressionAttributeValues: {
":scanner_email": { S: request.username },
":scan_time": { S: new Date().toISOString() },
":email_val": { S: request.body.email },
},
});
break;

case "ticket":
ticketId = request.body.ticketId;
command = new UpdateItemCommand({
TableName: genericConfig.TicketPurchasesTableName,
Key: {
ticket_id: { S: ticketId },
},
UpdateExpression:
"SET scannerEmail = :scanner_email, scanISOTimestamp = :scan_time",
ExpressionAttributeValues: {
":scanner_email": { S: request.username },
":scan_time": { S: new Date().toISOString() },
},
});
break;

default:
throw new ValidationError({
message: `Unknown verification type!`,
});
}
await fastify.dynamoClient.send(command);
reply.send(response);
});
request.log.info(
{ type: "audit", actor: request.username, target: ticketId },
{
type: "audit",
module: "tickets",
actor: request.username,
target: ticketId,
},
`checked in ticket of type "${request.body.type}" ${request.body.type === "merch" ? `purchased by email ${request.body.email}.` : "."}`,
);
},
Expand Down
7 changes: 6 additions & 1 deletion src/api/sqs/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,12 @@ export const provisionNewMemberHandler: SQSHandlerFunction<
});
if (updated) {
logger.info(
{ type: "audit", actor: metadata.initiator, target: email },
{
type: "audit",
module: "provisionNewMember",
actor: metadata.initiator,
target: email,
},
"marked user as a paid member.",
);
logger.info(
Expand Down
Loading
Loading