Migrate major controllers and services to PostgreSQL (gpi schema), fix build errors, add file and audit log support
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
import { query } from '../config/database.js';
|
||||
|
||||
export const syncUser = async (data: { externalId: string, email: string, name: string, organizationId?: string, clerkRole?: string }) => {
|
||||
const { externalId, email, name, organizationId, clerkRole } = data;
|
||||
|
||||
let result = await query(
|
||||
`INSERT INTO gpi.users (clerk_id, email, name, role, updated_at)
|
||||
VALUES ($1, $2, $3, 'guest', NOW())
|
||||
ON CONFLICT (clerk_id) DO UPDATE SET email = EXCLUDED.email, name = EXCLUDED.name, updated_at = NOW()
|
||||
RETURNING *`,
|
||||
[externalId, email, name]
|
||||
);
|
||||
|
||||
let user = result.rows[0];
|
||||
|
||||
if (organizationId) {
|
||||
let appRole = 'guest';
|
||||
if (clerkRole === 'org:admin') appRole = 'admin';
|
||||
else if (clerkRole === 'org:member') appRole = 'user';
|
||||
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length > 0) {
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
await query(
|
||||
`INSERT INTO gpi.user_organizations (user_id, organization_id, role, updated_at)
|
||||
VALUES ($1, $2, $3, NOW())
|
||||
ON CONFLICT (user_id, organization_id) DO NOTHING`,
|
||||
[user.id, orgUuid, appRole]
|
||||
);
|
||||
|
||||
const memberResult = await query(
|
||||
'SELECT role, is_banned FROM gpi.user_organizations WHERE user_id = $1 AND organization_id = $2',
|
||||
[user.id, orgUuid]
|
||||
);
|
||||
|
||||
return {
|
||||
...user,
|
||||
organizationRole: memberResult.rows[0].role,
|
||||
organizationBanned: memberResult.rows[0].is_banned
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return user;
|
||||
};
|
||||
|
||||
export const getCurrentUser = async (externalId: string, organizationId?: string) => {
|
||||
const userResult = await query('SELECT * FROM gpi.users WHERE clerk_id = $1 OR logto_id = $1', [externalId]);
|
||||
if (userResult.rows.length === 0) return null;
|
||||
const user = userResult.rows[0];
|
||||
|
||||
if (organizationId) {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length > 0) {
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
const memberResult = await query(
|
||||
'SELECT role, is_banned FROM gpi.user_organizations WHERE user_id = $1 AND organization_id = $2',
|
||||
[user.id, orgUuid]
|
||||
);
|
||||
if (memberResult.rows.length > 0) {
|
||||
return {
|
||||
...user,
|
||||
role: memberResult.rows[0].role,
|
||||
isBanned: memberResult.rows[0].is_banned,
|
||||
organizationId
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
return user;
|
||||
};
|
||||
|
||||
export const getAllUsersInOrg = async (organizationId: string) => {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length === 0) return [];
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
const results = await query(
|
||||
`SELECT u.*, uo.role as organization_role, uo.is_banned as organization_banned, uo.id as member_id
|
||||
FROM gpi.users u
|
||||
JOIN gpi.user_organizations uo ON u.id = uo.user_id
|
||||
WHERE uo.organization_id = $1
|
||||
ORDER BY uo.created_at DESC`,
|
||||
[orgUuid]
|
||||
);
|
||||
return results.rows;
|
||||
};
|
||||
|
||||
export const updateUserRole = async (userIdOrMemberId: string, organizationId: string, role: string) => {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length === 0) return null;
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
// Try update by member_id or user_id
|
||||
const result = await query(
|
||||
'UPDATE gpi.user_organizations SET role = $1, updated_at = NOW() WHERE (id = $2 OR user_id = $2) AND organization_id = $3 RETURNING *',
|
||||
[role, userIdOrMemberId, orgUuid]
|
||||
);
|
||||
return result.rows[0];
|
||||
};
|
||||
|
||||
export const toggleBanUser = async (userIdOrMemberId: string, organizationId: string, isBanned: boolean) => {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length === 0) return null;
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
const result = await query(
|
||||
'UPDATE gpi.user_organizations SET is_banned = $1, updated_at = NOW() WHERE (id = $2 OR user_id = $2) AND organization_id = $3 RETURNING *',
|
||||
[isBanned, userIdOrMemberId, orgUuid]
|
||||
);
|
||||
return result.rows[0];
|
||||
};
|
||||
|
||||
export const heartbeat = async (userId: string) => {
|
||||
await query('UPDATE gpi.users SET last_seen_at = NOW() WHERE id = $1', [userId]);
|
||||
};
|
||||
|
||||
export const getActiveUsers = async (organizationId: string, excludeUserId?: string) => {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length === 0) return [];
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
const twoMinutesAgo = new Date(Date.now() - 2 * 60 * 1000);
|
||||
const result = await query(
|
||||
`SELECT u.id, u.name, u.email, u.last_seen_at, u.clerk_id as "externalId"
|
||||
FROM gpi.users u
|
||||
JOIN gpi.user_organizations uo ON u.id = uo.user_id
|
||||
WHERE uo.organization_id = $1 AND u.last_seen_at >= $2 AND u.id != $3`,
|
||||
[orgUuid, twoMinutesAgo, excludeUserId || '00000000-0000-0000-0000-000000000000']
|
||||
);
|
||||
return result.rows;
|
||||
};
|
||||
|
||||
export const deleteUserFromOrg = async (userIdOrMemberId: string, organizationId: string) => {
|
||||
const orgResult = await query('SELECT id FROM gpi.organizations WHERE clerk_id = $1 OR logto_id = $1', [organizationId]);
|
||||
if (orgResult.rows.length === 0) return false;
|
||||
const orgUuid = orgResult.rows[0].id;
|
||||
|
||||
const result = await query(
|
||||
'DELETE FROM gpi.user_organizations WHERE (id = $1 OR user_id = $1) AND organization_id = $2',
|
||||
[userIdOrMemberId, orgUuid]
|
||||
);
|
||||
return result.rowCount > 0;
|
||||
};
|
||||
Reference in New Issue
Block a user