fix some middleware nonsense
This commit is contained in:
parent
564f3427a4
commit
b02191608a
@ -44,6 +44,7 @@ async function bootstrap() {
|
||||
}
|
||||
|
||||
app.use(
|
||||
/\/((?!api).)*/,
|
||||
session({
|
||||
secret: process.env.SESSION_SECRET,
|
||||
resave: true,
|
||||
|
@ -48,6 +48,7 @@ const SET_CLIENT_FIELDS = [
|
||||
'grants',
|
||||
'activated',
|
||||
'verified',
|
||||
'urls',
|
||||
];
|
||||
|
||||
const URL_TYPES = ['redirect_uri', 'terms', 'privacy', 'website'];
|
||||
@ -167,6 +168,10 @@ export class OAuth2AdminController {
|
||||
@CurrentUser() user: User,
|
||||
) {
|
||||
const client = await this._oaClient.getById(parseInt(id, 10), []);
|
||||
const reducedPermissions = !this._service.userHasPrivilege(
|
||||
user,
|
||||
'admin:oauth2',
|
||||
);
|
||||
if (!client) {
|
||||
throw new NotFoundException('Client not found');
|
||||
}
|
||||
@ -178,9 +183,11 @@ export class OAuth2AdminController {
|
||||
}
|
||||
|
||||
const allowedFieldsOnly = this._form.pluckObject(setter, SET_CLIENT_FIELDS);
|
||||
const urls = allowedFieldsOnly.urls?.slice();
|
||||
delete allowedFieldsOnly.urls;
|
||||
|
||||
// Non-admin cannot change the activated or verified status
|
||||
if (!this._service.userHasPrivilege(user, 'admin:oauth2')) {
|
||||
if (reducedPermissions) {
|
||||
delete allowedFieldsOnly.activated;
|
||||
delete allowedFieldsOnly.verified;
|
||||
}
|
||||
@ -189,9 +196,33 @@ export class OAuth2AdminController {
|
||||
return this._oaClient.stripClientInfo(client);
|
||||
}
|
||||
|
||||
const splitGrants = allowedFieldsOnly.grants.split(' ');
|
||||
const splitScopes = allowedFieldsOnly.scope.split(' ');
|
||||
let availableGrantTypes = this._oaClient.availableGrantTypes;
|
||||
let availableScopes = this._oaClient.availableScopes;
|
||||
|
||||
if (reducedPermissions) {
|
||||
availableGrantTypes =
|
||||
this._service.removeUnprivileged(availableGrantTypes);
|
||||
availableScopes = this._service.removeUnprivileged(availableScopes);
|
||||
allowedFieldsOnly.activated = true;
|
||||
}
|
||||
|
||||
if (!splitGrants.every((grant) => availableGrantTypes.includes(grant))) {
|
||||
throw new BadRequestException('Bad grant types');
|
||||
}
|
||||
|
||||
if (!splitScopes.every((scope) => availableScopes.includes(scope))) {
|
||||
throw new BadRequestException('Bad scopes');
|
||||
}
|
||||
|
||||
Object.assign(client, allowedFieldsOnly);
|
||||
await this._oaClient.updateClient(client);
|
||||
|
||||
if (urls?.length) {
|
||||
await this._oaClient.upsertURLs(client, urls);
|
||||
}
|
||||
|
||||
return this._oaClient.stripClientInfo(client);
|
||||
}
|
||||
|
||||
@ -484,6 +515,9 @@ export class OAuth2AdminController {
|
||||
throw new BadRequestException('Bad scopes');
|
||||
}
|
||||
|
||||
const urls = setter.urls?.slice();
|
||||
delete allowedFieldsOnly.urls;
|
||||
|
||||
const client = new OAuth2Client();
|
||||
Object.assign(client, allowedFieldsOnly);
|
||||
client.client_id = this._token.createUUID();
|
||||
@ -491,6 +525,10 @@ export class OAuth2AdminController {
|
||||
client.owner = user;
|
||||
await this._oaClient.updateClient(client);
|
||||
|
||||
if (urls?.length) {
|
||||
await this._oaClient.upsertURLs(client, urls);
|
||||
}
|
||||
|
||||
return this._oaClient.stripClientInfo(client);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
Get,
|
||||
NotFoundException,
|
||||
Param,
|
||||
Patch,
|
||||
Post,
|
||||
Put,
|
||||
Query,
|
||||
@ -18,6 +19,7 @@ import { OAuth2Guard } from 'src/guards/oauth2.guard';
|
||||
import { PrivilegesGuard } from 'src/guards/privileges.guard';
|
||||
import { ScopesGuard } from 'src/guards/scopes.guard';
|
||||
import { PrivilegeService } from 'src/modules/objects/privilege/privilege.service';
|
||||
import { User } from 'src/modules/objects/user/user.entity';
|
||||
import { UserService } from 'src/modules/objects/user/user.service';
|
||||
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
|
||||
import { PaginationService } from 'src/modules/utility/services/paginate.service';
|
||||
@ -80,6 +82,32 @@ export class UserAdminController {
|
||||
return this._form.stripObject(user, ['password']);
|
||||
}
|
||||
|
||||
@Patch(':id')
|
||||
@Scopes('management')
|
||||
@Privileges('admin', 'admin:user')
|
||||
async updateUser(@Param('id') id: string, @Body() body: Partial<User>) {
|
||||
const user = await this._user.getById(parseInt(id, 10));
|
||||
if (!user) {
|
||||
throw new NotFoundException('User not found');
|
||||
}
|
||||
|
||||
const allowedFieldsOnly = this._form.pluckObject(body, [
|
||||
'display_name',
|
||||
'username',
|
||||
'email',
|
||||
'activated',
|
||||
]);
|
||||
|
||||
if (!Object.keys(allowedFieldsOnly).length) {
|
||||
throw new BadRequestException('No data was updated.');
|
||||
}
|
||||
|
||||
Object.assign(user, allowedFieldsOnly);
|
||||
await this._user.updateUser(user);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a user avatar from the server
|
||||
* @param id User ID
|
||||
@ -162,7 +190,7 @@ export class UserAdminController {
|
||||
* @param id User ID
|
||||
* @returns Success or error
|
||||
*/
|
||||
@Post(':id/activate')
|
||||
@Post(':id/activation')
|
||||
@Scopes('management')
|
||||
@Privileges('admin', 'admin:user')
|
||||
async activateUserEmail(@Param('id') id: string) {
|
||||
|
@ -69,9 +69,9 @@ export class OAuth2Service {
|
||||
public clientService: OAuth2ClientService,
|
||||
public tokenService: OAuth2TokenService,
|
||||
) {
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
this.oauth.logger.setLogLevel('debug');
|
||||
}
|
||||
// if (process.env.NODE_ENV === 'development') {
|
||||
// this.oauth.logger.setLogLevel('debug');
|
||||
// }
|
||||
}
|
||||
|
||||
public splitScope(scope: string | string[]): string[] {
|
||||
|
@ -168,6 +168,7 @@ export class OAuth2ClientService {
|
||||
: undefined,
|
||||
skip: offset,
|
||||
take: limit,
|
||||
order: { id: 'asc' },
|
||||
relations,
|
||||
});
|
||||
}
|
||||
@ -197,6 +198,7 @@ export class OAuth2ClientService {
|
||||
): Promise<OAuth2Client[]> {
|
||||
return this.clientRepository.find({
|
||||
where: { owner: { id: owner.id } },
|
||||
order: { id: 'asc' },
|
||||
relations,
|
||||
});
|
||||
}
|
||||
@ -234,6 +236,37 @@ export class OAuth2ClientService {
|
||||
}));
|
||||
}
|
||||
|
||||
public async upsertURLs(
|
||||
client: OAuth2Client,
|
||||
urls: OAuth2ClientURL[],
|
||||
): Promise<OAuth2Client> {
|
||||
const existingURLs = await this.getClientURLs(client.client_id);
|
||||
const removed = [];
|
||||
|
||||
for (const existing of existingURLs) {
|
||||
const alsoProvided = urls.find(({ id }) => id === existing.id);
|
||||
if (alsoProvided && !!alsoProvided.url) {
|
||||
Object.assign(existing, alsoProvided);
|
||||
await this.updateClientURL(existing);
|
||||
} else {
|
||||
await this.deleteClientURL(existing);
|
||||
removed.push(existing);
|
||||
}
|
||||
}
|
||||
|
||||
for (const newUrl of urls.filter((url) => !url.id)) {
|
||||
const newUrlObject = this.reobjectifyURL(newUrl, client);
|
||||
await this.updateClientURL(newUrlObject);
|
||||
existingURLs.push(newUrlObject);
|
||||
}
|
||||
|
||||
client.urls = existingURLs
|
||||
.filter(({ id }) => !removed.some((removed) => removed.id === id))
|
||||
.map((itm) => ({ ...itm, client: undefined }));
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
public async updateClient(client: OAuth2Client): Promise<OAuth2Client> {
|
||||
await this.clientRepository.save(client);
|
||||
return client;
|
||||
@ -289,4 +322,14 @@ export class OAuth2ClientService {
|
||||
: null,
|
||||
} as Partial<OAuth2Client>;
|
||||
}
|
||||
|
||||
private reobjectifyURL(
|
||||
input: Partial<OAuth2ClientURL>,
|
||||
client: OAuth2Client,
|
||||
): OAuth2ClientURL {
|
||||
const reObjectifyURL = new OAuth2ClientURL();
|
||||
Object.assign(reObjectifyURL, input);
|
||||
reObjectifyURL.client = client;
|
||||
return reObjectifyURL;
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,9 @@ import {
|
||||
NestModule,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { FlashMiddleware } from 'src/middleware/flash.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
import { ValidateCSRFMiddleware } from 'src/middleware/validate-csrf.middleware';
|
||||
import { UserTokenModule } from 'src/modules/objects/user-token/user-token.module';
|
||||
import { UserModule } from 'src/modules/objects/user/user.module';
|
||||
@ -16,6 +18,7 @@ import { LoginController } from './login.controller';
|
||||
})
|
||||
export class LoginModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(CSRFMiddleware, UserMiddleware).forRoutes(LoginController);
|
||||
consumer
|
||||
.apply(ValidateCSRFMiddleware)
|
||||
.forRoutes({ path: 'login*', method: RequestMethod.POST });
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { AuthMiddleware } from 'src/middleware/auth.middleware';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
import { ValidateCSRFMiddleware } from 'src/middleware/validate-csrf.middleware';
|
||||
import { OAuth2Module } from 'src/modules/oauth2/oauth2.module';
|
||||
import { OAuth2Service } from 'src/modules/oauth2/oauth2.service';
|
||||
@ -14,6 +16,7 @@ export class OAuth2RouterModule implements NestModule {
|
||||
constructor(private _service: OAuth2Service) {}
|
||||
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer.apply(CSRFMiddleware, UserMiddleware).forRoutes(OAuth2Controller);
|
||||
consumer.apply(this._service.oauth.express()).forRoutes('oauth2/*');
|
||||
consumer
|
||||
.apply(AuthMiddleware, ValidateCSRFMiddleware)
|
||||
|
@ -4,7 +4,9 @@ import {
|
||||
NestModule,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { FlashMiddleware } from 'src/middleware/flash.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
import { ValidateCSRFMiddleware } from 'src/middleware/validate-csrf.middleware';
|
||||
import { UserModule } from 'src/modules/objects/user/user.module';
|
||||
import { RegisterController } from './register.controller';
|
||||
@ -15,6 +17,10 @@ import { RegisterController } from './register.controller';
|
||||
})
|
||||
export class RegisterModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(CSRFMiddleware, UserMiddleware)
|
||||
.forRoutes(RegisterController);
|
||||
|
||||
consumer
|
||||
.apply(ValidateCSRFMiddleware)
|
||||
.forRoutes({ path: 'register*', method: RequestMethod.POST });
|
||||
|
@ -21,6 +21,8 @@ import { UserTokenModule } from 'src/modules/objects/user-token/user-token.modul
|
||||
import { OAuth2Module } from '../../oauth2/oauth2.module';
|
||||
import { SettingsController } from './settings.controller';
|
||||
import { SettingsService } from './settings.service';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
|
||||
@Module({
|
||||
controllers: [SettingsController],
|
||||
@ -69,6 +71,9 @@ import { SettingsService } from './settings.service';
|
||||
})
|
||||
export class SettingsModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(CSRFMiddleware, UserMiddleware)
|
||||
.forRoutes(SettingsController);
|
||||
consumer
|
||||
.apply(ValidateCSRFMiddleware)
|
||||
.forRoutes(
|
||||
|
@ -1,11 +1,4 @@
|
||||
import {
|
||||
MiddlewareConsumer,
|
||||
Module,
|
||||
NestModule,
|
||||
RequestMethod,
|
||||
} from '@nestjs/common';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
import { Module } from '@nestjs/common';
|
||||
import { ConfigurationModule } from '../config/config.module';
|
||||
import { JWTModule } from '../jwt/jwt.module';
|
||||
import { ObjectsModule } from '../objects/objects.module';
|
||||
@ -32,15 +25,4 @@ import { TwoFactorModule } from './two-factor/two-factor.module';
|
||||
providers: [],
|
||||
exports: [],
|
||||
})
|
||||
export class StaticFrontEndModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(CSRFMiddleware, UserMiddleware)
|
||||
.exclude(
|
||||
{ path: 'uploads*', method: RequestMethod.ALL },
|
||||
{ path: 'public*', method: RequestMethod.ALL },
|
||||
{ path: 'api*', method: RequestMethod.ALL },
|
||||
)
|
||||
.forRoutes('*');
|
||||
}
|
||||
}
|
||||
export class StaticFrontEndModule {}
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { MiddlewareConsumer, Module, NestModule } from '@nestjs/common';
|
||||
import { AuthMiddleware } from 'src/middleware/auth.middleware';
|
||||
import { CSRFMiddleware } from 'src/middleware/csrf.middleware';
|
||||
import { FlashMiddleware } from 'src/middleware/flash.middleware';
|
||||
import { UserMiddleware } from 'src/middleware/user.middleware';
|
||||
import { UserTokenModule } from 'src/modules/objects/user-token/user-token.module';
|
||||
import { UserModule } from 'src/modules/objects/user/user.module';
|
||||
import { TwoFactorController } from './two-factor.controller';
|
||||
@ -11,6 +13,9 @@ import { TwoFactorController } from './two-factor.controller';
|
||||
})
|
||||
export class TwoFactorModule implements NestModule {
|
||||
configure(consumer: MiddlewareConsumer) {
|
||||
consumer
|
||||
.apply(CSRFMiddleware, UserMiddleware)
|
||||
.forRoutes(TwoFactorController);
|
||||
consumer.apply(AuthMiddleware).forRoutes('account/two-factor/activate');
|
||||
consumer.apply(FlashMiddleware).forRoutes('account/two-factor/activate');
|
||||
}
|
||||
|
Reference in New Issue
Block a user