mirror of
https://github.com/turt2live/matrix-dimension.git
synced 2024-09-02 23:21:58 +00:00
Use the right scalar route for the request
This commit is contained in:
parent
cf212d8f4e
commit
18ee47fa49
@ -51,9 +51,10 @@ export default class AccountController {
|
|||||||
/**
|
/**
|
||||||
* Registers an account to use the Integration Manager
|
* Registers an account to use the Integration Manager
|
||||||
* @param {OpenId} openId The OpenID request information.
|
* @param {OpenId} openId The OpenID request information.
|
||||||
|
* @param {string} scalarKind The kind of scalar client to use.
|
||||||
* @returns {Promise<IAccountRegisteredResponse>} Resolves when registered.
|
* @returns {Promise<IAccountRegisteredResponse>} Resolves when registered.
|
||||||
*/
|
*/
|
||||||
public async registerAccount(openId: OpenId): Promise<IAccountRegisteredResponse> {
|
public async registerAccount(openId: OpenId, scalarKind: string): Promise<IAccountRegisteredResponse> {
|
||||||
if (!openId || !openId.matrix_server_name || !openId.access_token) {
|
if (!openId || !openId.matrix_server_name || !openId.access_token) {
|
||||||
throw new ApiError(400, "Missing OpenID information");
|
throw new ApiError(400, "Missing OpenID information");
|
||||||
}
|
}
|
||||||
@ -76,7 +77,7 @@ export default class AccountController {
|
|||||||
|
|
||||||
const upstreams = await Upstream.findAll();
|
const upstreams = await Upstream.findAll();
|
||||||
await Promise.all(upstreams.map(async upstream => {
|
await Promise.all(upstreams.map(async upstream => {
|
||||||
if (!await ScalarStore.isUpstreamOnline(upstream)) {
|
if (!await ScalarStore.isUpstreamOnline(upstream, scalarKind)) {
|
||||||
LogService.warn("AccountController", `Skipping registration for ${mxUserId} on upstream ${upstream.id} (${upstream.name}) because it is offline`);
|
LogService.warn("AccountController", `Skipping registration for ${mxUserId} on upstream ${upstream.id} (${upstream.name}) because it is offline`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ import { OpenId } from "../../models/OpenId";
|
|||||||
import AccountController, { IAccountInfoResponse, IAccountRegisteredResponse } from "../controllers/AccountController";
|
import AccountController, { IAccountInfoResponse, IAccountRegisteredResponse } from "../controllers/AccountController";
|
||||||
import { AutoWired, Inject } from "typescript-ioc/es6";
|
import { AutoWired, Inject } from "typescript-ioc/es6";
|
||||||
import { IMSCUser, ROLE_MSC_USER } from "../security/MSCSecurity";
|
import { IMSCUser, ROLE_MSC_USER } from "../security/MSCSecurity";
|
||||||
|
import { ScalarClient } from "../../scalar/ScalarClient";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API for account management
|
* API for account management
|
||||||
@ -20,7 +21,7 @@ export class MSCAccountService {
|
|||||||
@POST
|
@POST
|
||||||
@Path("register")
|
@Path("register")
|
||||||
public async register(request: OpenId): Promise<IAccountRegisteredResponse> {
|
public async register(request: OpenId): Promise<IAccountRegisteredResponse> {
|
||||||
return this.accountController.registerAccount(request);
|
return this.accountController.registerAccount(request, ScalarClient.KIND_MATRIX_V1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
|
@ -7,6 +7,7 @@ import AccountController from "../controllers/AccountController";
|
|||||||
import { ROLE_MSC_USER } from "../security/MSCSecurity";
|
import { ROLE_MSC_USER } from "../security/MSCSecurity";
|
||||||
import TermsController, { ITermsNotSignedResponse } from "../controllers/TermsController";
|
import TermsController, { ITermsNotSignedResponse } from "../controllers/TermsController";
|
||||||
import { SignTermsRequest } from "../msc/MSCTermsService";
|
import { SignTermsRequest } from "../msc/MSCTermsService";
|
||||||
|
import { ScalarClient } from "../../scalar/ScalarClient";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* API for the minimum Scalar API we need to implement to be compatible with clients. Used for registration
|
* API for the minimum Scalar API we need to implement to be compatible with clients. Used for registration
|
||||||
@ -32,7 +33,7 @@ export class ScalarService {
|
|||||||
throw new ApiError(401, "Invalid API version.");
|
throw new ApiError(401, "Invalid API version.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const response = await this.accountController.registerAccount(request);
|
const response = await this.accountController.registerAccount(request, ScalarClient.KIND_LEGACY);
|
||||||
return {scalar_token: response.token};
|
return {scalar_token: response.token};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import AccountController from "../controllers/AccountController";
|
|||||||
import TermsController from "../controllers/TermsController";
|
import TermsController from "../controllers/TermsController";
|
||||||
import config from "../../config";
|
import config from "../../config";
|
||||||
import { ScalarStore } from "../../db/ScalarStore";
|
import { ScalarStore } from "../../db/ScalarStore";
|
||||||
|
import { ScalarClient } from "../../scalar/ScalarClient";
|
||||||
|
|
||||||
export interface IMSCUser {
|
export interface IMSCUser {
|
||||||
userId: string;
|
userId: string;
|
||||||
@ -74,7 +75,8 @@ export default class MSCSecurity implements ServiceAuthenticator {
|
|||||||
|
|
||||||
const needUpstreams = !this.matchesAnyRoute(req, ADMIN_ROUTES);
|
const needUpstreams = !this.matchesAnyRoute(req, ADMIN_ROUTES);
|
||||||
if (needUpstreams) {
|
if (needUpstreams) {
|
||||||
const hasUpstreams = await ScalarStore.doesUserHaveTokensForAllUpstreams(req.user.userId);
|
const scalarKind = req.path.startsWith("/_matrix/integrations/v1/") ? ScalarClient.KIND_MATRIX_V1 : ScalarClient.KIND_LEGACY;
|
||||||
|
const hasUpstreams = await ScalarStore.doesUserHaveTokensForAllUpstreams(req.user.userId, scalarKind);
|
||||||
if (!hasUpstreams) {
|
if (!hasUpstreams) {
|
||||||
return res.status(401).json({errcode: "M_INVALID_TOKEN", error: "Invalid token"});
|
return res.status(401).json({errcode: "M_INVALID_TOKEN", error: "Invalid token"});
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ import { Cache, CACHE_SCALAR_ONLINE_STATE } from "../MemoryCache";
|
|||||||
|
|
||||||
export class ScalarStore {
|
export class ScalarStore {
|
||||||
|
|
||||||
public static async doesUserHaveTokensForAllUpstreams(userId: string): Promise<boolean> {
|
public static async doesUserHaveTokensForAllUpstreams(userId: string, scalarKind: string): Promise<boolean> {
|
||||||
const scalarTokens = await UserScalarToken.findAll({where: {userId: userId}});
|
const scalarTokens = await UserScalarToken.findAll({where: {userId: userId}});
|
||||||
const upstreamTokenIds = scalarTokens.filter(t => !t.isDimensionToken).map(t => t.upstreamId);
|
const upstreamTokenIds = scalarTokens.filter(t => !t.isDimensionToken).map(t => t.upstreamId);
|
||||||
const hasDimensionToken = scalarTokens.filter(t => t.isDimensionToken).length >= 1;
|
const hasDimensionToken = scalarTokens.filter(t => t.isDimensionToken).length >= 1;
|
||||||
@ -20,7 +20,7 @@ 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)) {
|
if (!await ScalarStore.isUpstreamOnline(upstream, scalarKind)) {
|
||||||
LogService.warn("ScalarStore", `Upstream ${upstream.apiUrl} is offline - assuming token is valid`);
|
LogService.warn("ScalarStore", `Upstream ${upstream.apiUrl} is offline - assuming token is valid`);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ export class ScalarStore {
|
|||||||
return tokens[0].user;
|
return tokens[0].user;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async isUpstreamOnline(upstream: Upstream): Promise<boolean> {
|
public static async isUpstreamOnline(upstream: Upstream, scalarKind: string): Promise<boolean> {
|
||||||
const cache = Cache.for(CACHE_SCALAR_ONLINE_STATE);
|
const cache = Cache.for(CACHE_SCALAR_ONLINE_STATE);
|
||||||
const cacheKey = `Upstream ${upstream.id}`;
|
const cacheKey = `Upstream ${upstream.id}`;
|
||||||
const result = cache.get(cacheKey);
|
const result = cache.get(cacheKey);
|
||||||
@ -51,17 +51,17 @@ export class ScalarStore {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const state = ScalarStore.checkIfUpstreamOnline(upstream);
|
const state = ScalarStore.checkIfUpstreamOnline(upstream, scalarKind);
|
||||||
cache.put(cacheKey, state, 60 * 60 * 1000); // 1 hour
|
cache.put(cacheKey, state, 60 * 60 * 1000); // 1 hour
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async checkIfUpstreamOnline(upstream: Upstream): Promise<boolean> {
|
private static async checkIfUpstreamOnline(upstream: Upstream, scalarKind: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
// The sticker bot can be used for this for now
|
// The sticker bot can be used for this for now
|
||||||
|
|
||||||
const testUserId = await MatrixStickerBot.getUserId();
|
const testUserId = await MatrixStickerBot.getUserId();
|
||||||
const scalarClient = new ScalarClient(upstream);
|
const scalarClient = new ScalarClient(upstream, scalarKind);
|
||||||
|
|
||||||
// First see if we have a token for the upstream so we can try it
|
// First see if we have a token for the upstream so we can try it
|
||||||
const existingTokens = await UserScalarToken.findAll({
|
const existingTokens = await UserScalarToken.findAll({
|
||||||
|
@ -6,3 +6,7 @@ export interface ScalarAccountResponse {
|
|||||||
user_id: string;
|
user_id: string;
|
||||||
// credit: number; // present on scalar-web
|
// credit: number; // present on scalar-web
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ScalarLogoutResponse {
|
||||||
|
// Nothing of interest
|
||||||
|
}
|
@ -1,21 +1,58 @@
|
|||||||
import { OpenId } from "../models/OpenId";
|
import { OpenId } from "../models/OpenId";
|
||||||
import { ScalarAccountResponse, ScalarRegisterResponse } from "../models/ScalarResponses";
|
import { ScalarAccountResponse, ScalarLogoutResponse, 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";
|
||||||
import { SCALAR_API_VERSION } from "../utils/common-constants";
|
import { SCALAR_API_VERSION } from "../utils/common-constants";
|
||||||
|
import * as url from "url";
|
||||||
|
|
||||||
|
const REGISTER_ROUTE = "/register";
|
||||||
|
const ACCOUNT_INFO_ROUTE = "/account";
|
||||||
|
const LOGOUT_ROUTE = "/logout";
|
||||||
|
|
||||||
export class ScalarClient {
|
export class ScalarClient {
|
||||||
constructor(private upstream: Upstream) {
|
public static readonly KIND_LEGACY = "legacy";
|
||||||
|
public static readonly KIND_MATRIX_V1 = "matrix_v1";
|
||||||
|
|
||||||
|
constructor(private upstream: Upstream, private kind = ScalarClient.KIND_LEGACY) {
|
||||||
|
}
|
||||||
|
|
||||||
|
private makeRequestArguments(path: string, token: string): { scalarUrl: string, headers: any, queryString: any } {
|
||||||
|
if (this.kind === ScalarClient.KIND_LEGACY) {
|
||||||
|
const addlQuery = {};
|
||||||
|
if (token) addlQuery['scalar_token'] = token;
|
||||||
|
return {
|
||||||
|
scalarUrl: this.upstream.scalarUrl + path,
|
||||||
|
headers: {},
|
||||||
|
queryString: {
|
||||||
|
v: SCALAR_API_VERSION,
|
||||||
|
...addlQuery,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const parsed = url.parse(this.upstream.scalarUrl);
|
||||||
|
parsed.path = '/_matrix/integrations/v1' + (path === ACCOUNT_INFO_ROUTE ? path : `${ACCOUNT_INFO_ROUTE}${path}`);
|
||||||
|
|
||||||
|
const headers = {};
|
||||||
|
if (token) headers['Authorization'] = `Bearer ${token}`;
|
||||||
|
|
||||||
|
return {
|
||||||
|
scalarUrl: parsed.toString(),
|
||||||
|
headers: headers,
|
||||||
|
queryString: {},
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public register(openId: OpenId): Promise<ScalarRegisterResponse> {
|
public register(openId: OpenId): Promise<ScalarRegisterResponse> {
|
||||||
LogService.info("ScalarClient", "Doing upstream scalar request: " + this.upstream.scalarUrl + "/register");
|
const {scalarUrl, headers, queryString} = this.makeRequestArguments(REGISTER_ROUTE, null);
|
||||||
|
LogService.info("ScalarClient", "Doing upstream scalar request: " + scalarUrl);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request({
|
request({
|
||||||
method: "POST",
|
method: "POST",
|
||||||
url: this.upstream.scalarUrl + "/register",
|
url: scalarUrl,
|
||||||
qs: {v: SCALAR_API_VERSION},
|
qs: queryString,
|
||||||
|
headers: headers,
|
||||||
json: openId,
|
json: openId,
|
||||||
}, (err, res, _body) => {
|
}, (err, res, _body) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -33,12 +70,39 @@ export class ScalarClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public getAccount(token: string): Promise<ScalarAccountResponse> {
|
public getAccount(token: string): Promise<ScalarAccountResponse> {
|
||||||
LogService.info("ScalarClient", "Doing upstream scalar request: " + this.upstream.scalarUrl + "/account");
|
const {scalarUrl, headers, queryString} = this.makeRequestArguments(ACCOUNT_INFO_ROUTE, token);
|
||||||
|
LogService.info("ScalarClient", "Doing upstream scalar request: " + scalarUrl);
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
request({
|
request({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: this.upstream.scalarUrl + "/account",
|
url: scalarUrl,
|
||||||
qs: {v: SCALAR_API_VERSION, scalar_token: token},
|
qs: queryString,
|
||||||
|
headers: headers,
|
||||||
|
json: true,
|
||||||
|
}, (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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public logout(token: string): Promise<ScalarLogoutResponse> {
|
||||||
|
const {scalarUrl, headers, queryString} = this.makeRequestArguments(LOGOUT_ROUTE, token);
|
||||||
|
LogService.info("ScalarClient", "Doing upstream scalar request: " + scalarUrl);
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
request({
|
||||||
|
method: "POST",
|
||||||
|
url: scalarUrl,
|
||||||
|
qs: queryString,
|
||||||
|
headers: headers,
|
||||||
json: true,
|
json: true,
|
||||||
}, (err, res, _body) => {
|
}, (err, res, _body) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
Loading…
Reference in New Issue
Block a user