ability to remove user from org

This commit is contained in:
Milo Schwartz 2024-11-03 17:28:12 -05:00
parent 2852d62258
commit fadfaf1f0b
No known key found for this signature in database
28 changed files with 718 additions and 264 deletions

View file

@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { userInvites, userOrgs, users } from "@server/db/schema";
import { orgs, userInvites, userOrgs, users } from "@server/db/schema";
import { and, eq } from "drizzle-orm";
import response from "@server/utils/response";
import HttpCode from "@server/types/HttpCode";
@ -13,6 +13,8 @@ import { createDate, TimeSpan } from "oslo";
import config from "@server/config";
import { hashPassword } from "@server/auth/password";
import { fromError } from "zod-validation-error";
import { sendEmail } from "@server/emails";
import SendInviteLink from "@server/emails/templates/SendInviteLink";
const inviteUserParamsSchema = z.object({
orgId: z.string(),
@ -31,6 +33,8 @@ export type InviteUserResponse = {
expiresAt: number;
};
const inviteTracker: Record<string, { timestamps: number[] }> = {};
export async function inviteUser(
req: Request,
res: Response,
@ -73,6 +77,39 @@ export async function inviteUser(
);
}
const currentTime = Date.now();
const oneHourAgo = currentTime - 3600000;
if (!inviteTracker[email]) {
inviteTracker[email] = { timestamps: [] };
}
inviteTracker[email].timestamps = inviteTracker[
email
].timestamps.filter((timestamp) => timestamp > oneHourAgo);
if (inviteTracker[email].timestamps.length >= 3) {
return next(
createHttpError(
HttpCode.TOO_MANY_REQUESTS,
"User has already been invited 3 times in the last hour"
)
);
}
inviteTracker[email].timestamps.push(currentTime);
const org = await db
.select()
.from(orgs)
.where(eq(orgs.orgId, orgId))
.limit(1);
if (!org.length) {
return next(
createHttpError(HttpCode.NOT_FOUND, "Organization not found")
);
}
const existingUser = await db
.select()
.from(users)
@ -116,6 +153,21 @@ export async function inviteUser(
const inviteLink = `${config.app.base_url}/invite?token=${inviteId}-${token}`;
await sendEmail(
SendInviteLink({
email,
inviteLink,
expiresInDays: (validHours / 24).toString(),
orgName: orgId,
inviterName: req.user?.email,
}),
{
to: email,
from: config.email?.no_reply,
subject: "You're invited to join a Fossorial organization",
}
);
return response<InviteUserResponse>(res, {
data: {
inviteLink,

View file

@ -11,7 +11,7 @@ import logger from "@server/logger";
import { fromError } from "zod-validation-error";
const removeUserSchema = z.object({
userId: z.string().uuid(),
userId: z.string(),
orgId: z.string(),
});
@ -33,7 +33,6 @@ export async function removeUserOrg(
const { userId, orgId } = parsedParams.data;
// Check if the user has permission to list sites
const hasPermission = await checkUserActionPermission(
ActionsEnum.removeUser,
req
@ -56,7 +55,7 @@ export async function removeUserOrg(
data: null,
success: true,
error: false,
message: "User deleted successfully",
message: "User remove from org successfully",
status: HttpCode.OK,
});
} catch (error) {