HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //opt/agentcloud/webapp/src/db/account.ts
'use strict';

import Permission from '@permission';
import * as db from 'db/index';
import { Binary,ObjectId } from 'mongodb';
import { AccountStripeData, SubscriptionPlan } from 'struct/billing';
import { InsertResult } from 'struct/db';
import { OAUTH_PROVIDER } from 'struct/oauth';

import toObjectId from '../lib/misc/toobjectid';

export type AccountTeam = {
	id: ObjectId;
	name: string;
	ownerId: ObjectId;
}

export type AccountOrg = {
	id: ObjectId;
	name: string;
	ownerId: ObjectId;
	teams: AccountTeam[];
}

// OAuth data for account
export type AccountOAuthId = string | number;
export type AccountOAuthData = {
	id: AccountOAuthId,
	// potentially more stuff here later...
}
export type OAuthRecordType = Partial<Record<OAUTH_PROVIDER,AccountOAuthData>>;

export type Account = {
	_id?: ObjectId;
	name: string;
	email?: string;
	passwordHash?: string;
	orgs: AccountOrg[];
	currentOrg: ObjectId;
	currentTeam: ObjectId;
	emailVerified: boolean;
	apiJwt?: string;
	token?: string;
	stripe?: AccountStripeData;
	oauth?: OAuthRecordType;
	permissions: Binary;
}

export function AccountCollection(): any {
	return db.db().collection('accounts');
}

export async function getAccountById(userId: db.IdOrStr): Promise<Account> {
	return AccountCollection().findOne({
		_id: toObjectId(userId)
	});
}

export async function getAccountTeamMember(userId: db.IdOrStr, teamId: db.IdOrStr): Promise<Account> {
	return AccountCollection().findOne({
		_id: toObjectId(userId),
		'orgs.teams.id': toObjectId(teamId),
	});
}

export function getAccountByEmail(email: string): Promise<Account> {
	return AccountCollection().findOne({
		email: email,
	});
}

export function getAccountByOAuthOrEmail(oauthId: AccountOAuthId, provider: OAUTH_PROVIDER, email: string): Promise<Account> {
	let query: any = {
		[`oauth.${provider}.id`]: oauthId,
	};
	if (email != null && email.length > 0) {
		query = {
			$or: [
				query,
				{ email, emailVerified: true },
			]
		};
	}
	return AccountCollection().findOne(query);
}

export function setCurrentTeam(userId: db.IdOrStr, orgId: db.IdOrStr, teamId: db.IdOrStr): Promise<Account> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$set: {
			currentOrg: toObjectId(orgId),
			currentTeam: toObjectId(teamId),
		},
	});
}

export function verifyAccount(userId: db.IdOrStr): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$set: {
			emailVerified: true,
		}
	});
}

export function changeAccountPassword(userId: db.IdOrStr, passwordHash: string): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$set: {
			passwordHash,
		}
	});
}

export function pushAccountOrg(userId: db.IdOrStr, org: AccountOrg): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$push: {
			orgs: org
		}
	});
}

export function pushAccountTeam(userId: db.IdOrStr, orgId: db.IdOrStr, team: AccountTeam): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$push: {
			'orgs.$[org].teams': team
		}
	}, {
		arrayFilters: [{
			'org.id': toObjectId(orgId)
		}]
	});
}

//NOTE: will leave dangling orgs if removed from all teams in an org, but we filter these on the FE.
export function pullAccountTeam(userId: db.IdOrStr, orgId: db.IdOrStr, teamId: db.IdOrStr): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$pull: {
			'orgs.$[org].teams': {
				id: toObjectId(teamId)
			}
		}
	}, {
		arrayFilters: [{
			'org.id': toObjectId(orgId)
		}]
	});
}

export function setAccountOauth(userId: db.IdOrStr, oauthId: AccountOAuthId, provider: OAUTH_PROVIDER): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$set: {
			oauth: {
				[provider]: { id: oauthId },
			},
		}
	});
}

export function setPlanDebug(userId: db.IdOrStr, plan: SubscriptionPlan): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId),
	}, {
		$set: {
			'stripe.stripePlan': plan,
		},
	});
}

export function setStripePlan(stripeCustomerId: string, plan: SubscriptionPlan): Promise<any> {
	return AccountCollection().updateOne({
		'stripe.stripeCustomerId': stripeCustomerId,
	}, {
		$set: {
			'stripe.stripePlan': plan,
		},
	});
}

export function setStripeCustomerId(userId: db.IdOrStr, stripeCustomerId: string): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId)
	}, {
		$set: {
			'stripe.stripeCustomerId': stripeCustomerId,
		}
	});
}

export function updateStripeCustomer(stripeCustomerId: string, update: Partial<AccountStripeData>): Promise<any> {
	return AccountCollection().updateOne({
		'stripe.stripeCustomerId': stripeCustomerId
	}, {
		$set: {
			...(update.stripeCustomerId ? { 'stripe.stripeCustomerId': update.stripeCustomerId } : {}),
			...(update.stripeEndsAt ? { 'stripe.stripeEndsAt': update.stripeEndsAt } : {}),
			...(update.stripeCancelled != null ? { 'stripe.stripeCancelled': update.stripeCancelled } : {}),
			...(update.stripePlan ? { 'stripe.stripePlan': update.stripePlan } : {}),
			...(update.stripeAddons ? { 'stripe.stripeAddons': update.stripeAddons } : {}),
			...(update.stripeTrial != null ? { 'stripe.stripeTrial': update.stripeTrial } : {})
		}
	});
}

export function setAccountPermissions(userId: db.IdOrStr, permissions: Permission): Promise<any> {
	return AccountCollection().updateOne({
		_id: toObjectId(userId),
	}, {
		$set: {
			'permissions': new Binary(permissions.array),
		}
	});
}

export function addAccount(account: Account): Promise<InsertResult> {
	return AccountCollection().insertOne(account);
}