mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
feat: Add admin role to public API (no-changelog) (#7933)
## Summary Add the admin global role to the public API. This does not include porting over scopes. #### How to test the change: 1. ... ## Issues fixed Include links to Github issue or Community forum post or **Linear ticket**: > Important in order to close automatically and provide context to reviewers ... ## Review / Merge checklist - [ ] PR title and summary are descriptive. **Remember, the title automatically goes into the changelog. Use `(no-changelog)` otherwise.** ([conventions](https://github.com/n8n-io/n8n/blob/master/.github/pull_request_title_conventions.md)) - [ ] [Docs updated](https://github.com/n8n-io/n8n-docs) or follow-up ticket created. - [ ] Tests included. > A bug is not considered fixed, unless a test is added to prevent it from happening again. A feature is not complete without tests. > > *(internal)* You can use Slack commands to trigger [e2e tests](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#a39f9e5ba64a48b58a71d81c837e8227) or [deploy test instance](https://www.notion.so/n8n/How-to-use-Test-Instances-d65f49dfc51f441ea44367fb6f67eb0a?pvs=4#f6a177d32bde4b57ae2da0b8e454bfce) or [deploy early access version on Cloud](https://www.notion.so/n8n/Cloudbot-3dbe779836004972b7057bc989526998?pvs=4#fef2d36ab02247e1a0f65a74f6fb534e).
This commit is contained in:
parent
50e416d9ae
commit
4e55583715
|
@ -5,7 +5,7 @@ import Container from 'typedi';
|
|||
|
||||
export = {
|
||||
generateAudit: [
|
||||
authorize(['owner']),
|
||||
authorize(['owner', 'admin']),
|
||||
async (req: AuditRequest.Generate, res: Response): Promise<Response> => {
|
||||
try {
|
||||
const { SecurityAuditService } = await import('@/security-audit/SecurityAudit.service');
|
||||
|
|
|
@ -23,7 +23,7 @@ import { Container } from 'typedi';
|
|||
|
||||
export = {
|
||||
createCredential: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
validCredentialType,
|
||||
validCredentialsProperties,
|
||||
async (
|
||||
|
@ -47,7 +47,7 @@ export = {
|
|||
},
|
||||
],
|
||||
deleteCredential: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (
|
||||
req: CredentialRequest.Delete,
|
||||
res: express.Response,
|
||||
|
@ -55,7 +55,7 @@ export = {
|
|||
const { id: credentialId } = req.params;
|
||||
let credential: CredentialsEntity | undefined;
|
||||
|
||||
if (req.user.globalRole.name !== 'owner') {
|
||||
if (!['owner', 'admin'].includes(req.user.globalRole.name)) {
|
||||
const shared = await getSharedCredentials(req.user.id, credentialId, [
|
||||
'credentials',
|
||||
'role',
|
||||
|
@ -78,7 +78,7 @@ export = {
|
|||
],
|
||||
|
||||
getCredentialType: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: CredentialTypeRequest.Get, res: express.Response): Promise<express.Response> => {
|
||||
const { credentialTypeName } = req.params;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { ExecutionRepository } from '@db/repositories/execution.repository';
|
|||
|
||||
export = {
|
||||
deleteExecution: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: ExecutionRequest.Delete, res: express.Response): Promise<express.Response> => {
|
||||
const sharedWorkflowsIds = await getSharedWorkflowIds(req.user);
|
||||
|
||||
|
@ -42,7 +42,7 @@ export = {
|
|||
},
|
||||
],
|
||||
getExecution: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: ExecutionRequest.Get, res: express.Response): Promise<express.Response> => {
|
||||
const sharedWorkflowsIds = await getSharedWorkflowIds(req.user);
|
||||
|
||||
|
@ -71,7 +71,7 @@ export = {
|
|||
},
|
||||
],
|
||||
getExecutions: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
validCursor,
|
||||
async (req: ExecutionRequest.GetAll, res: express.Response): Promise<express.Response> => {
|
||||
const {
|
||||
|
|
|
@ -14,7 +14,7 @@ import { InternalHooks } from '@/InternalHooks';
|
|||
|
||||
export = {
|
||||
pull: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin']),
|
||||
async (
|
||||
req: PublicSourceControlRequest.Pull,
|
||||
res: express.Response,
|
||||
|
|
|
@ -15,7 +15,7 @@ import { InternalHooks } from '@/InternalHooks';
|
|||
export = {
|
||||
getUser: [
|
||||
validLicenseWithUserQuota,
|
||||
authorize(['owner']),
|
||||
authorize(['owner', 'admin']),
|
||||
async (req: UserRequest.Get, res: express.Response) => {
|
||||
const { includeRole = false } = req.query;
|
||||
const { id } = req.params;
|
||||
|
@ -41,7 +41,7 @@ export = {
|
|||
getUsers: [
|
||||
validLicenseWithUserQuota,
|
||||
validCursor,
|
||||
authorize(['owner']),
|
||||
authorize(['owner', 'admin']),
|
||||
async (req: UserRequest.Get, res: express.Response) => {
|
||||
const { offset = 0, limit = 100, includeRole = false } = req.query;
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ import { WorkflowHistoryService } from '@/workflows/workflowHistory/workflowHist
|
|||
|
||||
export = {
|
||||
createWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Create, res: express.Response): Promise<express.Response> => {
|
||||
const workflow = req.body;
|
||||
|
||||
|
@ -59,7 +59,7 @@ export = {
|
|||
},
|
||||
],
|
||||
deleteWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
|
||||
const { id: workflowId } = req.params;
|
||||
|
||||
|
@ -74,7 +74,7 @@ export = {
|
|||
},
|
||||
],
|
||||
getWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Get, res: express.Response): Promise<express.Response> => {
|
||||
const { id } = req.params;
|
||||
|
||||
|
@ -95,7 +95,7 @@ export = {
|
|||
},
|
||||
],
|
||||
getWorkflows: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
validCursor,
|
||||
async (req: WorkflowRequest.GetAll, res: express.Response): Promise<express.Response> => {
|
||||
const { offset = 0, limit = 100, active = undefined, tags = undefined } = req.query;
|
||||
|
@ -104,7 +104,7 @@ export = {
|
|||
...(active !== undefined && { active }),
|
||||
};
|
||||
|
||||
if (req.user.isOwner) {
|
||||
if (['owner', 'admin'].includes(req.user.globalRole.name)) {
|
||||
if (tags) {
|
||||
const workflowIds = await getWorkflowIdsViaTags(parseTagNames(tags));
|
||||
where.id = In(workflowIds);
|
||||
|
@ -152,7 +152,7 @@ export = {
|
|||
},
|
||||
],
|
||||
updateWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Update, res: express.Response): Promise<express.Response> => {
|
||||
const { id } = req.params;
|
||||
const updateData = new WorkflowEntity();
|
||||
|
@ -214,7 +214,7 @@ export = {
|
|||
},
|
||||
],
|
||||
activateWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Activate, res: express.Response): Promise<express.Response> => {
|
||||
const { id } = req.params;
|
||||
|
||||
|
@ -248,7 +248,7 @@ export = {
|
|||
},
|
||||
],
|
||||
deactivateWorkflow: [
|
||||
authorize(['owner', 'member']),
|
||||
authorize(['owner', 'admin', 'member']),
|
||||
async (req: WorkflowRequest.Activate, res: express.Response): Promise<express.Response> => {
|
||||
const { id } = req.params;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@ function insertIf(condition: boolean, elements: string[]): string[] {
|
|||
}
|
||||
|
||||
export async function getSharedWorkflowIds(user: User): Promise<string[]> {
|
||||
const where = user.globalRole.name === 'owner' ? {} : { userId: user.id };
|
||||
const where = ['owner', 'admin'].includes(user.globalRole.name) ? {} : { userId: user.id };
|
||||
const sharedWorkflows = await Container.get(SharedWorkflowRepository).find({
|
||||
where,
|
||||
select: ['workflowId'],
|
||||
|
@ -32,7 +32,7 @@ export async function getSharedWorkflow(
|
|||
): Promise<SharedWorkflow | null> {
|
||||
return Container.get(SharedWorkflowRepository).findOne({
|
||||
where: {
|
||||
...(!user.isOwner && { userId: user.id }),
|
||||
...(!['owner', 'admin'].includes(user.globalRole.name) && { userId: user.id }),
|
||||
...(workflowId && { workflowId }),
|
||||
},
|
||||
relations: [...insertIf(!config.getEnv('workflowTagsDisabled'), ['workflow.tags']), 'workflow'],
|
||||
|
@ -48,7 +48,7 @@ export async function getSharedWorkflows(
|
|||
): Promise<SharedWorkflow[]> {
|
||||
return Container.get(SharedWorkflowRepository).find({
|
||||
where: {
|
||||
...(!user.isOwner && { userId: user.id }),
|
||||
...(!['owner', 'admin'].includes(user.globalRole.name) && { userId: user.id }),
|
||||
...(options.workflowIds && { workflowId: In(options.workflowIds) }),
|
||||
},
|
||||
...(options.relations && { relations: options.relations }),
|
||||
|
|
|
@ -6,11 +6,12 @@ import { Container } from 'typedi';
|
|||
import type { AuthenticatedRequest, PaginatedRequest } from '../../../types';
|
||||
import { decodeCursor } from '../services/pagination.service';
|
||||
import { License } from '@/License';
|
||||
import type { RoleNames } from '@/databases/entities/Role';
|
||||
|
||||
const UNLIMITED_USERS_QUOTA = -1;
|
||||
|
||||
export const authorize =
|
||||
(authorizedRoles: readonly string[]) =>
|
||||
(authorizedRoles: readonly RoleNames[]) =>
|
||||
(
|
||||
req: AuthenticatedRequest,
|
||||
res: express.Response,
|
||||
|
|
Loading…
Reference in a new issue