2023-07-31 02:37:09 -07:00
|
|
|
import { Service } from 'typedi';
|
|
|
|
import { CacheService } from './cache.service';
|
2023-11-10 06:04:26 -08:00
|
|
|
import { SharedWorkflowRepository } from '@db/repositories/sharedWorkflow.repository';
|
|
|
|
import type { User } from '@db/entities/User';
|
2023-08-02 23:58:36 -07:00
|
|
|
import { RoleService } from './role.service';
|
2023-08-22 06:58:05 -07:00
|
|
|
import { UserService } from './user.service';
|
2023-09-04 01:37:16 -07:00
|
|
|
import type { Credentials, ListQuery } from '@/requests';
|
2023-11-10 06:04:26 -08:00
|
|
|
import type { Role } from '@db/entities/Role';
|
|
|
|
import type { CredentialsEntity } from '@db/entities/CredentialsEntity';
|
2023-11-29 03:25:10 -08:00
|
|
|
import { ApplicationError } from 'n8n-workflow';
|
2023-07-31 02:37:09 -07:00
|
|
|
|
|
|
|
@Service()
|
|
|
|
export class OwnershipService {
|
|
|
|
constructor(
|
|
|
|
private cacheService: CacheService,
|
2023-08-22 06:58:05 -07:00
|
|
|
private userService: UserService,
|
2023-08-02 23:58:36 -07:00
|
|
|
private roleService: RoleService,
|
2023-07-31 02:37:09 -07:00
|
|
|
private sharedWorkflowRepository: SharedWorkflowRepository,
|
|
|
|
) {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Retrieve the user who owns the workflow. Note that workflow ownership is **immutable**.
|
|
|
|
*/
|
|
|
|
async getWorkflowOwnerCached(workflowId: string) {
|
2023-08-02 03:51:25 -07:00
|
|
|
const cachedValue = (await this.cacheService.get(`cache:workflow-owner:${workflowId}`)) as User;
|
2023-07-31 02:37:09 -07:00
|
|
|
|
2023-08-22 06:58:05 -07:00
|
|
|
if (cachedValue) return this.userService.create(cachedValue);
|
2023-07-31 02:37:09 -07:00
|
|
|
|
2023-08-02 23:58:36 -07:00
|
|
|
const workflowOwnerRole = await this.roleService.findWorkflowOwnerRole();
|
2023-07-31 02:37:09 -07:00
|
|
|
|
2023-11-29 03:25:10 -08:00
|
|
|
if (!workflowOwnerRole) throw new ApplicationError('Failed to find workflow owner role');
|
2023-07-31 02:37:09 -07:00
|
|
|
|
|
|
|
const sharedWorkflow = await this.sharedWorkflowRepository.findOneOrFail({
|
|
|
|
where: { workflowId, roleId: workflowOwnerRole.id },
|
|
|
|
relations: ['user', 'user.globalRole'],
|
|
|
|
});
|
|
|
|
|
|
|
|
void this.cacheService.set(`cache:workflow-owner:${workflowId}`, sharedWorkflow.user);
|
|
|
|
|
|
|
|
return sharedWorkflow.user;
|
|
|
|
}
|
2023-08-22 04:19:37 -07:00
|
|
|
|
|
|
|
addOwnedBy(
|
|
|
|
workflow: ListQuery.Workflow.WithSharing,
|
|
|
|
workflowOwnerRole: Role,
|
|
|
|
): ListQuery.Workflow.WithOwnership {
|
|
|
|
const { shared, ...rest } = workflow;
|
|
|
|
|
|
|
|
const ownerId = shared?.find((s) => s.roleId.toString() === workflowOwnerRole.id)?.userId;
|
|
|
|
|
|
|
|
return Object.assign(rest, {
|
|
|
|
ownedBy: ownerId ? { id: ownerId } : null,
|
|
|
|
});
|
|
|
|
}
|
2023-09-04 01:37:16 -07:00
|
|
|
|
|
|
|
addOwnedByAndSharedWith(_credential: CredentialsEntity): Credentials.WithOwnedByAndSharedWith {
|
|
|
|
const { shared, ...rest } = _credential;
|
|
|
|
|
|
|
|
const credential = rest as Credentials.WithOwnedByAndSharedWith;
|
|
|
|
|
|
|
|
credential.ownedBy = null;
|
|
|
|
credential.sharedWith = [];
|
|
|
|
|
|
|
|
shared?.forEach(({ user, role }) => {
|
|
|
|
const { id, email, firstName, lastName } = user;
|
|
|
|
|
|
|
|
if (role.name === 'owner') {
|
|
|
|
credential.ownedBy = { id, email, firstName, lastName };
|
|
|
|
} else {
|
|
|
|
credential.sharedWith.push({ id, email, firstName, lastName });
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return credential;
|
|
|
|
}
|
2023-07-31 02:37:09 -07:00
|
|
|
}
|