|
|
|
|
@ -43,6 +43,7 @@ import { setStatusText } from '../../../lib/server/functions/setStatusText'; |
|
|
|
|
import { setUserAvatar } from '../../../lib/server/functions/setUserAvatar'; |
|
|
|
|
import { setUsernameWithValidation } from '../../../lib/server/functions/setUsername'; |
|
|
|
|
import { validateCustomFields } from '../../../lib/server/functions/validateCustomFields'; |
|
|
|
|
import { notifyOnUserChange, notifyOnUserChangeAsync } from '../../../lib/server/lib/notifyListener'; |
|
|
|
|
import { generateAccessToken } from '../../../lib/server/methods/createToken'; |
|
|
|
|
import { settings } from '../../../settings/server'; |
|
|
|
|
import { getURL } from '../../../utils/server/getURL'; |
|
|
|
|
@ -387,7 +388,8 @@ API.v1.addRoute( |
|
|
|
|
const lastLoggedIn = new Date(); |
|
|
|
|
lastLoggedIn.setDate(lastLoggedIn.getDate() - daysIdle); |
|
|
|
|
|
|
|
|
|
const count = (await Users.setActiveNotLoggedInAfterWithRole(lastLoggedIn, role, false)).modifiedCount; |
|
|
|
|
// since we're deactiving users that are not logged in, there is no need to send data through WS
|
|
|
|
|
const { modifiedCount: count } = await Users.setActiveNotLoggedInAfterWithRole(lastLoggedIn, role, false); |
|
|
|
|
|
|
|
|
|
return API.v1.success({ |
|
|
|
|
count, |
|
|
|
|
@ -861,14 +863,31 @@ API.v1.addRoute( |
|
|
|
|
|
|
|
|
|
// When 2FA is enable we logout all other clients
|
|
|
|
|
const xAuthToken = this.request.headers['x-auth-token'] as string; |
|
|
|
|
if (xAuthToken) { |
|
|
|
|
const hashedToken = Accounts._hashLoginToken(xAuthToken); |
|
|
|
|
if (!xAuthToken) { |
|
|
|
|
return API.v1.success(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (!(await Users.removeNonPATLoginTokensExcept(this.userId, hashedToken))) { |
|
|
|
|
throw new MeteorError('error-logging-out-other-clients', 'Error logging out other clients'); |
|
|
|
|
} |
|
|
|
|
const hashedToken = Accounts._hashLoginToken(xAuthToken); |
|
|
|
|
|
|
|
|
|
if (!(await Users.removeNonPATLoginTokensExcept(this.userId, hashedToken))) { |
|
|
|
|
throw new MeteorError('error-logging-out-other-clients', 'Error logging out other clients'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO this can be optmized so places that care about loginTokens being removed are invoked directly
|
|
|
|
|
// instead of having to listen to every watch.users event
|
|
|
|
|
void notifyOnUserChangeAsync(async () => { |
|
|
|
|
const userTokens = await Users.findOneById(this.userId, { projection: { 'services.resume.loginTokens': 1 } }); |
|
|
|
|
if (!userTokens) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
clientAction: 'updated', |
|
|
|
|
id: this.user._id, |
|
|
|
|
diff: { 'services.resume.loginTokens': userTokens.services?.resume?.loginTokens }, |
|
|
|
|
}; |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return API.v1.success(); |
|
|
|
|
}, |
|
|
|
|
}, |
|
|
|
|
@ -1021,6 +1040,12 @@ API.v1.addRoute( |
|
|
|
|
|
|
|
|
|
const me = (await Users.findOneById(this.userId, { projection: { 'services.resume.loginTokens': 1 } })) as Pick<IUser, 'services'>; |
|
|
|
|
|
|
|
|
|
void notifyOnUserChange({ |
|
|
|
|
clientAction: 'updated', |
|
|
|
|
id: this.userId, |
|
|
|
|
diff: { 'services.resume.loginTokens': me.services?.resume?.loginTokens }, |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
const token = me.services?.resume?.loginTokens?.find((token) => token.hashedToken === hashedToken); |
|
|
|
|
|
|
|
|
|
const tokenExpires = |
|
|
|
|
@ -1172,6 +1197,8 @@ API.v1.addRoute( |
|
|
|
|
throw new Meteor.Error('error-invalid-user-id', 'Invalid user id'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void notifyOnUserChange({ clientAction: 'updated', id: this.userId, diff: { 'services.resume.loginTokens': [] } }); |
|
|
|
|
|
|
|
|
|
return API.v1.success({ |
|
|
|
|
message: `User ${userId} has been logged out!`, |
|
|
|
|
}); |
|
|
|
|
@ -1242,6 +1269,8 @@ API.v1.addRoute( |
|
|
|
|
return API.v1.unauthorized(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO refactor to not update the user twice (one inside of `setStatusText` and then later just the status + statusDefault)
|
|
|
|
|
|
|
|
|
|
if (this.bodyParams.message || this.bodyParams.message === '') { |
|
|
|
|
await setStatusText(user._id, this.bodyParams.message); |
|
|
|
|
} |
|
|
|
|
|