mirror of
https://github.com/NginxProxyManager/nginx-proxy-manager.git
synced 2026-09-20 00:35:20 +01:00
Tokens are stateless JWTs, so changing a password left every session that the old one had opened working until its own expiry, up to a day later. That is the case the password change is meant to close: an administrator resetting a compromised account did not evict whoever was already in it. The auth row already records when the password last changed, so no migration is needed: `Access.init()` reads it alongside the user it already loads and refuses a token whose `iat` is older. Both sides are compared as whole seconds, which is all `iat` carries, so a token minted in the same second as the change is kept. Postgres stores that column to the microsecond, which is why the comparison is not done in milliseconds. It is reported as 401 rather than the usual 403 because that is what the frontend clears the session on, so the browser holding the dead token lands on the login page instead of a page full of errors, and `can()` lets that one error through unwrapped for the same reason. Only the password does this. A user row changing (a rename, an avatar, permissions) does not, and a user with no password auth row, which is what a login through an external provider looks like, is not affected.
113 lines
2.8 KiB
JavaScript
113 lines
2.8 KiB
JavaScript
import _ from "lodash";
|
|
|
|
const errs = {
|
|
PermissionError: function (_, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = "Permission Denied";
|
|
this.public = true;
|
|
this.status = 403;
|
|
},
|
|
|
|
ItemNotFoundError: function (id, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = "Not Found";
|
|
if (id) {
|
|
this.message = `Not Found - ${id}`;
|
|
}
|
|
this.public = true;
|
|
this.status = 404;
|
|
},
|
|
|
|
TokenRevokedError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.public = true;
|
|
this.status = 401;
|
|
},
|
|
|
|
AuthError: function (message, messageI18n, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.message_i18n = messageI18n;
|
|
this.public = true;
|
|
this.status = 400;
|
|
},
|
|
|
|
InternalError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.status = 500;
|
|
this.public = false;
|
|
},
|
|
|
|
InternalValidationError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.status = 400;
|
|
this.public = false;
|
|
},
|
|
|
|
ConfigurationError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.status = 400;
|
|
this.public = true;
|
|
},
|
|
|
|
CacheError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.message = message;
|
|
this.previous = previous;
|
|
this.status = 500;
|
|
this.public = false;
|
|
},
|
|
|
|
ValidationError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.public = true;
|
|
this.status = 400;
|
|
},
|
|
|
|
AssertionFailedError: function (message, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = message;
|
|
this.public = false;
|
|
this.status = 400;
|
|
},
|
|
|
|
CommandError: function (stdErr, code, previous) {
|
|
Error.captureStackTrace(this, this.constructor);
|
|
this.name = this.constructor.name;
|
|
this.previous = previous;
|
|
this.message = stdErr;
|
|
this.code = code;
|
|
this.public = false;
|
|
},
|
|
};
|
|
|
|
_.forEach(errs, (err) => {
|
|
err.prototype = Object.create(Error.prototype);
|
|
});
|
|
|
|
export default errs;
|