mirror of
https://github.com/zoriya/flood.git
synced 2026-06-02 11:06:35 +00:00
server: invalidate previous tokens when user changed
This commit is contained in:
@@ -0,0 +1,28 @@
|
||||
import Users from '../../models/Users';
|
||||
|
||||
const migrationError = (err?: Error) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
}
|
||||
console.error('Migration failed. You need to reset the databases manually.');
|
||||
process.exit();
|
||||
};
|
||||
|
||||
const migration = () => {
|
||||
return Users.listUsers().then((users) => {
|
||||
return Promise.all(
|
||||
users.map(async (user) => {
|
||||
if (user.timestamp != null) {
|
||||
// No need to migrate.
|
||||
return;
|
||||
}
|
||||
|
||||
await Users.updateUser(user.username, {});
|
||||
}),
|
||||
).catch((err) => {
|
||||
migrationError(err);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export default migration;
|
||||
@@ -1,6 +1,7 @@
|
||||
import UserInDatabase2 from './UserInDatabase2';
|
||||
import UserInDatabase3 from './UserInDatabase3';
|
||||
|
||||
const migrations = [UserInDatabase2];
|
||||
const migrations = [UserInDatabase2, UserInDatabase3];
|
||||
|
||||
const migrate = () => Promise.all(migrations.map((migration) => migration()));
|
||||
|
||||
|
||||
@@ -26,7 +26,11 @@ export default (passport: PassportStatic) => {
|
||||
|
||||
Users.lookupUser(parsedResult.data.username).then(
|
||||
(user) => {
|
||||
callback(null, user);
|
||||
if (user?.timestamp <= parsedResult.data.iat + 10) {
|
||||
callback(null, user);
|
||||
} else {
|
||||
callback(new Error(), false);
|
||||
}
|
||||
},
|
||||
(err) => {
|
||||
callback(err, false);
|
||||
|
||||
@@ -37,6 +37,7 @@ class Users {
|
||||
|
||||
private configUser: UserInDatabase = {
|
||||
_id: '_config',
|
||||
timestamp: 0,
|
||||
username: '_config',
|
||||
password: '',
|
||||
client: config.configUser as ClientConnectionSettings,
|
||||
@@ -105,6 +106,7 @@ class Users {
|
||||
.insert({
|
||||
...credentials,
|
||||
password: hashed,
|
||||
timestamp: Math.ceil(Date.now() / 1000),
|
||||
})
|
||||
.catch((err) => {
|
||||
if (err.message.includes('violates the unique constraint')) {
|
||||
@@ -139,12 +141,14 @@ class Users {
|
||||
* @return {Promise<string>} - Returns new username of updated user or rejects with error.
|
||||
*/
|
||||
async updateUser(username: string, userRecordPatch: Partial<Credentials>): Promise<string> {
|
||||
const patch = userRecordPatch;
|
||||
const patch: Omit<Partial<UserInDatabase>, '_id'> = userRecordPatch;
|
||||
|
||||
if (patch.password != null) {
|
||||
patch.password = await hashPassword(patch.password);
|
||||
}
|
||||
|
||||
patch.timestamp = Math.ceil(Date.now() / 1000);
|
||||
|
||||
return this.db.update({username}, {$set: patch}, {}).then((numUsersUpdated) => {
|
||||
if (numUsersUpdated === 0) {
|
||||
throw new Error();
|
||||
@@ -165,7 +169,7 @@ class Users {
|
||||
return this.getConfigUser();
|
||||
}
|
||||
|
||||
return this.db.findOne<Credentials>({username});
|
||||
return this.db.findOne<UserInDatabase>({username});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,7 +182,7 @@ class Users {
|
||||
return [this.getConfigUser()];
|
||||
}
|
||||
|
||||
return this.db.find<Credentials>({});
|
||||
return this.db.find<UserInDatabase>({});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,7 +17,7 @@ export const credentialsSchema = object({
|
||||
|
||||
export type Credentials = zodInfer<typeof credentialsSchema>;
|
||||
|
||||
export type UserInDatabase = Required<Credentials> & {_id: string};
|
||||
export type UserInDatabase = Required<Credentials> & {_id: string; timestamp: number};
|
||||
|
||||
export const authTokenSchema = object({
|
||||
username: string(),
|
||||
|
||||
Reference in New Issue
Block a user