mirror of
				https://codeberg.org/yeentown/barkey.git
				synced 2025-11-03 23:14:13 +00:00 
			
		
		
		
	check token permissions in admin/accounts/create.ts
This commit is contained in:
		
							parent
							
								
									37ff2bb0ca
								
							
						
					
					
						commit
						ade801ec58
					
				
					 1 changed files with 46 additions and 11 deletions
				
			
		| 
						 | 
					@ -5,13 +5,14 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Injectable } from '@nestjs/common';
 | 
					import { Injectable } from '@nestjs/common';
 | 
				
			||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
 | 
					import { Endpoint } from '@/server/api/endpoint-base.js';
 | 
				
			||||||
import { MiUser } from '@/models/_.js';
 | 
					import { MiAccessToken, MiUser } from '@/models/_.js';
 | 
				
			||||||
import { SignupService } from '@/core/SignupService.js';
 | 
					import { SignupService } from '@/core/SignupService.js';
 | 
				
			||||||
import { UserEntityService } from '@/core/entities/UserEntityService.js';
 | 
					import { UserEntityService } from '@/core/entities/UserEntityService.js';
 | 
				
			||||||
import { InstanceActorService } from '@/core/InstanceActorService.js';
 | 
					import { InstanceActorService } from '@/core/InstanceActorService.js';
 | 
				
			||||||
import { localUsernameSchema, passwordSchema } from '@/models/User.js';
 | 
					import { localUsernameSchema, passwordSchema } from '@/models/User.js';
 | 
				
			||||||
import { Packed } from '@/misc/json-schema.js';
 | 
					import { Packed } from '@/misc/json-schema.js';
 | 
				
			||||||
import { RoleService } from '@/core/RoleService.js';
 | 
					import { RoleService } from '@/core/RoleService.js';
 | 
				
			||||||
 | 
					import { ApiError } from '@/server/api/error.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const meta = {
 | 
					export const meta = {
 | 
				
			||||||
	tags: ['admin'],
 | 
						tags: ['admin'],
 | 
				
			||||||
| 
						 | 
					@ -27,6 +28,35 @@ export const meta = {
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						errors: {
 | 
				
			||||||
 | 
							// From ApiCallService.ts
 | 
				
			||||||
 | 
							noCredential: {
 | 
				
			||||||
 | 
								message: 'Credential required.',
 | 
				
			||||||
 | 
								code: 'CREDENTIAL_REQUIRED',
 | 
				
			||||||
 | 
								id: '1384574d-a912-4b81-8601-c7b1c4085df1',
 | 
				
			||||||
 | 
								httpStatusCode: 401,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							noAdmin: {
 | 
				
			||||||
 | 
								message: 'You are not assigned to an administrator role.',
 | 
				
			||||||
 | 
								code: 'ROLE_PERMISSION_DENIED',
 | 
				
			||||||
 | 
								kind: 'permission',
 | 
				
			||||||
 | 
								id: 'c3d38592-54c0-429d-be96-5636b0431a61',
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							noPermission: {
 | 
				
			||||||
 | 
								message: 'Your app does not have the necessary permissions to use this endpoint.',
 | 
				
			||||||
 | 
								code: 'PERMISSION_DENIED',
 | 
				
			||||||
 | 
								kind: 'permission',
 | 
				
			||||||
 | 
								id: '1370e5b7-d4eb-4566-bb1d-7748ee6a1838',
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Required token permissions, but we need to check them manually.
 | 
				
			||||||
 | 
						// ApiCallService checks access in a way that would prevent creating the first account.
 | 
				
			||||||
 | 
						softPermissions: [
 | 
				
			||||||
 | 
							'write:admin:account',
 | 
				
			||||||
 | 
							'write:admin:approve-user',
 | 
				
			||||||
 | 
						],
 | 
				
			||||||
} as const;
 | 
					} as const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export const paramDef = {
 | 
					export const paramDef = {
 | 
				
			||||||
| 
						 | 
					@ -46,10 +76,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
				
			||||||
		private signupService: SignupService,
 | 
							private signupService: SignupService,
 | 
				
			||||||
		private instanceActorService: InstanceActorService,
 | 
							private instanceActorService: InstanceActorService,
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		super(meta, paramDef, async (ps, _me) => {
 | 
							super(meta, paramDef, async (ps, _me, token) => {
 | 
				
			||||||
			if (!await this.canCreate(_me)) {
 | 
								await this.ensurePermissions(_me, token);
 | 
				
			||||||
				throw new Error('access denied');
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			const { account, secret } = await this.signupService.signup({
 | 
								const { account, secret } = await this.signupService.signup({
 | 
				
			||||||
				username: ps.username,
 | 
									username: ps.username,
 | 
				
			||||||
| 
						 | 
					@ -69,13 +97,20 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private async canCreate(me: MiUser | null): Promise<boolean> {
 | 
						private async ensurePermissions(me: MiUser | null, token: MiAccessToken | null): Promise<void> {
 | 
				
			||||||
		// Allow the first user to be created without authentication, as part of normal setup flow
 | 
							// Tokens have scoped permissions which may be *less* than the user's official role, so we need to check.
 | 
				
			||||||
		if (!me) {
 | 
							if (token && !meta.softPermissions.every(p => token.permission.includes(p))) {
 | 
				
			||||||
			return !await this.instanceActorService.realLocalUsersPresent();
 | 
								throw new ApiError(meta.errors.noPermission);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Administrators (including root) can always create users
 | 
							// Only administrators (including root) can create users.
 | 
				
			||||||
		return await this.roleService.isAdministrator(me);
 | 
							if (me && !await this.roleService.isAdministrator(me)) {
 | 
				
			||||||
 | 
								throw new ApiError(meta.errors.noAdmin);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Anonymous access is only allowed for initial instance setup.
 | 
				
			||||||
 | 
							if (!me && await this.instanceActorService.realLocalUsersPresent()) {
 | 
				
			||||||
 | 
								throw new ApiError(meta.errors.noCredential);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue