126 lines
3.4 KiB
TypeScript
126 lines
3.4 KiB
TypeScript
import { OAuth2AccessToken } from '@icynet/oauth2-provider';
|
|
import {
|
|
Controller,
|
|
Get,
|
|
NotFoundException,
|
|
Param,
|
|
StreamableFile,
|
|
UseGuards,
|
|
} from '@nestjs/common';
|
|
import { join } from 'path';
|
|
import { createReadStream } from 'fs';
|
|
import { Bearer } from 'src/decorators/bearer.decorator';
|
|
import { Scope } from 'src/decorators/scope.decorator';
|
|
import { CurrentUser } from 'src/decorators/user.decorator';
|
|
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 { FormUtilityService } from '../utility/services/form-utility.service';
|
|
import { UploadService } from '../objects/upload/upload.service';
|
|
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
|
|
|
@ApiTags('api')
|
|
@Controller({
|
|
path: '/api',
|
|
})
|
|
export class ApiController {
|
|
constructor(
|
|
private _config: ConfigurationService,
|
|
private _oaClient: OAuth2ClientService,
|
|
private _form: FormUtilityService,
|
|
private _upload: UploadService,
|
|
) {}
|
|
|
|
@Get()
|
|
welcome() {
|
|
return {
|
|
welcome: { to: 'Icy Network!' },
|
|
api: true,
|
|
oauth2: {
|
|
authorizationUrl: '/oauth2/authorize',
|
|
tokenUrl: '/oauth2/token',
|
|
userUrl: '/api/user',
|
|
},
|
|
swaggerdoc: '/api/openapi',
|
|
};
|
|
}
|
|
|
|
@Get('/user')
|
|
@ApiBearerAuth()
|
|
@UseGuards(OAuth2Guard)
|
|
getCurrentUser(@CurrentUser() user: User, @Scope() scopeStr: string) {
|
|
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')
|
|
@ApiBearerAuth()
|
|
@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',
|
|
]);
|
|
}
|
|
|
|
@Get('/upload/:file')
|
|
@ApiBearerAuth()
|
|
@UseGuards(OAuth2Guard)
|
|
async sendFile(@Param('file') fileName: string) {
|
|
const cleanFile = decodeURI(fileName).replace(/(\&(.*))/, '');
|
|
const file = await this._upload.getByFile(cleanFile);
|
|
if (!file) {
|
|
throw new NotFoundException('File not found');
|
|
}
|
|
|
|
const path = join(this._upload.uploadPath, file.file);
|
|
const stream = createReadStream(path);
|
|
|
|
return new StreamableFile(stream);
|
|
}
|
|
}
|