1
0
mirror of https://github.com/xuthus83/pigallery2.git synced 2025-01-14 14:43:17 +08:00

Making enforced users reflect readonly state #507

This commit is contained in:
Patrik J. Braun 2023-03-11 22:42:46 +01:00
parent b7fe8f681c
commit b3a20cf41d
6 changed files with 170 additions and 52 deletions

30
package-lock.json generated
View File

@ -27,7 +27,7 @@
"sharp": "0.31.3", "sharp": "0.31.3",
"ts-exif-parser": "0.2.2", "ts-exif-parser": "0.2.2",
"ts-node-iptc": "1.0.11", "ts-node-iptc": "1.0.11",
"typeconfig": "2.0.37", "typeconfig": "2.0.38",
"typeorm": "0.3.12", "typeorm": "0.3.12",
"xml2js": "0.4.23" "xml2js": "0.4.23"
}, },
@ -15711,9 +15711,9 @@
} }
}, },
"node_modules/minimist": { "node_modules/minimist": {
"version": "1.2.7", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": { "funding": {
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
@ -21670,11 +21670,11 @@
} }
}, },
"node_modules/typeconfig": { "node_modules/typeconfig": {
"version": "2.0.37", "version": "2.0.38",
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.0.37.tgz", "resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.0.38.tgz",
"integrity": "sha512-IB45azVLIZH1Hzn+6jWTKiGef76MqYsAf2SgaqXd+rqaFLPEOkDS/OSp0fPSlOPO4vcSEYpsmd/AgaugpVDUmA==", "integrity": "sha512-yN9rRqJQ21xAYdR/1vhv4DPurOA7DNCN7zqPDPD6ZA2fLKcNTRa2flG/z2FaQE4UuBfnQ1o96c50xeNozDMbZQ==",
"dependencies": { "dependencies": {
"minimist": "1.2.7" "minimist": "1.2.8"
} }
}, },
"node_modules/typed-assert": { "node_modules/typed-assert": {
@ -35144,9 +35144,9 @@
} }
}, },
"minimist": { "minimist": {
"version": "1.2.7", "version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="
}, },
"minipass": { "minipass": {
"version": "3.1.6", "version": "3.1.6",
@ -39736,11 +39736,11 @@
} }
}, },
"typeconfig": { "typeconfig": {
"version": "2.0.37", "version": "2.0.38",
"resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.0.37.tgz", "resolved": "https://registry.npmjs.org/typeconfig/-/typeconfig-2.0.38.tgz",
"integrity": "sha512-IB45azVLIZH1Hzn+6jWTKiGef76MqYsAf2SgaqXd+rqaFLPEOkDS/OSp0fPSlOPO4vcSEYpsmd/AgaugpVDUmA==", "integrity": "sha512-yN9rRqJQ21xAYdR/1vhv4DPurOA7DNCN7zqPDPD6ZA2fLKcNTRa2flG/z2FaQE4UuBfnQ1o96c50xeNozDMbZQ==",
"requires": { "requires": {
"minimist": "1.2.7" "minimist": "1.2.8"
} }
}, },
"typed-assert": { "typed-assert": {

View File

@ -50,7 +50,7 @@
"sharp": "0.31.3", "sharp": "0.31.3",
"ts-exif-parser": "0.2.2", "ts-exif-parser": "0.2.2",
"ts-node-iptc": "1.0.11", "ts-node-iptc": "1.0.11",
"typeconfig": "2.0.37", "typeconfig": "2.0.38",
"xml2js": "0.4.23", "xml2js": "0.4.23",
"typeorm": "0.3.12" "typeorm": "0.3.12"
}, },

View File

@ -46,7 +46,7 @@ export class SettingsMWs {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore // @ts-ignore
Config[settingsPath] = settings; Config[settingsPath] = settings;
original.save(); await original.save();
await ConfigDiagnostics.runDiagnostics(); await ConfigDiagnostics.runDiagnostics();
Logger.info(LOG_TAG, 'new config:'); Logger.info(LOG_TAG, 'new config:');
Logger.info(LOG_TAG, JSON.stringify(Config.toJSON({attachDescription: false}), null, '\t')); Logger.info(LOG_TAG, JSON.stringify(Config.toJSON({attachDescription: false}), null, '\t'));

View File

@ -187,6 +187,7 @@
placeholder="Name" placeholder="Name"
[(ngModel)]="item.name" [(ngModel)]="item.name"
(ngModelChange)="onChange($event)" (ngModelChange)="onChange($event)"
[disabled]="state.readonly"
[name]="'link_n_'+idName+i" [name]="'link_n_'+idName+i"
[id]="'link_n_'+idName+i" required> [id]="'link_n_'+idName+i" required>
</div> </div>
@ -194,6 +195,7 @@
<select <select
[name]="'item_r_'+idName+i" [name]="'item_r_'+idName+i"
[id]="'item_r_'+idName+i" [id]="'item_r_'+idName+i"
[disabled]="state.readonly"
(ngModelChange)="onChange($event)" (ngModelChange)="onChange($event)"
class="form-select" class="form-select"
[(ngModel)]="item.role"> [(ngModel)]="item.role">
@ -206,6 +208,7 @@
type="password" type="password"
class="form-control" class="form-control"
[(ngModel)]="item.password" [(ngModel)]="item.password"
[disabled]="state.readonly"
(ngModelChange)="onChange($event)" (ngModelChange)="onChange($event)"
[name]="'item_p_'+idName+i" [name]="'item_p_'+idName+i"
[id]="'item_p_'+idName+i" [id]="'item_p_'+idName+i"
@ -219,7 +222,7 @@
[id]="'item_p_'+idName+i"> [id]="'item_p_'+idName+i">
</div> </div>
<div class="col-1 pe-0"> <div class="col-1 pe-0">
<button [disabled]="(state.value.length == 1 && !state.tags.uiOptional)" <button [disabled]="(state.value.length == 1 && !state.tags.uiOptional) || state.readonly"
(click)="remove(i)" (click)="remove(i)"
[ngClass]="(state.value.length > 1 || state.tags.uiOptional)? 'btn-danger':'btn-secondary'" [ngClass]="(state.value.length > 1 || state.tags.uiOptional)? 'btn-danger':'btn-secondary'"
class="btn float-end"> class="btn float-end">
@ -228,9 +231,10 @@
</div> </div>
</div> </div>
<div class="row me-0"> <div class="row me-0" >
<div class="col pe-0"> <div class="col pe-0">
<button class="btn btn-primary float-end" <button class="btn btn-primary float-end"
[disabled]="state.readonly"
(click)="AddNew()" i18n>+ Add (click)="AddNew()" i18n>+ Add
</button> </button>
</div> </div>

View File

@ -0,0 +1,82 @@
/* eslint-disable no-unused-expressions,@typescript-eslint/no-unused-expressions */
import {expect} from 'chai';
import {ErrorDTO} from '../../../../../src/common/entities/Error';
import {ObjectManagers} from '../../../../../src/backend/model/ObjectManagers';
import {SettingsMWs} from '../../../../../src/backend/middlewares/admin/SettingsMWs';
import {ServerUserConfig} from '../../../../../src/common/config/private/PrivateConfig';
import {Config} from '../../../../../src/common/config/private/Config';
import {UserRoles} from '../../../../../src/common/entities/UserDTO';
declare const describe: any;
declare const it: any;
declare const beforeEach: any;
describe('Settings middleware', () => {
beforeEach(() => {
ObjectManagers.reset();
});
it('should save empty enforced users settings', (done: (err?: any) => void) => {
const req: any = {
session: {},
sessionOptions: {},
query: {},
params: {},
body: {
settingsPath: 'Users',
settings: new ServerUserConfig()
}
};
req.body.settings.enforcedUsers = [];
const next: any = (err: ErrorDTO) => {
try {
expect(Config.Users.enforcedUsers.length).to.be.equal(0);
done();
} catch (err) {
done(err);
}
};
SettingsMWs.updateSettings(req, null, next);
});
it('should save enforced users settings', (done: (err?: any) => void) => {
const req: any = {
session: {},
sessionOptions: {},
query: {},
params: {},
body: {
settingsPath: 'Users',
settings: {
enforcedUsers: [],
authenticationRequired: false,
unAuthenticatedUserRole: UserRoles.User
}
}
};
req.body.settings.enforcedUsers = [{name: 'Apple', password: 'Apple pass', role: UserRoles.User}];
const next2: any = (err: ErrorDTO) => {
try {
expect(Config.Users.enforcedUsers.length).to.be.equal(1);
expect(Config.Users.enforcedUsers[0].name).to.be.equal('Apple');
expect(Config.Users.enforcedUsers.length).to.be.equal(1);
Config.original().then((cfg) => {
expect(cfg.Users.enforcedUsers.length).to.be.equal(1);
expect(cfg.Users.enforcedUsers[0].name).to.be.equal('Apple');
done();
}).catch(done);
} catch (err) {
done(err);
}
};
SettingsMWs.updateSettings(req, null, next2);
});
});

View File

@ -20,7 +20,7 @@ describe('Authentication middleware', () => {
}); });
describe('authenticate', () => { describe('authenticate', () => {
it('should call next on authenticated', (done: () => void) => { it('should call next on authenticated', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: { session: {
user: 'A user' user: 'A user'
@ -30,14 +30,18 @@ describe('Authentication middleware', () => {
params: {} params: {}
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined; try {
done(); expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.authenticate(req, null, next); AuthenticationMWs.authenticate(req, null, next);
}); });
it('should call next with error on not authenticated', (done: () => void) => { it('should call next with error on not authenticated', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: {}, session: {},
sessionOptions: {}, sessionOptions: {},
@ -46,9 +50,13 @@ describe('Authentication middleware', () => {
}; };
Config.Users.authenticationRequired = true; Config.Users.authenticationRequired = true;
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined; try {
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED); expect(err).not.to.be.undefined;
done(); expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.authenticate(req, { AuthenticationMWs.authenticate(req, {
status: () => { status: () => {
@ -114,22 +122,26 @@ describe('Authentication middleware', () => {
describe('inverseAuthenticate', () => { describe('inverseAuthenticate', () => {
it('should call next with error on authenticated', (done: () => void) => { it('should call next with error on authenticated', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: {}, session: {},
sessionOptions: {}, sessionOptions: {},
}; };
const res: any = {}; const res: any = {};
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined; try {
done(); expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.inverseAuthenticate(req, null, next); AuthenticationMWs.inverseAuthenticate(req, null, next);
}); });
it('should call next error on authenticated', (done: () => void) => { it('should call next error on authenticated', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: { session: {
user: 'A user' user: 'A user'
@ -147,7 +159,7 @@ describe('Authentication middleware', () => {
}); });
describe('authorise', () => { describe('authorise', () => {
it('should call next on authorised', (done: () => void) => { it('should call next on authorised', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: { session: {
user: { user: {
@ -157,14 +169,18 @@ describe('Authentication middleware', () => {
sessionOptions: {} sessionOptions: {}
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined; try {
done(); expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.authorise(UserRoles.LimitedGuest)(req, null, next); AuthenticationMWs.authorise(UserRoles.LimitedGuest)(req, null, next);
}); });
it('should call next with error on not authorised', (done: () => void) => { it('should call next with error on not authorised', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: { session: {
user: { user: {
@ -189,7 +205,7 @@ describe('Authentication middleware', () => {
}); });
describe('should call input ErrorDTO next on missing...', () => { describe('should call input ErrorDTO next on missing...', () => {
it('body', (done: () => void) => { it('body', (done: (err?: any) => void) => {
const req: any = { const req: any = {
query: {}, query: {},
params: {} params: {}
@ -203,16 +219,20 @@ describe('Authentication middleware', () => {
}); });
it('loginCredential', (done: () => void) => { it('loginCredential', (done: (err?: any) => void) => {
const req: any = { const req: any = {
body: {}, body: {},
query: {}, query: {},
params: {} params: {}
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined; try {
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR); expect(err).not.to.be.undefined;
done(); expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.login(req, null, next); AuthenticationMWs.login(req, null, next);
@ -220,16 +240,20 @@ describe('Authentication middleware', () => {
}); });
it('loginCredential content', (done: () => void) => { it('loginCredential content', (done: (err?: any) => void) => {
const req: any = { const req: any = {
body: {loginCredential: {}}, body: {loginCredential: {}},
query: {}, query: {},
params: {} params: {}
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined; try {
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR); expect(err).not.to.be.undefined;
done(); expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.login(req, null, next); AuthenticationMWs.login(req, null, next);
@ -237,7 +261,7 @@ describe('Authentication middleware', () => {
}); });
}); });
it('should call next with error on not finding user', (done: () => void) => { it('should call next with error on not finding user', (done: (err?: any) => void) => {
const req: any = { const req: any = {
body: { body: {
loginCredential: { loginCredential: {
@ -249,9 +273,13 @@ describe('Authentication middleware', () => {
params: {} params: {}
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined; try {
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND); expect(err).not.to.be.undefined;
done(); expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
done();
} catch (err) {
done(err);
}
}; };
ObjectManagers.getInstance().UserManager = { ObjectManagers.getInstance().UserManager = {
findOne: (_: never): Promise<UserDTO> => { findOne: (_: never): Promise<UserDTO> => {
@ -263,7 +291,7 @@ describe('Authentication middleware', () => {
}); });
it('should call next with user on the session on finding user', (done: () => void) => { it('should call next with user on the session on finding user', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: {}, session: {},
body: { body: {
@ -293,7 +321,7 @@ describe('Authentication middleware', () => {
describe('logout', () => { describe('logout', () => {
it('should call next on logout', (done: () => void) => { it('should call next on logout', (done: (err?: any) => void) => {
const req: any = { const req: any = {
session: { session: {
user: { user: {
@ -302,9 +330,13 @@ describe('Authentication middleware', () => {
} }
}; };
const next: any = (err: ErrorDTO) => { const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined; try {
expect(req.user).to.be.undefined; expect(err).to.be.undefined;
done(); expect(req.user).to.be.undefined;
done();
} catch (err) {
done(err);
}
}; };
AuthenticationMWs.logout(req, null, next); AuthenticationMWs.logout(req, null, next);