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

View File

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

View File

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

View File

@ -187,6 +187,7 @@
placeholder="Name"
[(ngModel)]="item.name"
(ngModelChange)="onChange($event)"
[disabled]="state.readonly"
[name]="'link_n_'+idName+i"
[id]="'link_n_'+idName+i" required>
</div>
@ -194,6 +195,7 @@
<select
[name]="'item_r_'+idName+i"
[id]="'item_r_'+idName+i"
[disabled]="state.readonly"
(ngModelChange)="onChange($event)"
class="form-select"
[(ngModel)]="item.role">
@ -206,6 +208,7 @@
type="password"
class="form-control"
[(ngModel)]="item.password"
[disabled]="state.readonly"
(ngModelChange)="onChange($event)"
[name]="'item_p_'+idName+i"
[id]="'item_p_'+idName+i"
@ -219,7 +222,7 @@
[id]="'item_p_'+idName+i">
</div>
<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)"
[ngClass]="(state.value.length > 1 || state.tags.uiOptional)? 'btn-danger':'btn-secondary'"
class="btn float-end">
@ -228,9 +231,10 @@
</div>
</div>
<div class="row me-0">
<div class="row me-0" >
<div class="col pe-0">
<button class="btn btn-primary float-end"
[disabled]="state.readonly"
(click)="AddNew()" i18n>+ Add
</button>
</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', () => {
it('should call next on authenticated', (done: () => void) => {
it('should call next on authenticated', (done: (err?: any) => void) => {
const req: any = {
session: {
user: 'A user'
@ -30,14 +30,18 @@ describe('Authentication middleware', () => {
params: {}
};
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
done();
try {
expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
};
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 = {
session: {},
sessionOptions: {},
@ -46,9 +50,13 @@ describe('Authentication middleware', () => {
};
Config.Users.authenticationRequired = true;
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
done();
try {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.NOT_AUTHENTICATED);
done();
} catch (err) {
done(err);
}
};
AuthenticationMWs.authenticate(req, {
status: () => {
@ -114,22 +122,26 @@ describe('Authentication middleware', () => {
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 = {
session: {},
sessionOptions: {},
};
const res: any = {};
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
done();
try {
expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
};
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 = {
session: {
user: 'A user'
@ -147,7 +159,7 @@ describe('Authentication middleware', () => {
});
describe('authorise', () => {
it('should call next on authorised', (done: () => void) => {
it('should call next on authorised', (done: (err?: any) => void) => {
const req: any = {
session: {
user: {
@ -157,14 +169,18 @@ describe('Authentication middleware', () => {
sessionOptions: {}
};
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
done();
try {
expect(err).to.be.undefined;
done();
} catch (err) {
done(err);
}
};
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 = {
session: {
user: {
@ -189,7 +205,7 @@ describe('Authentication middleware', () => {
});
describe('should call input ErrorDTO next on missing...', () => {
it('body', (done: () => void) => {
it('body', (done: (err?: any) => void) => {
const req: any = {
query: {},
params: {}
@ -203,16 +219,20 @@ describe('Authentication middleware', () => {
});
it('loginCredential', (done: () => void) => {
it('loginCredential', (done: (err?: any) => void) => {
const req: any = {
body: {},
query: {},
params: {}
};
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
try {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
} catch (err) {
done(err);
}
};
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 = {
body: {loginCredential: {}},
query: {},
params: {}
};
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
try {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.INPUT_ERROR);
done();
} catch (err) {
done(err);
}
};
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 = {
body: {
loginCredential: {
@ -249,9 +273,13 @@ describe('Authentication middleware', () => {
params: {}
};
const next: any = (err: ErrorDTO) => {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
done();
try {
expect(err).not.to.be.undefined;
expect(err.code).to.be.eql(ErrorCodes.CREDENTIAL_NOT_FOUND);
done();
} catch (err) {
done(err);
}
};
ObjectManagers.getInstance().UserManager = {
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 = {
session: {},
body: {
@ -293,7 +321,7 @@ describe('Authentication middleware', () => {
describe('logout', () => {
it('should call next on logout', (done: () => void) => {
it('should call next on logout', (done: (err?: any) => void) => {
const req: any = {
session: {
user: {
@ -302,9 +330,13 @@ describe('Authentication middleware', () => {
}
};
const next: any = (err: ErrorDTO) => {
expect(err).to.be.undefined;
expect(req.user).to.be.undefined;
done();
try {
expect(err).to.be.undefined;
expect(req.user).to.be.undefined;
done();
} catch (err) {
done(err);
}
};
AuthenticationMWs.logout(req, null, next);