fix members

This commit is contained in:
Emily
2025-03-26 16:15:46 +01:00
parent 1f9ef5d18c
commit 7658dbe85c
11 changed files with 63 additions and 44 deletions

View File

@@ -14,7 +14,7 @@ export async function getUserProjectFromId(project_id: string, user: AuthContext
const project = await ProjectModel.findById(project_id); const project = await ProjectModel.findById(project_id);
if (!project) return; if (!project) return;
const [hasAccess, role] = await hasAccessToProject(user.id, project_id, project); const [hasAccess, role] = await hasAccessToProject(user.id, project_id, user.user.email, project);
if (!hasAccess) return; if (!hasAccess) return;
if (role === 'GUEST' && !allowGuest) return false; if (role === 'GUEST' && !allowGuest) return false;

View File

@@ -23,7 +23,7 @@ export default defineEventHandler(async event => {
...result ...result
] ]
const member = await TeamMemberModel.findOne({ project_id, user_id: data.user.id, pending: false }); const member = await TeamMemberModel.findOne({ project_id, $or: [{ user_id: user.id }, { email: user.user.email }], pending: false });
if (!member) return setResponseStatus(event, 400, 'Not a member'); if (!member) return setResponseStatus(event, 400, 'Not a member');
if (!member.permission) return setResponseStatus(event, 400, 'No permission'); if (!member.permission) return setResponseStatus(event, 400, 'No permission');

View File

@@ -11,7 +11,7 @@ export default defineEventHandler(async event => {
const project = await ProjectModel.findOne({ _id: project_id }); const project = await ProjectModel.findOne({ _id: project_id });
if (!project) return; if (!project) return;
const [hasAccess] = await hasAccessToProject(user.id, project_id, project) const [hasAccess] = await hasAccessToProject(user.id, project_id, user.user.email, project)
if (!hasAccess) return; if (!hasAccess) return;
const query = getQuery(event); const query = getQuery(event);

View File

@@ -7,7 +7,13 @@ export default defineEventHandler(async event => {
if (!userData?.logged) return []; if (!userData?.logged) return [];
const members = await TeamMemberModel.find({ user_id: userData.id, pending: false }); const members = await TeamMemberModel.find({
$or: [
{ user_id: userData.id },
{ email: userData.user.email }
],
pending: false
});
const projects: TProject[] = []; const projects: TProject[] = [];

View File

@@ -16,6 +16,7 @@ export default defineEventHandler(async event => {
if (!user) return setResponseStatus(event, 400, 'Email not found'); if (!user) return setResponseStatus(event, 400, 'Email not found');
await TeamMemberModel.deleteOne({ project_id, user_id: user.id }); await TeamMemberModel.deleteOne({ project_id, user_id: user.id });
await TeamMemberModel.deleteOne({ project_id, email: email });
return { ok: true } return { ok: true }

View File

@@ -42,8 +42,15 @@ export default defineEventHandler(async event => {
}) })
for (const member of members) { for (const member of members) {
const userMember = member.user_id ? await UserModel.findById(member.user_id) : await UserModel.findOne({ email: member.email });
if (!userMember) continue; let userMember;
if (member.user_id) {
userMember = await UserModel.findById(member.user_id);
} else {
userMember = await UserModel.findOne({ email: member.email });
}
const permission: TPermission = { const permission: TPermission = {
webAnalytics: member.permission?.webAnalytics || false, webAnalytics: member.permission?.webAnalytics || false,
@@ -54,11 +61,11 @@ export default defineEventHandler(async event => {
result.push({ result.push({
id: member.id, id: member.id,
email: userMember.email, email: userMember?.email || member.email || 'NO_EMAIL',
name: userMember.name, name: userMember?.name || 'NO_NAME',
role: member.role, role: member.role,
pending: member.pending, pending: member.pending,
me: user.id === userMember.id, me: user.id === (userMember?.id || member.user_id || 'NO_ID'),
permission permission
}) })
} }

View File

@@ -19,13 +19,18 @@ export default defineEventHandler(async event => {
webAnalytics: true webAnalytics: true
} }
const member = await TeamMemberModel.findOne({ project_id, user_id: user.id }); const member = await TeamMemberModel.findOne({
project_id,
$or: [
{ user_id: user.id }, { email: user.user.email }
]
});
if (!member) return { if (!member) return {
ai: true, ai: false,
domains: ['All domains'], domains: [],
events: true, events: false,
webAnalytics: true webAnalytics: false
} }
return { return {

View File

@@ -8,6 +8,12 @@ import { LimitNotifyModel } from "@schema/broker/LimitNotifySchema";
import { SessionModel } from "@schema/metrics/SessionSchema"; import { SessionModel } from "@schema/metrics/SessionSchema";
import StripeService from "~/server/services/StripeService"; import StripeService from "~/server/services/StripeService";
import { UserModel } from "@schema/UserSchema"; import { UserModel } from "@schema/UserSchema";
import { AddressBlacklistModel } from "~/shared/schema/shields/AddressBlacklistSchema";
import { DomainWhitelistModel } from "~/shared/schema/shields/DomainWhitelistSchema";
import { CountryBlacklistModel } from "~/shared/schema/shields/CountryBlacklistSchema";
import { BotTrafficOptionModel } from "~/shared/schema/shields/BotTrafficOptionSchema";
import { TeamMemberModel } from "~/shared/schema/TeamMemberSchema";
import { PasswordModel } from "~/shared/schema/PasswordSchema";
export default defineEventHandler(async event => { export default defineEventHandler(async event => {
@@ -19,6 +25,11 @@ export default defineEventHandler(async event => {
const premiumProjects = projects.filter(e => { return e.premium && e.premium_type != 0 }).length; const premiumProjects = projects.filter(e => { return e.premium && e.premium_type != 0 }).length;
if (premiumProjects > 0) return setResponseStatus(event, 400, 'Cannot delete an account with a premium project'); if (premiumProjects > 0) return setResponseStatus(event, 400, 'Cannot delete an account with a premium project');
const membersDeletation = await TeamMemberModel.deleteMany({ user_id: userData.id });
const membersEmailDeletation = await TeamMemberModel.deleteMany({ email: userData.user.email });
const passwordDeletation = await PasswordModel.deleteMany({ user_id: userData.id });
for (const project of projects) { for (const project of projects) {
const project_id = project._id; const project_id = project._id;
await StripeService.deleteCustomer(project.customer_id); await StripeService.deleteCustomer(project.customer_id);
@@ -28,9 +39,16 @@ export default defineEventHandler(async event => {
const limitdeletation = await ProjectLimitModel.deleteMany({ project_id }); const limitdeletation = await ProjectLimitModel.deleteMany({ project_id });
const sessionsDeletation = await SessionModel.deleteMany({ project_id }); const sessionsDeletation = await SessionModel.deleteMany({ project_id });
const notifiesDeletation = await LimitNotifyModel.deleteMany({ project_id }); const notifiesDeletation = await LimitNotifyModel.deleteMany({ project_id });
const aiChatsDeletation = await AiChatModel.deleteMany({ project_id }); const aiChatsDeletation = await AiChatModel.deleteMany({ project_id });
const userDeletation = await UserModel.deleteOne({ _id: userData.id }); //Shields
const addressBlacklistDeletation = await AddressBlacklistModel.deleteMany({ project_id });
const botTrafficOptionsDeletation = await BotTrafficOptionModel.deleteMany({ project_id });
const countryBlacklistDeletation = await CountryBlacklistModel.deleteMany({ project_id });
const domainWhitelistDeletation = await DomainWhitelistModel.deleteMany({ project_id });
const userDeletation = await UserModel.deleteOne({ _id: userData.id });
} }

View File

@@ -35,7 +35,7 @@ export type GetRequestDataOptions = {
export type RequestDataScope = 'SCHEMA' | 'ANON' | 'SLICE' | 'RANGE' | 'OFFSET' | 'DOMAIN'; export type RequestDataScope = 'SCHEMA' | 'ANON' | 'SLICE' | 'RANGE' | 'OFFSET' | 'DOMAIN';
export type RequestDataPermissions = 'WEB' | 'EVENTS' | 'AI' | 'OWNER'; export type RequestDataPermissions = 'WEB' | 'EVENTS' | 'AI' | 'OWNER';
async function getAccessPermission(user_id: string, project: TProject): Promise<TPermission> { async function getAccessPermission(user_id: string, project: TProject, email: string): Promise<TPermission> {
if (!project) return { ai: false, domains: [], events: false, webAnalytics: false } if (!project) return { ai: false, domains: [], events: false, webAnalytics: false }
//TODO: Create table with admins //TODO: Create table with admins
@@ -44,17 +44,17 @@ async function getAccessPermission(user_id: string, project: TProject): Promise<
const owner = project.owner.toString(); const owner = project.owner.toString();
const project_id = project._id; const project_id = project._id;
if (owner === user_id) return { ai: true, domains: ['All domains'], events: true, webAnalytics: true } if (owner === user_id) return { ai: true, domains: ['All domains'], events: true, webAnalytics: true }
const member = await TeamMemberModel.findOne({ project_id, user_id }, { permission: 1 }); const member = await TeamMemberModel.findOne({ project_id, $or: [{ user_id }, { email }] }, { permission: 1 });
if (!member) return { ai: false, domains: [], events: false, webAnalytics: false } if (!member) return { ai: false, domains: [], events: false, webAnalytics: false }
return { ai: false, domains: [], events: false, webAnalytics: false, ...member.permission as any } return { ai: false, domains: [], events: false, webAnalytics: false, ...member.permission as any }
} }
async function hasAccessToProject(user_id: string, project: TProject) { async function hasAccessToProject(user_id: string, project: TProject, email: string) {
if (!project) return [false, 'NONE']; if (!project) return [false, 'NONE'];
const owner = project.owner.toString(); const owner = project.owner.toString();
const project_id = project._id; const project_id = project._id;
if (owner === user_id) return [true, 'OWNER']; if (owner === user_id) return [true, 'OWNER'];
const isGuest = await TeamMemberModel.exists({ project_id, user_id }); const isGuest = await TeamMemberModel.exists({ project_id, $or: [{ user_id }, { email }] });
if (isGuest) return [true, 'GUEST']; if (isGuest) return [true, 'GUEST'];
//TODO: Create table with admins //TODO: Create table with admins
@@ -128,14 +128,14 @@ export async function getRequestData(event: H3Event<EventHandlerRequest>, requir
if (user.id != project.owner.toString()) { if (user.id != project.owner.toString()) {
if (required_permissions.includes('OWNER')) return setResponseStatus(event, 403, 'ADMIN permission required'); if (required_permissions.includes('OWNER')) return setResponseStatus(event, 403, 'ADMIN permission required');
const hasAccess = await TeamMemberModel.findOne({ project_id, user_id: user.id }); const hasAccess = await TeamMemberModel.findOne({ project_id, $or: [{ user_id: user.id }, { email: user.user.email }] });
if (!hasAccess) return setResponseStatus(event, 403, 'No permissions'); if (!hasAccess) return setResponseStatus(event, 403, 'No permissions');
} }
if (required_permissions.length > 0 || requireDomain) { if (required_permissions.length > 0 || requireDomain) {
const permission = await getAccessPermission(user.id, project); const permission = await getAccessPermission(user.id, project, user.user.email);
if (required_permissions.includes('WEB') && permission.webAnalytics === false) { if (required_permissions.includes('WEB') && permission.webAnalytics === false) {
return setResponseStatus(event, 403, 'WEB permission required'); return setResponseStatus(event, 403, 'WEB permission required');
@@ -220,7 +220,7 @@ export async function getRequestDataOld(event: H3Event<EventHandlerRequest>, opt
if (pid !== "6643cd08a1854e3b81722ab5") { if (pid !== "6643cd08a1854e3b81722ab5") {
const [hasAccess, role] = await hasAccessToProject(user.id, project); const [hasAccess, role] = await hasAccessToProject(user.id, project, user.user.email);
if (!hasAccess) return setResponseStatus(event, 400, 'no access to project'); if (!hasAccess) return setResponseStatus(event, 400, 'no access to project');
if (role === 'GUEST' && !allowGuests) return setResponseStatus(event, 403, 'only owner can access this'); if (role === 'GUEST' && !allowGuests) return setResponseStatus(event, 403, 'only owner can access this');
} else { } else {

View File

@@ -1,11 +1,11 @@
import { ProjectModel, TProject } from "@schema/project/ProjectSchema"; import { ProjectModel, TProject } from "@schema/project/ProjectSchema";
import { TeamMemberModel } from "@schema/TeamMemberSchema"; import { TeamMemberModel } from "@schema/TeamMemberSchema";
export async function hasAccessToProject(user_id: string, project_id: string, project?: TProject) { export async function hasAccessToProject(user_id: string, project_id: string, email: string, project?: TProject) {
const targetProject = project ?? await ProjectModel.findById(project_id, { owner: true }); const targetProject = project ?? await ProjectModel.findById(project_id, { owner: true });
if (!targetProject) return [false, 'NONE']; if (!targetProject) return [false, 'NONE'];
if (targetProject.owner.toString() === user_id) return [true, 'OWNER']; if (targetProject.owner.toString() === user_id) return [true, 'OWNER'];
const isGuest = await TeamMemberModel.exists({ project_id, user_id }); const isGuest = await TeamMemberModel.exists({ project_id, $or: [{ user_id }, { email }] });
if (isGuest) return [true, 'GUEST']; if (isGuest) return [true, 'GUEST'];
return [false, 'NONE']; return [false, 'NONE'];
} }

View File

@@ -1,18 +0,0 @@
import { model, Schema, Types } from 'mongoose';
export type TPageBlacklistSchema = {
_id: Schema.Types.ObjectId,
project_id: Schema.Types.ObjectId,
page: string,
description:string,
created_at: Date
}
const CountryBlacklistSchema = new Schema<TPageBlacklistSchema>({
project_id: { type: Types.ObjectId, index: 1 },
page: { type: String, required: true },
description: { type: String },
created_at: { type: Date, default: () => Date.now() },
});
export const CountryBlacklistModel = model<TPageBlacklistSchema>('country_blacklists', CountryBlacklistSchema);