diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index ec4a808c..47f6ab37 100644
--- a/src/api/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -116,7 +116,7 @@ export async function Authentication(req: Request, res: Response, next: NextFunc
if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401));
try {
- const { decoded, user } = await checkToken(req.headers.authorization, {
+ const { decoded, user, session, tokenVersion } = await checkToken(req.headers.authorization, {
ipAddress: req.ip,
fingerprint: req.fingerprint,
});
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 923ff533..99a01094 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -140,34 +140,16 @@ export async function onIdentify(this: WebSocket, data: Payload) {
});
this.session.status = identify.presence?.status || "online";
+ this.session.last_seen = new Date();
this.session.client_info ??= {};
this.session.client_info.platform = identify.properties?.$device ?? identify.properties?.$device;
this.session.client_info.os = identify.properties?.os || identify.properties?.$os;
this.session.client_status = {};
this.session.activities = identify.presence?.activities ?? []; // TODO: validation
+
if (this.ipAddress && this.ipAddress !== this.session.last_seen_ip) {
this.session.last_seen_ip = this.ipAddress;
- const ipInfo = await IpDataClient.getIpInfo(this.ipAddress);
- if (ipInfo?.ip) {
- this.session.last_seen_location = `${ipInfo.emoji_flag} ${ipInfo.postal} ${ipInfo.city}, ${ipInfo.region}, ${ipInfo.country_name}`;
- this.session.last_seen_location_info = {
- is_eu: ipInfo.is_eu,
- city: ipInfo.city,
- region: ipInfo.region,
- region_code: ipInfo.region_code,
- country_name: ipInfo.country_name,
- country_code: ipInfo.country_code,
- continent_name: ipInfo.continent_name,
- continent_code: ipInfo.continent_code,
- latitude: ipInfo.latitude,
- longitude: ipInfo.longitude,
- postal: ipInfo.postal,
- calling_code: ipInfo.calling_code,
- flag: ipInfo.flag,
- emoji_flag: ipInfo.emoji_flag,
- emoji_unicode: ipInfo.emoji_unicode,
- };
- }
+ await this.session.updateIpInfo();
}
const createSessionTime = taskSw.getElapsedAndReset();
@@ -179,12 +161,14 @@ export async function onIdentify(this: WebSocket, data: Payload) {
// * the bot application, if it exists
const [
{ elapsed: sessionSaveTime },
+ { elapsed: ipInfoUpdateTime },
{ result: application, elapsed: applicationQueryTime },
{ result: read_states, elapsed: read_statesQueryTime },
{ result: members, elapsed: membersQueryTime },
{ result: recipients, elapsed: recipientsQueryTime },
] = await Promise.all([
timePromise(() => this.session!.save()),
+ updateIpInfoPromise ? updateIpInfoPromise : { elapsed: new ElapsedTime(0n) },
timePromise(() =>
Application.findOne({
@@ -505,9 +489,9 @@ export async function onIdentify(this: WebSocket, data: Payload) {
// Send SESSIONS_REPLACE and PRESENCE_UPDATE
const allSessions = (
await Session.find({
- where: { user_id: this.user_id }
+ where: { user_id: this.user_id, is_admin_session: false },
})
- ).map(x=>x.toPrivateGatewayDeviceInfo());
+ ).map((x) => x.toPrivateGatewayDeviceInfo());
// ).map((x) => ({
// // TODO how is active determined?
// // in our lazy request impl, we just pick the 'most relevant' session
diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts
index 3f5543fd..fa2629c0 100644
--- a/src/util/entities/Session.ts
+++ b/src/util/entities/Session.ts
@@ -23,7 +23,7 @@ import { Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, Primary
import { Activity, ClientStatus, GatewaySession, GatewaySessionClientInfo, Status } from "../interfaces";
import { randomUpperString } from "@spacebar/api";
import { IpDataIpLookupResponse } from "../util/networking/ipdata/IpDataSampleResponses";
-import { DateBuilder, TimeSpan } from "../util";
+import { DateBuilder, IpDataClient, TimeSpan } from "../util";
//TODO we need to remove all sessions on server start because if the server crashes without closing websockets it won't delete them
@@ -136,6 +136,30 @@ export class Session extends BaseClassWithoutId {
active: TimeSpan.fromDates(this.last_seen?.getTime() ?? 0, new Date().getTime()).totalMillis < inactiveTreshold,
}
}
+
+ async updateIpInfo() {
+ const ipInfo = await IpDataClient.getIpInfo(this.last_seen_ip!);
+ if (ipInfo?.ip) {
+ this.last_seen_location = `${ipInfo.emoji_flag} ${ipInfo.postal} ${ipInfo.city}, ${ipInfo.region}, ${ipInfo.country_name}`;
+ this.last_seen_location_info = {
+ is_eu: ipInfo.is_eu,
+ city: ipInfo.city,
+ region: ipInfo.region,
+ region_code: ipInfo.region_code,
+ country_name: ipInfo.country_name,
+ country_code: ipInfo.country_code,
+ continent_name: ipInfo.continent_name,
+ continent_code: ipInfo.continent_code,
+ latitude: ipInfo.latitude,
+ longitude: ipInfo.longitude,
+ postal: ipInfo.postal,
+ calling_code: ipInfo.calling_code,
+ flag: ipInfo.flag,
+ emoji_flag: ipInfo.emoji_flag,
+ emoji_unicode: ipInfo.emoji_unicode,
+ };
+ }
+ }
}
export interface ExtendedLocationInfo {
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts
index a1d0ca20..91d475df 100644
--- a/src/util/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -122,12 +122,12 @@ export const checkToken = (
if (session && TimeSpan.fromDates(session.last_seen?.getTime() ?? 0, new Date().getTime()).totalSeconds >= 15) {
session.last_seen = new Date();
+ let updateIpInfoPromise;
if (opts?.ipAddress && opts?.ipAddress !== session.last_seen_ip) {
session.last_seen_ip = opts.ipAddress;
- const ipInfo = await IpDataClient.getIpInfo(opts.ipAddress);
- if (ipInfo?.ip) session.last_seen_location = `${ipInfo.emoji_flag} ${ipInfo.postal} ${ipInfo.city}, ${ipInfo.region}, ${ipInfo.country_name}`;
+ updateIpInfoPromise = session.updateIpInfo();
}
- await session.save();
+ await Promise.all([session.save(), updateIpInfoPromise]);
}
const result: UserTokenData = {
|