2022-09-21 01:20:29 -07:00
|
|
|
/* eslint-disable no-param-reassign */
|
2023-01-02 08:42:32 -08:00
|
|
|
import { DeleteResult, EntityManager, FindConditions, In, Not } from 'typeorm';
|
2022-11-09 06:25:00 -08:00
|
|
|
import * as Db from '@/Db';
|
|
|
|
import { RoleService } from '@/role/role.service';
|
|
|
|
import { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
|
|
|
import { SharedCredentials } from '@db/entities/SharedCredentials';
|
|
|
|
import { User } from '@db/entities/User';
|
|
|
|
import { UserService } from '@/user/user.service';
|
2022-09-21 01:20:29 -07:00
|
|
|
import { CredentialsService } from './credentials.service';
|
|
|
|
import type { CredentialWithSharings } from './credentials.types';
|
|
|
|
|
|
|
|
export class EECredentialsService extends CredentialsService {
|
|
|
|
static async isOwned(
|
|
|
|
user: User,
|
|
|
|
credentialId: string,
|
|
|
|
): Promise<{ ownsCredential: boolean; credential?: CredentialsEntity }> {
|
|
|
|
const sharing = await this.getSharing(user, credentialId, ['credentials', 'role'], {
|
|
|
|
allowGlobalOwner: false,
|
|
|
|
});
|
|
|
|
|
|
|
|
if (!sharing || sharing.role.name !== 'owner') return { ownsCredential: false };
|
|
|
|
|
|
|
|
const { credentials: credential } = sharing;
|
|
|
|
|
|
|
|
return { ownsCredential: true, credential };
|
|
|
|
}
|
|
|
|
|
2022-11-21 23:37:52 -08:00
|
|
|
/**
|
|
|
|
* Retrieve the sharing that matches a user and a credential.
|
|
|
|
*/
|
|
|
|
static async getSharing(
|
|
|
|
user: User,
|
2023-01-02 08:42:32 -08:00
|
|
|
credentialId: string,
|
2022-11-21 23:37:52 -08:00
|
|
|
relations: string[] = ['credentials'],
|
|
|
|
{ allowGlobalOwner } = { allowGlobalOwner: true },
|
|
|
|
): Promise<SharedCredentials | undefined> {
|
2023-01-02 08:42:32 -08:00
|
|
|
const where: FindConditions<SharedCredentials> = { credentialsId: credentialId };
|
2022-11-21 23:37:52 -08:00
|
|
|
|
|
|
|
// Omit user from where if the requesting user is the global
|
|
|
|
// owner. This allows the global owner to view and delete
|
|
|
|
// credentials they don't own.
|
|
|
|
if (!allowGlobalOwner || user.globalRole.name !== 'owner') {
|
2023-01-02 08:42:32 -08:00
|
|
|
where.user = { id: user.id };
|
2022-11-21 23:37:52 -08:00
|
|
|
}
|
|
|
|
|
2023-01-02 08:42:32 -08:00
|
|
|
return Db.collections.SharedCredentials.findOne({
|
|
|
|
where,
|
|
|
|
relations,
|
|
|
|
});
|
2022-11-21 23:37:52 -08:00
|
|
|
}
|
|
|
|
|
2022-09-21 01:20:29 -07:00
|
|
|
static async getSharings(
|
|
|
|
transaction: EntityManager,
|
|
|
|
credentialId: string,
|
|
|
|
): Promise<SharedCredentials[]> {
|
2023-01-02 08:42:32 -08:00
|
|
|
const credential = await transaction.findOne(CredentialsEntity, {
|
|
|
|
where: { id: credentialId },
|
2022-09-21 01:20:29 -07:00
|
|
|
relations: ['shared'],
|
|
|
|
});
|
|
|
|
return credential?.shared ?? [];
|
|
|
|
}
|
|
|
|
|
|
|
|
static async pruneSharings(
|
|
|
|
transaction: EntityManager,
|
|
|
|
credentialId: string,
|
|
|
|
userIds: string[],
|
|
|
|
): Promise<DeleteResult> {
|
2023-01-02 08:42:32 -08:00
|
|
|
const conditions: FindConditions<SharedCredentials> = {
|
|
|
|
credentialsId: credentialId,
|
|
|
|
userId: Not(In(userIds)),
|
|
|
|
};
|
|
|
|
return transaction.delete(SharedCredentials, conditions);
|
2022-09-21 01:20:29 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static async share(
|
|
|
|
transaction: EntityManager,
|
|
|
|
credential: CredentialsEntity,
|
|
|
|
shareWithIds: string[],
|
|
|
|
): Promise<SharedCredentials[]> {
|
|
|
|
const [users, role] = await Promise.all([
|
|
|
|
UserService.getByIds(transaction, shareWithIds),
|
|
|
|
RoleService.trxGet(transaction, { scope: 'credential', name: 'user' }),
|
|
|
|
]);
|
|
|
|
|
|
|
|
const newSharedCredentials = users
|
|
|
|
.filter((user) => !user.isPending)
|
|
|
|
.map((user) =>
|
|
|
|
Db.collections.SharedCredentials.create({
|
|
|
|
credentials: credential,
|
|
|
|
user,
|
|
|
|
role,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
|
|
|
return transaction.save(newSharedCredentials);
|
|
|
|
}
|
|
|
|
|
|
|
|
static addOwnerAndSharings(
|
|
|
|
credential: CredentialsEntity & CredentialWithSharings,
|
|
|
|
): CredentialsEntity & CredentialWithSharings {
|
|
|
|
credential.ownedBy = null;
|
|
|
|
credential.sharedWith = [];
|
|
|
|
|
|
|
|
credential.shared?.forEach(({ user, role }) => {
|
|
|
|
const { id, email, firstName, lastName } = user;
|
|
|
|
|
|
|
|
if (role.name === 'owner') {
|
|
|
|
credential.ownedBy = { id, email, firstName, lastName };
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
credential.sharedWith?.push({ id, email, firstName, lastName });
|
|
|
|
});
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
delete credential.shared;
|
|
|
|
|
|
|
|
return credential;
|
|
|
|
}
|
|
|
|
}
|