privilege
This commit is contained in:
parent
8cff63a0a7
commit
3f399320b6
@ -9,6 +9,8 @@ dotenv.config();
|
|||||||
const CONFIG_ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'dev';
|
const CONFIG_ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'dev';
|
||||||
const CONFIG_FILENAME = process.env.CONFIG || `config.${CONFIG_ENV}.toml`;
|
const CONFIG_FILENAME = process.env.CONFIG || `config.${CONFIG_ENV}.toml`;
|
||||||
const CONFIG_PATH = join(process.cwd(), CONFIG_FILENAME);
|
const CONFIG_PATH = join(process.cwd(), CONFIG_FILENAME);
|
||||||
const config = toml.parse(readFileSync(CONFIG_PATH, { encoding: 'utf-8' }));
|
const config = JSON.parse(
|
||||||
|
JSON.stringify(toml.parse(readFileSync(CONFIG_PATH, { encoding: 'utf-8' }))),
|
||||||
|
);
|
||||||
|
|
||||||
module.exports = config.database;
|
module.exports = config.database;
|
@ -21,6 +21,7 @@ import { DatabaseModule } from './modules/objects/database/database.module';
|
|||||||
import { EmailModule } from './modules/objects/email/email.module';
|
import { EmailModule } from './modules/objects/email/email.module';
|
||||||
import { OAuth2ClientModule } from './modules/objects/oauth2-client/oauth2-client.module';
|
import { OAuth2ClientModule } from './modules/objects/oauth2-client/oauth2-client.module';
|
||||||
import { OAuth2TokenModule } from './modules/objects/oauth2-token/oauth2-token.module';
|
import { OAuth2TokenModule } from './modules/objects/oauth2-token/oauth2-token.module';
|
||||||
|
import { PrivilegeModule } from './modules/objects/privilege/privilege.module';
|
||||||
import { UploadModule } from './modules/objects/upload/upload.module';
|
import { UploadModule } from './modules/objects/upload/upload.module';
|
||||||
import { UserModule } from './modules/objects/user/user.module';
|
import { UserModule } from './modules/objects/user/user.module';
|
||||||
import { UtilityModule } from './modules/utility/utility.module';
|
import { UtilityModule } from './modules/utility/utility.module';
|
||||||
@ -48,6 +49,7 @@ import { UtilityModule } from './modules/utility/utility.module';
|
|||||||
OAuth2Module,
|
OAuth2Module,
|
||||||
TwoFactorModule,
|
TwoFactorModule,
|
||||||
SettingsModule,
|
SettingsModule,
|
||||||
|
PrivilegeModule,
|
||||||
],
|
],
|
||||||
controllers: [AppController],
|
controllers: [AppController],
|
||||||
providers: [AppService, CSRFMiddleware],
|
providers: [AppService, CSRFMiddleware],
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
--main-background: #314550;
|
--main-background: #314550;
|
||||||
--main: #2e6b81;
|
--main: #2e6b81;
|
||||||
--main-light: #519eb9;
|
--main-light: #519eb9;
|
||||||
|
--main-darkish: #006683;
|
||||||
--main-darker: #005b74;
|
--main-darker: #005b74;
|
||||||
--main-dark: #042b3a;
|
--main-dark: #042b3a;
|
||||||
|
|
||||||
|
@ -17,9 +17,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&__nav {
|
&__nav {
|
||||||
|
display: flex;
|
||||||
padding: 2rem 0rem;
|
padding: 2rem 0rem;
|
||||||
background-color: var(--main-darker);
|
background-color: var(--main-darker);
|
||||||
|
|
||||||
|
&-content {
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@ -43,13 +49,17 @@
|
|||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-right-color: var(--main-light);
|
border-right-color: var(--main-light);
|
||||||
font-weight: bold;
|
background-color: var(--main-darkish);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 4px solid var(--focus-outline);
|
outline: 4px solid var(--focus-outline);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -177,6 +187,7 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: var(--main-darker);
|
background-color: var(--main-darker);
|
||||||
box-shadow: 0px 6px 62px -14px rgba(0, 0, 0, 0.45);
|
box-shadow: 0px 6px 62px -14px rgba(0, 0, 0, 0.45);
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
& > .settings__nav-content {
|
& > .settings__nav-content {
|
||||||
display: block;
|
display: block;
|
||||||
|
30
src/fe/ts/upload.ts
Normal file
30
src/fe/ts/upload.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
export class UploadInput {
|
||||||
|
private wrap: HTMLElement;
|
||||||
|
private inner: HTMLElement;
|
||||||
|
private hover = false;
|
||||||
|
|
||||||
|
constructor(public input: HTMLInputElement) {}
|
||||||
|
|
||||||
|
initialize(): void {
|
||||||
|
this.wrap = document.createElement('div');
|
||||||
|
this.wrap.classList.add('upload__wrapper');
|
||||||
|
|
||||||
|
this.inner = document.createElement('div');
|
||||||
|
this.inner.classList.add('upload');
|
||||||
|
this.wrap.appendChild(this.inner);
|
||||||
|
|
||||||
|
this.inner.addEventListener('dragenter', () => {
|
||||||
|
this.hover = true;
|
||||||
|
this.inner.classList.add('upload--hovered');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.inner.addEventListener('dragleave', () => {
|
||||||
|
this.hover = false;
|
||||||
|
this.inner.classList.remove('upload--hovered');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.inner.addEventListener('dragover', () => {});
|
||||||
|
|
||||||
|
this.input.parentElement.appendChild(this.wrap);
|
||||||
|
}
|
||||||
|
}
|
@ -13,6 +13,7 @@ export class UserMiddleware implements NestMiddleware {
|
|||||||
// TODO: check for bans
|
// TODO: check for bans
|
||||||
const userObj = await this.userService.getByUUID(req.session.user, [
|
const userObj = await this.userService.getByUUID(req.session.user, [
|
||||||
'picture',
|
'picture',
|
||||||
|
'privileges',
|
||||||
]);
|
]);
|
||||||
if (userObj && userObj.activated) {
|
if (userObj && userObj.activated) {
|
||||||
req.user = userObj;
|
req.user = userObj;
|
||||||
|
@ -67,7 +67,7 @@ export class OAuth2Controller {
|
|||||||
const token = res.locals.accessToken as OAuth2AccessToken;
|
const token = res.locals.accessToken as OAuth2AccessToken;
|
||||||
const user = await this._service.userService.getById(
|
const user = await this._service.userService.getById(
|
||||||
token.user_id as number,
|
token.user_id as number,
|
||||||
['picture'],
|
['picture', 'privileges'],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!user) {
|
if (!user) {
|
||||||
@ -101,6 +101,13 @@ export class OAuth2Controller {
|
|||||||
userData.image_file = user.picture.file;
|
userData.image_file = user.picture.file;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
token.scope.includes('privileges') ||
|
||||||
|
(token.scope.includes('user:privileges') && user.privileges?.length)
|
||||||
|
) {
|
||||||
|
userData.privileges = user.privileges;
|
||||||
|
}
|
||||||
|
|
||||||
return userData;
|
return userData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,9 @@ import {
|
|||||||
Render,
|
Render,
|
||||||
Req,
|
Req,
|
||||||
Res,
|
Res,
|
||||||
Session,
|
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { Throttle } from '@nestjs/throttler';
|
import { Throttle } from '@nestjs/throttler';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { SessionData } from 'express-session';
|
|
||||||
import { UserService } from 'src/modules/objects/user/user.service';
|
import { UserService } from 'src/modules/objects/user/user.service';
|
||||||
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
|
import { FormUtilityService } from 'src/modules/utility/services/form-utility.service';
|
||||||
import { RegisterDto } from './register.interfaces';
|
import { RegisterDto } from './register.interfaces';
|
||||||
|
10
src/modules/objects/privilege/privilege.entity.ts
Normal file
10
src/modules/objects/privilege/privilege.entity.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';
|
||||||
|
|
||||||
|
@Entity()
|
||||||
|
export class Privilege {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ type: 'text', nullable: false })
|
||||||
|
name: string;
|
||||||
|
}
|
11
src/modules/objects/privilege/privilege.module.ts
Normal file
11
src/modules/objects/privilege/privilege.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { DatabaseModule } from '../database/database.module';
|
||||||
|
import { privilegeProviders } from './privilege.providers';
|
||||||
|
import { PrivilegeService } from './privilege.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [DatabaseModule],
|
||||||
|
providers: [...privilegeProviders, PrivilegeService],
|
||||||
|
exports: [PrivilegeService],
|
||||||
|
})
|
||||||
|
export class PrivilegeModule {}
|
10
src/modules/objects/privilege/privilege.providers.ts
Normal file
10
src/modules/objects/privilege/privilege.providers.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Connection } from 'typeorm';
|
||||||
|
import { Privilege } from './privilege.entity';
|
||||||
|
|
||||||
|
export const privilegeProviders = [
|
||||||
|
{
|
||||||
|
provide: 'PRIVILEGE_REPOSITORY',
|
||||||
|
useFactory: (connection: Connection) => connection.getRepository(Privilege),
|
||||||
|
inject: ['DATABASE_CONNECTION'],
|
||||||
|
},
|
||||||
|
];
|
11
src/modules/objects/privilege/privilege.service.ts
Normal file
11
src/modules/objects/privilege/privilege.service.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { Privilege } from './privilege.entity';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class PrivilegeService {
|
||||||
|
constructor(
|
||||||
|
@Inject('PRIVILEGE_REPOSITORY')
|
||||||
|
private privilegeRepository: Repository<Privilege>,
|
||||||
|
) {}
|
||||||
|
}
|
@ -2,11 +2,13 @@ import {
|
|||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
|
JoinTable,
|
||||||
|
ManyToMany,
|
||||||
ManyToOne,
|
ManyToOne,
|
||||||
OneToOne,
|
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
import { Privilege } from '../privilege/privilege.entity';
|
||||||
import { Upload } from '../upload/upload.entity';
|
import { Upload } from '../upload/upload.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
@ -54,4 +56,8 @@ export class User {
|
|||||||
onUpdate: 'CASCADE',
|
onUpdate: 'CASCADE',
|
||||||
})
|
})
|
||||||
public picture: Upload;
|
public picture: Upload;
|
||||||
|
|
||||||
|
@ManyToMany(() => Privilege)
|
||||||
|
@JoinTable()
|
||||||
|
public privileges: Privilege[];
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,20 @@
|
|||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
import { DatabaseModule } from '../database/database.module';
|
import { DatabaseModule } from '../database/database.module';
|
||||||
import { EmailModule } from '../email/email.module';
|
import { EmailModule } from '../email/email.module';
|
||||||
|
import { PrivilegeModule } from '../privilege/privilege.module';
|
||||||
import { UploadModule } from '../upload/upload.module';
|
import { UploadModule } from '../upload/upload.module';
|
||||||
import { UserTokenModule } from '../user-token/user-token.module';
|
import { UserTokenModule } from '../user-token/user-token.module';
|
||||||
import { userProviders } from './user.providers';
|
import { userProviders } from './user.providers';
|
||||||
import { UserService } from './user.service';
|
import { UserService } from './user.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
imports: [DatabaseModule, EmailModule, UserTokenModule, UploadModule],
|
imports: [
|
||||||
|
DatabaseModule,
|
||||||
|
EmailModule,
|
||||||
|
UserTokenModule,
|
||||||
|
UploadModule,
|
||||||
|
PrivilegeModule,
|
||||||
|
],
|
||||||
providers: [...userProviders, UserService],
|
providers: [...userProviders, UserService],
|
||||||
exports: [UserService],
|
exports: [UserService],
|
||||||
})
|
})
|
||||||
|
@ -10,11 +10,23 @@ block body
|
|||||||
.settings__nav-content
|
.settings__nav-content
|
||||||
ul
|
ul
|
||||||
li
|
li
|
||||||
a(href="/account/general", class=path === '/account/general' ? 'active' : '') General
|
a(
|
||||||
|
href="/account/general",
|
||||||
|
class=path === '/account/general' ? 'active' : ''
|
||||||
|
aria-selected=path === '/account/general' ? 'true' : 'false'
|
||||||
|
) General
|
||||||
li
|
li
|
||||||
a(href="/account/oauth2", class=path === '/account/oauth2' ? 'active' : '') Authorizations
|
a(
|
||||||
|
href="/account/oauth2",
|
||||||
|
class=path === '/account/oauth2' ? 'active' : ''
|
||||||
|
aria-selected=path === '/account/oauth2' ? 'true' : 'false'
|
||||||
|
) Authorizations
|
||||||
li
|
li
|
||||||
a(href="/account/security", class=path === '/account/security' ? 'active' : '') Security
|
a(
|
||||||
|
href="/account/security",
|
||||||
|
class=path === '/account/security' ? 'active' : ''
|
||||||
|
aria-selected=path === '/account/security' ? 'true' : 'false'
|
||||||
|
) Security
|
||||||
li
|
li
|
||||||
a(href="/account/logout?csrf=" + csrf) Log out
|
a(href="/account/logout?csrf=" + csrf) Log out
|
||||||
section.content.settings__content
|
section.content.settings__content
|
||||||
|
Reference in New Issue
Block a user