diff --git a/src/api/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts
index e7b14c4f..f35411c8 100644
--- a/src/api/util/handlers/Instance.ts
+++ b/src/api/util/handlers/Instance.ts
@@ -17,6 +17,7 @@
*/
import { Session } from "@spacebar/util";
+import { Like } from "typeorm";
export async function initInstance() {
// TODO: clean up database and delete tombstone data
@@ -34,5 +35,6 @@ export async function initInstance() {
// }
// TODO: do no clear sessions for instance cluster
- await Session.clear();
+ // await Session.clear(); // This is now used as part of authentication...
+ await Session.delete({ session_id: Like("TEMP_%") }); // ...but we can still clear out temporary sessions
}
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 0c36829e..bd6653d8 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -95,15 +95,18 @@ export async function onIdentify(this: WebSocket, data: Payload) {
this.large_threshold = identify.large_threshold || 250;
const parseAndValidateTime = taskSw.getElapsedAndReset();
- const user = await tryGetUserFromToken(identify.token, {
+ const tokenData = await checkToken(identify.token, {
relations: ["relationships", "relationships.to", "settings"],
select: [...PrivateUserProjection, "relationships", "rights"],
});
+
+ const user = tokenData.user;
if (!user) {
console.log("[Gateway] Failed to identify user");
return this.close(CLOSECODES.Authentication_failed);
}
this.user_id = user.id;
+ this.session = tokenData.session;
const userQueryTime = taskSw.getElapsedAndReset();
// Check intents
@@ -126,18 +129,25 @@ export async function onIdentify(this: WebSocket, data: Payload) {
const validateIntentsAndShardingTime = taskSw.getElapsedAndReset();
// Generate a new gateway session ( id is already made, just save it in db )
- const session = Session.create({
- user_id: this.user_id,
- session_id: this.session_id,
- status: identify.presence?.status || "online",
- client_info: {
- client: identify.properties?.device || identify.properties?.$device,
- os: identify.properties?.os || identify.properties?.$os,
- version: 0,
- },
- client_status: {},
- activities: identify.presence?.activities, // TODO: validation
- });
+ this.session =
+ tokenData.session ??
+ Session.create({
+ user_id: this.user_id,
+ session_id: "TEMP_" + this.session_id,
+ });
+
+ this.session.status = identify.presence?.status || "online";
+ this.session.client_info ??= {
+ os: "Unknown",
+ client: "Unknown",
+ version: 0,
+ location: "Unknown",
+ };
+ this.session.client_info.client = identify.properties?.device ?? identify.properties?.$device ?? this.session.client_info.client;
+ this.session.client_info.os = (identify.properties?.os || identify.properties?.$os) ?? this.session.client_info.os;
+ this.session.client_status = {};
+ this.session.activities = identify.presence?.activities ?? []; // TODO: validation
+
const createSessionTime = taskSw.getElapsedAndReset();
// Get from database:
@@ -152,7 +162,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
{ result: members, elapsed: membersQueryTime },
{ result: recipients, elapsed: recipientsQueryTime },
] = await Promise.all([
- timePromise(() => session.save()),
+ timePromise(() => this.session!.save()),
timePromise(() =>
Application.findOne({
@@ -479,7 +489,7 @@ export async function onIdentify(this: WebSocket, data: Payload) {
).map((x) => ({
// TODO how is active determined?
// in our lazy request impl, we just pick the 'most relevant' session
- active: x.session_id == session.session_id,
+ active: x.session_id == this.session!.session_id,
activities: x.activities ?? [],
client_info: x.client_info,
session_id: x.session_id, // TODO: discord.com sends 'all', what is that???
@@ -501,9 +511,9 @@ export async function onIdentify(this: WebSocket, data: Payload) {
user_id: this.user_id,
data: {
user: user.toPublicUser(),
- activities: session.activities,
- client_status: session.client_status,
- status: session.getPublicStatus(),
+ activities: this.session!.activities,
+ client_status: this.session!.client_status,
+ status: this.session!.getPublicStatus(),
},
} as PresenceUpdateEvent),
),
diff --git a/src/gateway/util/WebSocket.ts b/src/gateway/util/WebSocket.ts
index d0a42eaf..cbf8a739 100644
--- a/src/gateway/util/WebSocket.ts
+++ b/src/gateway/util/WebSocket.ts
@@ -16,12 +16,10 @@
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
-import { Intents, ListenEventOpts, Permissions } from "@spacebar/util";
+import { Intents, ListenEventOpts, Permissions, Session } from "@spacebar/util";
import WS from "ws";
import { Deflate, Inflate } from "fast-zlib";
import { Capabilities } from "./Capabilities";
-import { ZstdCompress } from "zlib";
-import { ZstdDecompress } from "node:zlib";
import { Decoder, Encoder } from "@toondepauw/node-zstd";
import { QoSPayload } from "../opcodes/Heartbeat";
@@ -51,4 +49,5 @@ export interface WebSocket extends WS {
capabilities?: Capabilities;
large_threshold: number;
qos?: QoSPayload;
+ session?: Session;
}
diff --git a/src/util/entities/Session.ts b/src/util/entities/Session.ts
index 093933b8..1569543f 100644
--- a/src/util/entities/Session.ts
+++ b/src/util/entities/Session.ts
@@ -17,8 +17,8 @@
*/
import { User } from "./User";
-import { BaseClass, BaseClassWithoutId } from "./BaseClass";
-import { ClientSession, Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
+import { BaseClassWithoutId } from "./BaseClass";
+import { Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
import { ClientStatus, Status } from "../interfaces/Status";
import { Activity } from "../interfaces/Activity";
import crypto from "crypto";
diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts
index a364fa24..1f4920d8 100644
--- a/src/util/util/Token.ts
+++ b/src/util/util/Token.ts
@@ -124,7 +124,7 @@ export const checkToken = (
session.last_seen = new Date();
if (opts?.ipAddress && opts?.ipAddress !== session.last_seen_ip) {
session.last_seen_ip = opts.ipAddress;
- let ipInfo = await IpDataClient.getIpInfo(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}`;
}
await session.save();
@@ -169,6 +169,14 @@ export async function generateToken(id: string, isAdminSession: boolean = false)
session_id: randomUpperString(10), // readable at a glance
user_id: id,
is_admin_session: isAdminSession,
+ client_status: {},
+ status: "online",
+ client_info: {
+ os: "Unknown",
+ client: "Unknown",
+ version: 0,
+ location: "Unknown",
+ },
});
} while (await Session.findOne({ where: { session_id: newSession.session_id } }));
|