put user and client api endpoints under api

This commit is contained in:
Evert Prants 2022-08-29 17:51:20 +03:00
parent 1495e8092f
commit 7f523c9606
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
4 changed files with 100 additions and 25 deletions

View File

@ -1,24 +1,11 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { Client } from 'connect-redis'; import { Client } from 'connect-redis';
import { OAuth2Client } from 'src/modules/objects/oauth2-client/oauth2-client.entity';
import { User } from 'src/modules/objects/user/user.entity'; import { User } from 'src/modules/objects/user/user.entity';
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
const UNPRIVILEGED_STRIP = ['openid', 'id_token', 'management', 'implicit']; const UNPRIVILEGED_STRIP = ['openid', 'id_token', 'management', 'implicit'];
@Injectable() @Injectable()
export class AdminService { export class AdminService {
constructor(private _form: FormUtilityService) {}
public stripClientInfo(client: OAuth2Client): Partial<OAuth2Client> {
return {
...client,
owner: client.owner
? this._form.pluckObject(client.owner, ['id', 'uuid', 'username'])
: null,
} as Partial<OAuth2Client>;
}
public userHasPrivilege(user: User, privilege: string): boolean { public userHasPrivilege(user: User, privilege: string): boolean {
return user.privileges.some(({ name }) => name === privilege); return user.privileges.some(({ name }) => name === privilege);
} }

View File

@ -109,7 +109,11 @@ export class OAuth2AdminController {
user, user,
RELATIONS, RELATIONS,
); );
return unprivileged.map((item) => this._service.stripClientInfo(item));
return {
pagination: null,
list: unprivileged.map((item) => this._oaClient.stripClientInfo(item)),
};
} }
const search = options.q ? decodeURIComponent(options.q) : null; const search = options.q ? decodeURIComponent(options.q) : null;
@ -130,7 +134,7 @@ export class OAuth2AdminController {
return { return {
pagination, pagination,
list: this._form.stripObjectArray( list: this._form.stripObjectArray(
list.map((item) => this._service.stripClientInfo(item)), list.map((item) => this._oaClient.stripClientInfo(item)),
['password'], ['password'],
), ),
}; };
@ -151,7 +155,7 @@ export class OAuth2AdminController {
); );
} }
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
@Patch('clients/:id') @Patch('clients/:id')
@ -182,13 +186,13 @@ export class OAuth2AdminController {
} }
if (!Object.keys(allowedFieldsOnly).length) { if (!Object.keys(allowedFieldsOnly).length) {
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
Object.assign(client, allowedFieldsOnly); Object.assign(client, allowedFieldsOnly);
await this._oaClient.updateClient(client); await this._oaClient.updateClient(client);
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
@Post('clients/:id/new-secret') @Post('clients/:id/new-secret')
@ -213,7 +217,7 @@ export class OAuth2AdminController {
await this._oaToken.wipeClientTokens(client); await this._oaToken.wipeClientTokens(client);
await this._oaClient.wipeClientAuthorizations(client); await this._oaClient.wipeClientAuthorizations(client);
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
@Delete('clients/:id/authorizations') @Delete('clients/:id/authorizations')
@ -236,7 +240,7 @@ export class OAuth2AdminController {
await this._oaClient.wipeClientAuthorizations(client); await this._oaClient.wipeClientAuthorizations(client);
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
@Get('clients/:id/urls') @Get('clients/:id/urls')
@ -435,7 +439,7 @@ export class OAuth2AdminController {
client.picture = null; client.picture = null;
await this._oaClient.updateClient(client); await this._oaClient.updateClient(client);
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
// New client // New client
@ -487,6 +491,6 @@ export class OAuth2AdminController {
client.owner = user; client.owner = user;
await this._oaClient.updateClient(client); await this._oaClient.updateClient(client);
return this._service.stripClientInfo(client); return this._oaClient.stripClientInfo(client);
} }
} }

View File

@ -1,15 +1,80 @@
import { OAuth2AccessToken } from '@icynet/oauth2-provider';
import { Controller, Get, UseGuards } from '@nestjs/common'; import { Controller, Get, UseGuards } from '@nestjs/common';
import { Bearer } from 'src/decorators/bearer.decorator';
import { Scope } from 'src/decorators/scope.decorator';
import { CurrentUser } from 'src/decorators/user.decorator'; import { CurrentUser } from 'src/decorators/user.decorator';
import { OAuth2Guard } from 'src/guards/oauth2.guard'; import { OAuth2Guard } from 'src/guards/oauth2.guard';
import { ScopesGuard } from 'src/guards/scopes.guard';
import { ConfigurationService } from '../config/config.service';
import { OAuth2ClientService } from '../objects/oauth2-client/oauth2-client.service';
import { User } from '../objects/user/user.entity'; import { User } from '../objects/user/user.entity';
import { FormUtilityService } from '../utility/services/form-utility.service';
@Controller({ @Controller({
path: '/api', path: '/api',
}) })
export class ApiController { export class ApiController {
@Get('/') constructor(
private _config: ConfigurationService,
private _oaClient: OAuth2ClientService,
private _form: FormUtilityService,
) {}
@Get('/user')
@UseGuards(OAuth2Guard) @UseGuards(OAuth2Guard)
index(@CurrentUser() user: User) { getCurrentUser(@CurrentUser() user: User, @Scope() scopeStr: string) {
return { hello: true, user: user.username }; const scope = scopeStr.split(' ');
// Management scope allows access to basically everything anyway
const scopelessAccess = scope.includes('management');
const userData: Record<string, any> = {
id: user.id,
uuid: user.uuid,
username: user.username,
display_name: user.display_name,
// Standard claims
name: user.display_name,
preferred_username: user.username,
nickname: user.display_name,
};
if (scope.includes('email') || scopelessAccess) {
userData.email = user.email;
userData.email_verified = true;
}
if ((scope.includes('image') || scopelessAccess) && user.picture) {
userData.image = `${this._config.get('app.base_url')}/uploads/${
user.picture.file
}`;
userData.image_file = user.picture.file;
}
if (
(scope.includes('privileges') || scopelessAccess) &&
user.privileges?.length
) {
userData.privileges = user.privileges.map(({ name }) => name);
}
return userData;
}
@Get('/client')
@UseGuards(OAuth2Guard, ScopesGuard)
async getCurrentClient(@Bearer() token: OAuth2AccessToken) {
const client = await this._oaClient.getById(token.client_id, [
'urls',
'picture',
]);
return this._form.pluckObject(client, [
'title',
'description',
'client_id',
'urls',
'picture',
'verified',
]);
} }
} }

View File

@ -1,4 +1,5 @@
import { Inject, Injectable } from '@nestjs/common'; import { Inject, Injectable } from '@nestjs/common';
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
import { ILike, Repository } from 'typeorm'; import { ILike, Repository } from 'typeorm';
import { Upload } from '../upload/upload.entity'; import { Upload } from '../upload/upload.entity';
import { UploadService } from '../upload/upload.service'; import { UploadService } from '../upload/upload.service';
@ -29,6 +30,7 @@ export class OAuth2ClientService {
@Inject('CLIENT_AUTHORIZATION_REPOSITORY') @Inject('CLIENT_AUTHORIZATION_REPOSITORY')
private clientAuthRepository: Repository<OAuth2ClientAuthorization>, private clientAuthRepository: Repository<OAuth2ClientAuthorization>,
private _upload: UploadService, private _upload: UploadService,
private _form: FormUtilityService,
) {} ) {}
public async hasAuthorized( public async hasAuthorized(
@ -270,4 +272,21 @@ export class OAuth2ClientService {
await this._upload.delete(client.picture); await this._upload.delete(client.picture);
} }
} }
public stripClientInfo(client: OAuth2Client): Partial<OAuth2Client> {
return {
...client,
owner: client.owner
? this._form.pluckObject(client.owner, ['id', 'uuid', 'username'])
: null,
picture: client.picture
? this._form.pluckObject(client.picture, [
'id',
'mimetype',
'file',
'created_at',
])
: null,
} as Partial<OAuth2Client>;
}
} }