mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-04 08:02:22 +00:00
Assume upstream tokens are valid if they are offline
This commit is contained in:
parent
52f3c72db6
commit
8cd5067e73
@ -45,6 +45,7 @@ export const CACHE_INTEGRATIONS = "integrations";
|
|||||||
export const CACHE_NEB = "neb";
|
export const CACHE_NEB = "neb";
|
||||||
export const CACHE_UPSTREAM = "upstream";
|
export const CACHE_UPSTREAM = "upstream";
|
||||||
export const CACHE_SCALAR_ACCOUNTS = "scalar-accounts";
|
export const CACHE_SCALAR_ACCOUNTS = "scalar-accounts";
|
||||||
|
export const CACHE_SCALAR_ONLINE_STATE = "scalar-online-state";
|
||||||
export const CACHE_WIDGET_TITLES = "widget-titles";
|
export const CACHE_WIDGET_TITLES = "widget-titles";
|
||||||
export const CACHE_FEDERATION = "federation";
|
export const CACHE_FEDERATION = "federation";
|
||||||
export const CACHE_IRC_BRIDGE = "irc-bridge";
|
export const CACHE_IRC_BRIDGE = "irc-bridge";
|
||||||
|
@ -2,6 +2,9 @@ import UserScalarToken from "./models/UserScalarToken";
|
|||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import Upstream from "./models/Upstream";
|
import Upstream from "./models/Upstream";
|
||||||
import User from "./models/User";
|
import User from "./models/User";
|
||||||
|
import { MatrixStickerBot } from "../matrix/MatrixStickerBot";
|
||||||
|
import { ScalarClient } from "../scalar/ScalarClient";
|
||||||
|
import { CACHE_SCALAR_ONLINE_STATE, Cache } from "../MemoryCache";
|
||||||
|
|
||||||
export class ScalarStore {
|
export class ScalarStore {
|
||||||
|
|
||||||
@ -17,6 +20,10 @@ export class ScalarStore {
|
|||||||
|
|
||||||
const upstreams = await Upstream.findAll();
|
const upstreams = await Upstream.findAll();
|
||||||
for (const upstream of upstreams) {
|
for (const upstream of upstreams) {
|
||||||
|
if (!await ScalarStore.isUpstreamOnline(upstream)) {
|
||||||
|
LogService.warn("ScalarStore", `Upstream ${upstream.apiUrl} is offline - assuming token is valid`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (upstreamTokenIds.indexOf(upstream.id) === -1) {
|
if (upstreamTokenIds.indexOf(upstream.id) === -1) {
|
||||||
LogService.warn("ScalarStore", "user " + userId + " is missing a scalar token for upstream " + upstream.id + " (" + upstream.name + ")");
|
LogService.warn("ScalarStore", "user " + userId + " is missing a scalar token for upstream " + upstream.id + " (" + upstream.name + ")");
|
||||||
return false;
|
return false;
|
||||||
@ -43,6 +50,76 @@ export class ScalarStore {
|
|||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async isUpstreamOnline(upstream: Upstream): Promise<boolean> {
|
||||||
|
const cache = Cache.for(CACHE_SCALAR_ONLINE_STATE);
|
||||||
|
const cacheKey = `Upstream ${upstream.id}`;
|
||||||
|
const result = cache.get(cacheKey);
|
||||||
|
if (typeof (result) === 'boolean') {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const state = ScalarStore.checkIfUpstreamOnline(upstream);
|
||||||
|
cache.put(cacheKey, state, 60 * 60 * 1000); // 1 hour
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async checkIfUpstreamOnline(upstream: Upstream): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
// The sticker bot can be used for this for now
|
||||||
|
|
||||||
|
const testUserId = await MatrixStickerBot.getUserId();
|
||||||
|
const scalarClient = new ScalarClient(upstream);
|
||||||
|
|
||||||
|
// First see if we have a token for the upstream so we can try it
|
||||||
|
const existingTokens = await UserScalarToken.findAll({
|
||||||
|
where: {isDimensionToken: false, userId: testUserId, upstreamId: upstream.id},
|
||||||
|
});
|
||||||
|
if (existingTokens && existingTokens.length) {
|
||||||
|
// Test that the token works
|
||||||
|
try {
|
||||||
|
const result = await scalarClient.getAccount(existingTokens[0].scalarToken);
|
||||||
|
if (result.user_id !== testUserId) {
|
||||||
|
// noinspection ExceptionCaughtLocallyJS
|
||||||
|
throw new Error(`Unexpected error: Upstream ${upstream.id} did not return account info for the right token`);
|
||||||
|
}
|
||||||
|
return true; // it's online
|
||||||
|
} catch (e) {
|
||||||
|
LogService.error("ScalarStore", e);
|
||||||
|
if (!isNaN(Number(e))) {
|
||||||
|
if (e === 401 || e === 403) {
|
||||||
|
LogService.info("ScalarStore", "Test user token expired");
|
||||||
|
} else {
|
||||||
|
// Assume offline
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're here, we need to register a new token
|
||||||
|
|
||||||
|
if (existingTokens && existingTokens.length) {
|
||||||
|
for (const token of existingTokens) {
|
||||||
|
await token.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const openId = await MatrixStickerBot.getOpenId();
|
||||||
|
const token = await scalarClient.register(openId);
|
||||||
|
await UserScalarToken.create({
|
||||||
|
userId: testUserId,
|
||||||
|
scalarToken: token.scalar_token,
|
||||||
|
isDimensionToken: false,
|
||||||
|
upstreamId: upstream.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch (e) {
|
||||||
|
LogService.error("ScalarStore", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private constructor() {
|
private constructor() {
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,6 +2,7 @@ import { doClientApiCall } from "./helpers";
|
|||||||
import config from "../config";
|
import config from "../config";
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
|
import { OpenId } from "../models/OpenId";
|
||||||
|
|
||||||
export interface MatrixUrlPreview {
|
export interface MatrixUrlPreview {
|
||||||
// This is really the only parameter we care about
|
// This is really the only parameter we care about
|
||||||
@ -44,6 +45,14 @@ export class MatrixLiteClient {
|
|||||||
return response['user_id'];
|
return response['user_id'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getOpenId(): Promise<OpenId> {
|
||||||
|
return await doClientApiCall(
|
||||||
|
"POST",
|
||||||
|
`/_matrix/client/r0/user/${await this.whoAmI()}/openid/request_token`,
|
||||||
|
{access_token: this.accessToken},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
public async leaveRoom(roomId: string): Promise<string> {
|
public async leaveRoom(roomId: string): Promise<string> {
|
||||||
return doClientApiCall(
|
return doClientApiCall(
|
||||||
"POST",
|
"POST",
|
||||||
|
@ -11,6 +11,7 @@ import Sticker from "../db/models/Sticker";
|
|||||||
import { MatrixLiteClient } from "./MatrixLiteClient";
|
import { MatrixLiteClient } from "./MatrixLiteClient";
|
||||||
import { Cache, CACHE_STICKERS } from "../MemoryCache";
|
import { Cache, CACHE_STICKERS } from "../MemoryCache";
|
||||||
import { LicenseMap } from "../utils/LicenseMap";
|
import { LicenseMap } from "../utils/LicenseMap";
|
||||||
|
import { OpenId } from "../models/OpenId";
|
||||||
|
|
||||||
class _MatrixStickerBot {
|
class _MatrixStickerBot {
|
||||||
|
|
||||||
@ -36,6 +37,11 @@ class _MatrixStickerBot {
|
|||||||
return this.client.getUserId();
|
return this.client.getUserId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getOpenId(): Promise<OpenId> {
|
||||||
|
const liteClient = new MatrixLiteClient(config.homeserver.accessToken);
|
||||||
|
return liteClient.getOpenId();
|
||||||
|
}
|
||||||
|
|
||||||
private async onEvent(roomId, event) {
|
private async onEvent(roomId, event) {
|
||||||
LogService.info("MatrixStickerBot", `Event ${event.type} in ${roomId}`);
|
LogService.info("MatrixStickerBot", `Event ${event.type} in ${roomId}`);
|
||||||
if (event.type !== "io.t2bot.stickers.metadata" || event.state_key !== "") return;
|
if (event.type !== "io.t2bot.stickers.metadata" || event.state_key !== "") return;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { OpenId } from "../models/OpenId";
|
import { OpenId } from "../models/OpenId";
|
||||||
import { ScalarRegisterResponse } from "../models/ScalarResponses";
|
import { ScalarAccountResponse, ScalarRegisterResponse } from "../models/ScalarResponses";
|
||||||
import * as request from "request";
|
import * as request from "request";
|
||||||
import { LogService } from "matrix-js-snippets";
|
import { LogService } from "matrix-js-snippets";
|
||||||
import Upstream from "../db/models/Upstream";
|
import Upstream from "../db/models/Upstream";
|
||||||
@ -31,4 +31,26 @@ export class ScalarClient {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getAccount(token: string): Promise<ScalarAccountResponse> {
|
||||||
|
LogService.info("ScalarClient", "Doing upstream scalar request: " + this.upstream.scalarUrl + "/account");
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request({
|
||||||
|
method: "GET",
|
||||||
|
url: this.upstream.scalarUrl + "/account",
|
||||||
|
qs: {v: SCALAR_API_VERSION, scalar_token: token},
|
||||||
|
}, (err, res, _body) => {
|
||||||
|
if (err) {
|
||||||
|
LogService.error("ScalarClient", "Error getting information for token");
|
||||||
|
LogService.error("ScalarClient", err);
|
||||||
|
reject(err);
|
||||||
|
} else if (res.statusCode !== 200) {
|
||||||
|
LogService.error("ScalarClient", "Got status code " + res.statusCode + " while getting information for token");
|
||||||
|
reject(res.statusCode);
|
||||||
|
} else {
|
||||||
|
resolve(res.body);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user