From be66dd04f977ec13dc4dd41a9914a7f7fa821647 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Wed, 17 Apr 2019 23:34:14 -0600 Subject: [PATCH] Handle upstream tokens more safely --- src/api/scalar/ScalarService.ts | 2 +- src/db/NebStore.ts | 2 +- src/db/ScalarStore.ts | 10 +++++++++- .../20190417231045-AddSelfBotFlagToUsers.ts | 17 +++++++++++++++++ src/db/models/User.ts | 3 +++ src/index.ts | 6 +++--- src/matrix/MatrixLiteClient.ts | 2 +- src/scalar/ScalarClient.ts | 1 + 8 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 src/db/migrations/20190417231045-AddSelfBotFlagToUsers.ts diff --git a/src/api/scalar/ScalarService.ts b/src/api/scalar/ScalarService.ts index b0611e9..e01173b 100644 --- a/src/api/scalar/ScalarService.ts +++ b/src/api/scalar/ScalarService.ts @@ -33,7 +33,7 @@ export class ScalarService { * @returns {Promise} Resolves to the owner's user ID if the token is valid. * @throws {ApiError} Thrown with a status code of 401 if the token is invalid. */ - public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise { + public static async getTokenOwner(scalarToken: string, ignoreUpstreams = false): Promise { const cachedUserId = Cache.for(CACHE_SCALAR_ACCOUNTS).get(scalarToken); if (cachedUserId) return cachedUserId; diff --git a/src/db/NebStore.ts b/src/db/NebStore.ts index c2922ad..d78a33a 100644 --- a/src/db/NebStore.ts +++ b/src/db/NebStore.ts @@ -150,7 +150,7 @@ export class NebStore { const botUserId = null; // TODO: For github const botConfig = await proxy.getServiceConfiguration(i.integration, roomId); const bot = new ComplexBot(i.integration, notifUserId, botUserId, botConfig); - bot.isOnline = !!bot.botUserId; + bot.isOnline = !!bot.notificationUserId; return bot; } catch (e) { LogService.error("NebStore", e); diff --git a/src/db/ScalarStore.ts b/src/db/ScalarStore.ts index a77437a..b23461e 100644 --- a/src/db/ScalarStore.ts +++ b/src/db/ScalarStore.ts @@ -33,7 +33,7 @@ export class ScalarStore { return true; } - public static async getTokenOwner(scalarToken: string, ignoreUpstreams?: boolean): Promise { + public static async getTokenOwner(scalarToken: string, ignoreUpstreams = false): Promise { const tokens = await UserScalarToken.findAll({ where: {isDimensionToken: true, scalarToken: scalarToken}, include: [User] @@ -104,6 +104,14 @@ export class ScalarStore { } } + const user = await User.findByPk(testUserId); + if (!user) { + await User.create({ + userId: testUserId, + isSelfBot: true, + }); + } + const openId = await MatrixStickerBot.getOpenId(); const token = await scalarClient.register(openId); await UserScalarToken.create({ diff --git a/src/db/migrations/20190417231045-AddSelfBotFlagToUsers.ts b/src/db/migrations/20190417231045-AddSelfBotFlagToUsers.ts new file mode 100644 index 0000000..1539ee8 --- /dev/null +++ b/src/db/migrations/20190417231045-AddSelfBotFlagToUsers.ts @@ -0,0 +1,17 @@ +import { QueryInterface } from "sequelize"; +import { DataType } from "sequelize-typescript"; + +export default { + up: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.addColumn("dimension_users", "isSelfBot", { + type: DataType.BOOLEAN, + allowNull: false, + defaultValue: false, + })); + }, + down: (queryInterface: QueryInterface) => { + return Promise.resolve() + .then(() => queryInterface.removeColumn("dimension_users", "isSelfBot")); + } +} \ No newline at end of file diff --git a/src/db/models/User.ts b/src/db/models/User.ts index 36a28f4..77a28a3 100644 --- a/src/db/models/User.ts +++ b/src/db/models/User.ts @@ -11,4 +11,7 @@ export default class User extends Model { @PrimaryKey @Column userId: string; + + @Column + isSelfBot: boolean; } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index ad812c8..7491b1b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -4,8 +4,8 @@ import { DimensionStore } from "./db/DimensionStore"; import Webserver from "./api/Webserver"; import { CURRENT_VERSION } from "./version"; import { MatrixStickerBot } from "./matrix/MatrixStickerBot"; -import UserScalarToken from "./db/models/UserScalarToken"; import * as BotSdk from "matrix-bot-sdk"; +import User from "./db/models/User"; LogService.configure(config.logging); LogService.info("index", "Starting dimension " + CURRENT_VERSION); @@ -25,8 +25,8 @@ async function startup() { await webserver.start(); const userId = await MatrixStickerBot.getUserId(); - const tokens = await UserScalarToken.findAll({where: {userId: userId}}); - if (tokens.length > 0) { + const users = await User.findAll({where: {userId: userId, isSelfBot: false}}); + if (users.length > 0) { LogService.error("index", "The access token configured for Dimension belongs to a user which is also " + "a user known to Dimension. This usually indicates that the access token is not a dedicated user " + "account for Dimension. To prevent potential confusion to this user, Dimension will refuse to start " + diff --git a/src/matrix/MatrixLiteClient.ts b/src/matrix/MatrixLiteClient.ts index 6d7d5ca..0d34778 100644 --- a/src/matrix/MatrixLiteClient.ts +++ b/src/matrix/MatrixLiteClient.ts @@ -49,7 +49,7 @@ export class MatrixLiteClient { return await doClientApiCall( "POST", `/_matrix/client/r0/user/${await this.whoAmI()}/openid/request_token`, - {access_token: this.accessToken}, + {access_token: this.accessToken}, {}, ); } diff --git a/src/scalar/ScalarClient.ts b/src/scalar/ScalarClient.ts index 8902843..78656d2 100644 --- a/src/scalar/ScalarClient.ts +++ b/src/scalar/ScalarClient.ts @@ -39,6 +39,7 @@ export class ScalarClient { method: "GET", url: this.upstream.scalarUrl + "/account", qs: {v: SCALAR_API_VERSION, scalar_token: token}, + json: true, }, (err, res, _body) => { if (err) { LogService.error("ScalarClient", "Error getting information for token");