mirror of
https://github.com/formbricks/formbricks.git
synced 2026-01-01 11:20:26 -06:00
* fat: added prisma model for Tag * feat: adds api route for tags * fat: added prisma model for Tag * feat: adds mutation hook for creating a tag * feat: adds apis for creating and retrieving tags * feat: adds sample UI for creating and retrieving tags * feat: adds UI components for Combobox * feat: adds api router for fetching all tags for a product * feat: adds combobox and api for appending tag to a response * feat: adds api call for removing a tag from a response * fix: relaced normal post with swr mutations * fix: mutations for adding and deleting tags * feat: integrated the create and delete tags apis and combobox * fix: fixes api routes and db queries for tags apis * fix: fixes api routes and headers * feat: adds tag delete functionality * feat: adds update tag api and UI * feat: adds tags count api and integration * feat: inital UI for tags table * fix: UI for autosave name component * fix: fixes api response * fix: fixes errors on merge tags * fat: added prisma model for Tag * fix: replaces lodash.debounce with lodash * fix: fixes capital letter tags not getting added * fix: changed tag table to relate to environment * fix: migrated tag apis from product to environment * fix: formatting with prettier * fix: fixes tags interface in single response * fix: fixes UI bugs * fix: fixes text on no tags * fix: deleted local migrations * fix: synced migrations with main * fix: fixes combobox bugs * fix: fixes placeholder * update migrations * fix build issues * fix tag adding functionality --------- Co-authored-by: Matthias Nannt <mail@matthiasnannt.com>
148 lines
3.6 KiB
TypeScript
148 lines
3.6 KiB
TypeScript
import { authOptions } from "@/app/api/auth/[...nextauth]/authOptions";
|
|
import { prisma } from "@formbricks/database";
|
|
import { createHash } from "crypto";
|
|
import { NextApiRequest, NextApiResponse } from "next";
|
|
import type { Session } from "next-auth";
|
|
import { getServerSession } from "next-auth";
|
|
|
|
export const hashApiKey = (key: string): string => createHash("sha256").update(key).digest("hex");
|
|
|
|
export const hasEnvironmentAccess = async (
|
|
req: NextApiRequest,
|
|
res: NextApiResponse,
|
|
environmentId: string
|
|
) => {
|
|
if (req.headers["x-api-key"]) {
|
|
const ownership = await hasApiEnvironmentAccess(req.headers["x-api-key"].toString(), environmentId);
|
|
if (!ownership) {
|
|
return false;
|
|
}
|
|
} else {
|
|
const user = await getSessionUser(req, res);
|
|
if (!user) {
|
|
return false;
|
|
}
|
|
const ownership = await hasUserEnvironmentAccess(user, environmentId);
|
|
if (!ownership) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
};
|
|
|
|
export const hasUserEnvironmentAccess = async (user, environmentId) => {
|
|
const environment = await prisma.environment.findUnique({
|
|
where: {
|
|
id: environmentId,
|
|
},
|
|
select: {
|
|
product: {
|
|
select: {
|
|
team: {
|
|
select: {
|
|
memberships: {
|
|
select: {
|
|
userId: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
const environmentUsers = environment?.product.team.memberships.map((member) => member.userId) || [];
|
|
if (environmentUsers.includes(user.id)) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
export const getPlan = async (req, res) => {
|
|
if (req.headers["x-api-key"]) {
|
|
const apiKey = req.headers["x-api-key"].toString();
|
|
const apiKeyData = await prisma.apiKey.findUnique({
|
|
where: {
|
|
hashedKey: hashApiKey(apiKey),
|
|
},
|
|
select: {
|
|
environment: {
|
|
select: {
|
|
product: {
|
|
select: {
|
|
team: {
|
|
select: {
|
|
plan: true,
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
});
|
|
return apiKeyData?.environment.product.team.plan || "free";
|
|
} else {
|
|
const user = await getSessionUser(req, res);
|
|
return user ? user.plan : "free";
|
|
}
|
|
};
|
|
|
|
export const hasApiEnvironmentAccess = async (apiKey, environmentId) => {
|
|
// write function to check if the API Key has access to the environment
|
|
const apiKeyData = await prisma.apiKey.findUnique({
|
|
where: {
|
|
hashedKey: hashApiKey(apiKey),
|
|
},
|
|
select: {
|
|
environmentId: true,
|
|
},
|
|
});
|
|
|
|
if (apiKeyData?.environmentId === environmentId) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
export const hasTeamAccess = async (user, teamId) => {
|
|
const membership = await prisma.membership.findUnique({
|
|
where: {
|
|
userId_teamId: {
|
|
userId: user.id,
|
|
teamId: teamId,
|
|
},
|
|
},
|
|
});
|
|
if (membership) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
export const getSessionUser = async (req?: NextApiRequest, res?: NextApiResponse) => {
|
|
// check for session (browser usage)
|
|
let session: Session | null;
|
|
if (req && res) {
|
|
session = await getServerSession(req, res, authOptions);
|
|
} else {
|
|
session = await getServerSession(authOptions);
|
|
}
|
|
if (session && "user" in session) return session.user;
|
|
};
|
|
|
|
export const isAdminOrOwner = async (user, teamId) => {
|
|
const membership = await prisma.membership.findUnique({
|
|
where: {
|
|
userId_teamId: {
|
|
userId: user.id,
|
|
teamId: teamId,
|
|
},
|
|
},
|
|
});
|
|
if (membership && (membership.role === "admin" || membership.role === "owner")) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|