From e24a187699cd4ce7baf338add93f57401178be31 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Fri, 9 Nov 2018 23:40:33 -0800 Subject: [PATCH] accessToken per subdomain --- app/components/Auth.js | 12 +- app/stores/AuthStore.js | 26 +++- flow-typed/npm/koa_v2.x.x.js | 201 +++++++++++++++------------ flow-typed/npm/localforage_v1.5.x.js | 84 ----------- package.json | 1 - server/auth/google.js | 22 +-- server/auth/slack.js | 22 +-- server/middlewares/authentication.js | 31 ++++- server/models/Team.js | 5 + server/pages/Home.js | 2 +- server/presenters/team.js | 3 +- server/routes.js | 16 ++- webpack.config.js | 4 +- yarn.lock | 104 +------------- 14 files changed, 201 insertions(+), 332 deletions(-) delete mode 100644 flow-typed/npm/localforage_v1.5.x.js diff --git a/app/components/Auth.js b/app/components/Auth.js index 1143ffe41..a4ca6d67f 100644 --- a/app/components/Auth.js +++ b/app/components/Auth.js @@ -26,12 +26,12 @@ const Auth = observer(({ auth, children }: Props) => { // Check the current origin against the teams url, if they differ we need to // redirect to the canonical subdomain for this team - if (window.location.origin !== team.url) { - const redirectTo = `${team.url}${window.location.pathname}`; - console.warn(`Redirecting to ${redirectTo}…`); - window.location.href = redirectTo; - return ; - } + // if (window.location.origin !== team.url) { + // const redirectTo = `${team.url}${window.location.pathname}`; + // console.warn(`Redirecting to ${redirectTo}…`); + // window.location.href = redirectTo; + // return ; + // } // Only initialize stores once. Kept in global scope because otherwise they // will get overridden on route change diff --git a/app/stores/AuthStore.js b/app/stores/AuthStore.js index 02672538a..6761f61f1 100644 --- a/app/stores/AuthStore.js +++ b/app/stores/AuthStore.js @@ -2,8 +2,8 @@ import { observable, action, computed, autorun, runInAction } from 'mobx'; import invariant from 'invariant'; import Cookie from 'js-cookie'; -import localForage from 'localforage'; import { client } from 'utils/ApiClient'; +import { stripSubdomain } from 'shared/utils/domains'; import type { User, Team } from 'types'; const AUTH_STORE = 'AUTH_STORE'; @@ -102,8 +102,18 @@ class AuthStore { this.user = null; this.token = null; + // remove deprecated authentication if it exists Cookie.remove('accessToken', { path: '/' }); - await localForage.clear(); + + if (this.team) { + const sessions = Cookie.getJSON('sessions') || {}; + delete sessions[this.team.subdomain || 'root']; + + Cookie.set('sessions', sessions, { + domain: stripSubdomain(window.location.hostname), + }); + this.team = null; + } // add a timestamp to force reload from server window.location.href = `${BASE_URL}?done=${new Date().getTime()}`; @@ -120,9 +130,15 @@ class AuthStore { this.user = data.user; this.team = data.team; - // load token from state for backwards compatability with - // sessions created pre-google auth - this.token = Cookie.get('accessToken') || data.token; + const sessions = Cookie.getJSON('sessions') || {}; + const subdomain = window.location.hostname.split('.')[0]; + console.log({ sessions }); + const accessToken = sessions[subdomain || 'root'] + ? sessions[subdomain || 'root'].accessToken + : Cookie.get('accessToken'); + + console.log({ accessToken }); + this.token = accessToken; if (this.token) setImmediate(() => this.fetch()); diff --git a/flow-typed/npm/koa_v2.x.x.js b/flow-typed/npm/koa_v2.x.x.js index 62f8db311..787c1fc94 100644 --- a/flow-typed/npm/koa_v2.x.x.js +++ b/flow-typed/npm/koa_v2.x.x.js @@ -14,17 +14,22 @@ declare module 'koa' { // Currently, import type doesn't work well ? // so copy `Server` from flow/lib/node.js#L820 declare class Server extends net$Server { - listen(port?: number, hostname?: string, backlog?: number, callback?: Function): Server, - listen(path: string, callback?: Function): Server, - listen(handle: Object, callback?: Function): Server, - close(callback?: Function): Server, - maxHeadersCount: number, - setTimeout(msecs: number, callback: Function): Server, - timeout: number, + listen( + port?: number, + hostname?: string, + backlog?: number, + callback?: Function + ): Server; + listen(path: string, callback?: Function): Server; + listen(handle: Object, callback?: Function): Server; + close(callback?: Function): Server; + maxHeadersCount: number; + setTimeout(msecs: number, callback: Function): Server; + timeout: number; } declare type ServerType = Server; - declare type JSON = | string | number | boolean | null | JSONObject | JSONArray; + declare type JSON = string | number | boolean | null | JSONObject | JSONArray; declare type JSONObject = { [key: string]: JSON }; declare type JSONArray = Array; @@ -34,11 +39,11 @@ declare module 'koa' { }; declare type RequestJSON = { - 'method': string, - 'url': string, - 'header': SimpleHeader, + method: string, + url: string, + header: SimpleHeader, }; - declare type RequestInspect = void|RequestJSON; + declare type RequestInspect = void | RequestJSON; declare type Request = { app: Application, req: http$IncomingMessage, @@ -60,7 +65,7 @@ declare module 'koa' { originalUrl: string, path: string, protocol: string, - query: {[key: string]: string}, // always string + query: { [key: string]: string }, // always string querystring: string, search: string, secure: boolean, // Shorthand for ctx.protocol == "https" to check if a request was issued via TLS. @@ -70,55 +75,55 @@ declare module 'koa' { type: string, url: string, - charset: string|void, - length: number|void, + charset: string | void, + length: number | void, -// Those functions comes from https://github.com/jshttp/accepts/blob/master/index.js -// request.js$L445 -// https://github.com/jshttp/accepts/blob/master/test/type.js - accepts: ((args: string[]) => string|false)& - // ToDo: There is an issue https://github.com/facebook/flow/issues/3009 - // if you meet some error here, temporarily add an additional annotation - // like: `request.accepts((['json', 'text']:Array))` to fix it. - ((arg: string, ...args: string[]) => string|false) & - ( () => string[] ) , // return the old value. + // Those functions comes from https://github.com/jshttp/accepts/blob/master/index.js + // request.js$L445 + // https://github.com/jshttp/accepts/blob/master/test/type.js + accepts: ((args: string[]) => string | false) & + // ToDo: There is an issue https://github.com/facebook/flow/issues/3009 + // if you meet some error here, temporarily add an additional annotation + // like: `request.accepts((['json', 'text']:Array))` to fix it. + ((arg: string, ...args: string[]) => string | false) & + (() => string[]), // return the old value. -// https://github.com/jshttp/accepts/blob/master/index.js#L153 -// https://github.com/jshttp/accepts/blob/master/test/charset.js - acceptsCharsets: ( (args: string[]) => buffer$Encoding|false)& - // ToDo: https://github.com/facebook/flow/issues/3009 - // if you meet some error here, see L70. - ( (arg: string, ...args: string[]) => buffer$Encoding|false ) & - ( () => string[] ), + // https://github.com/jshttp/accepts/blob/master/index.js#L153 + // https://github.com/jshttp/accepts/blob/master/test/charset.js + acceptsCharsets: ((args: string[]) => buffer$Encoding | false) & + // ToDo: https://github.com/facebook/flow/issues/3009 + // if you meet some error here, see L70. + ((arg: string, ...args: string[]) => buffer$Encoding | false) & + (() => string[]), -// https://github.com/jshttp/accepts/blob/master/index.js#L119 -// https://github.com/jshttp/accepts/blob/master/test/encoding.js - acceptsEncodings: ( (args: string[]) => string|false)& - // ToDo: https://github.com/facebook/flow/issues/3009 - // if you meet some error here, see L70. - ( (arg: string, ...args: string[]) => string|false ) & - ( () => string[] ), + // https://github.com/jshttp/accepts/blob/master/index.js#L119 + // https://github.com/jshttp/accepts/blob/master/test/encoding.js + acceptsEncodings: ((args: string[]) => string | false) & + // ToDo: https://github.com/facebook/flow/issues/3009 + // if you meet some error here, see L70. + ((arg: string, ...args: string[]) => string | false) & + (() => string[]), -// https://github.com/jshttp/accepts/blob/master/index.js#L185 -// https://github.com/jshttp/accepts/blob/master/test/language.js - acceptsLanguages: ( (args: string[]) => string|false) & - // ToDo: https://github.com/facebook/flow/issues/3009 - // if you meet some error here, see L70. - ( (arg: string, ...args: string[]) => string|false ) & - ( () => string[] ), + // https://github.com/jshttp/accepts/blob/master/index.js#L185 + // https://github.com/jshttp/accepts/blob/master/test/language.js + acceptsLanguages: ((args: string[]) => string | false) & + // ToDo: https://github.com/facebook/flow/issues/3009 + // if you meet some error here, see L70. + ((arg: string, ...args: string[]) => string | false) & + (() => string[]), get: (field: string) => string, -/* https://github.com/jshttp/type-is/blob/master/test/test.js + /* https://github.com/jshttp/type-is/blob/master/test/test.js * Check if the incoming request contains the "Content-Type" * header field, and it contains any of the give mime `type`s. * If there is no request body, `null` is returned. * If there is no content type, `false` is returned. * Otherwise, it returns the first `type` that matches. */ - is: ( (args: string[]) => null|false|string)& - ( (arg: string, ...args: string[]) => null|false|string ) & - ( () => string ), // should return the mime type + is: ((args: string[]) => null | false | string) & + ((arg: string, ...args: string[]) => null | false | string) & + (() => string), // should return the mime type toJSON: () => RequestJSON, inspect: () => RequestInspect, @@ -127,15 +132,15 @@ declare module 'koa' { }; declare type ResponseJSON = { - 'status': mixed, - 'message': mixed, - 'header': mixed, + status: mixed, + message: mixed, + header: mixed, }; declare type ResponseInspect = { - 'status': mixed, - 'message': mixed, - 'header': mixed, - 'body': mixed, + status: mixed, + message: mixed, + header: mixed, + body: mixed, }; declare type Response = { app: Application, @@ -145,7 +150,7 @@ declare module 'koa' { request: Request, // docs/api/response.md#L113. - body: string|Buffer|stream$Stream|Object|Array|null, // JSON contains null + body: string | Buffer | stream$Stream | Object | Array | null, // JSON contains null etag: string, header: SimpleHeader, headers: SimpleHeader, // alias as header @@ -160,21 +165,21 @@ declare module 'koa' { writable: boolean, // charset: string, // doesn't find in response.js - length: number|void, + length: number | void, append: (field: string, val: string | string[]) => void, attachment: (filename?: string) => void, get: (field: string) => string, // https://github.com/jshttp/type-is/blob/master/test/test.js // https://github.com/koajs/koa/blob/v2.x/lib/response.js#L382 - is: ( (arg: string[]) => false|string) & - ( (arg: string, ...args: string[]) => false|string ) & - ( () => string ), // should return the mime type + is: ((arg: string[]) => false | string) & + ((arg: string, ...args: string[]) => false | string) & + (() => string), // should return the mime type redirect: (url: string, alt?: string) => void, remove: (field: string) => void, // https://github.com/koajs/koa/blob/v2.x/lib/response.js#L418 - set: ((field: string, val: string | string[]) => void)& - ((field: {[key: string]: string | string[]}) => void), + set: ((field: string, val: string | string[]) => void) & + ((field: { [key: string]: string | string[] }) => void), vary: (field: string) => void, @@ -183,7 +188,7 @@ declare module 'koa' { inspect(): ResponseInspect, [key: string]: mixed, // props added by middlewares. - } + }; declare type ContextJSON = { request: RequestJSON, @@ -197,7 +202,7 @@ declare module 'koa' { // https://github.com/pillarjs/cookies declare type CookiesSetOptions = { domain: string, // domain of the cookie (no default). - maxAge: number, // milliseconds from Date.now() for expiry + maxAge?: number, // milliseconds from Date.now() for expiry expires?: Date, //cookie's expiration date (expires at the end of session by default). path?: string, // the path of the cookie (/ by default). secure?: boolean, // false by default for HTTP, true by default for HTTPS @@ -207,10 +212,14 @@ declare module 'koa' { overwrite?: boolean, // whether to overwrite previously set cookies of the same name (false by default). }; declare type Cookies = { - get: (name: string, options?: {signed: boolean}) => string|void, - set: ((name: string, value: string, options?: CookiesSetOptions) => Context)& - // delete cookie (an outbound header with an expired date is used.) - ( (name: string) => Context), + get: (name: string, options?: { signed: boolean }) => string | void, + set: (( + name: string, + value: string, + options?: CookiesSetOptions + ) => Context) & + // delete cookie (an outbound header with an expired date is used.) + ((name: string) => Context), }; // The default props of context come from two files // `application.createContext` & `context.js` @@ -228,12 +237,17 @@ declare module 'koa' { state: Object, // context.js#L55 - assert: (test: mixed, status: number, message?: string, opts?: mixed) => void, + assert: ( + test: mixed, + status: number, + message?: string, + opts?: mixed + ) => void, // context.js#L107 // if (!(err instanceof Error)) err = new Error(`non-error thrown: ${err}`); onerror: (err?: mixed) => void, // context.md#L88 - throw: ( status: number, msg?: string, opts?: Object) => void, + throw: (status: number, msg?: string, opts?: Object) => void, toJSON(): ContextJSON, inspect(): ContextJSON, @@ -287,32 +301,37 @@ declare module 'koa' { ip: $PropertyType, [key: string]: any, // props added by middlewares. - } + }; - declare type Middleware = - (ctx: Context, next: () => Promise) => Promise|void; + declare type Middleware = ( + ctx: Context, + next: () => Promise + ) => Promise | void; declare type ApplicationJSON = { - 'subdomainOffset': mixed, - 'proxy': mixed, - 'env': string, + subdomainOffset: mixed, + proxy: mixed, + env: string, }; declare class Application extends events$EventEmitter { - context: Context, + context: Context; // request handler for node's native http server. - callback: () => (req: http$IncomingMessage, res: http$ServerResponse) => void, - env: string, - keys?: Array|Object, // https://github.com/crypto-utils/keygrip - middleware: Array, - proxy: boolean, // when true proxy header fields will be trusted - request: Request, - response: Response, - server: Server, - subdomainOffset: number, + callback: () => ( + req: http$IncomingMessage, + res: http$ServerResponse + ) => void; + env: string; + keys?: Array | Object; // https://github.com/crypto-utils/keygrip + middleware: Array; + proxy: boolean; // when true proxy header fields will be trusted + request: Request; + response: Response; + server: Server; + subdomainOffset: number; - listen: $PropertyType, - toJSON(): ApplicationJSON, - inspect(): ApplicationJSON, - use(fn: Middleware): this, + listen: $PropertyType; + toJSON(): ApplicationJSON; + inspect(): ApplicationJSON; + use(fn: Middleware): this; } declare module.exports: Class; diff --git a/flow-typed/npm/localforage_v1.5.x.js b/flow-typed/npm/localforage_v1.5.x.js deleted file mode 100644 index bcbf1704b..000000000 --- a/flow-typed/npm/localforage_v1.5.x.js +++ /dev/null @@ -1,84 +0,0 @@ -// flow-typed signature: 37b164ad4c10b3c89887d1fd5b7ca096 -// flow-typed version: 9c854fa980/localforage_v1.5.x/flow_>=v0.25.x - -type PartialConfig = { - driver?: string | Array, - name?: string, - size?: number, - storeName?: string, - version?: string, - description?: string, -}; - -type Driver = { - _driver: string, - _initStorage(config: PartialConfig): void, - - getItem( - key: string, - successCallback?: (err?: Error, value?: T) => mixed, - ): ?Promise, - setItem( - key: string, - value: T, - successCallback?: (err?: Error, value?: T) => mixed, - ): ?Promise, - removeItem( - key: string, - successCallback?: (err?: Error) => mixed, - ): ?Promise, - clear(successCallback?: ?(numberOfKeys: number) => mixed): ?Promise, - length(successCallback?: (numberOfKeys: number) => mixed): ?Promise, - key( - keyIndex: number, - successCallback?: (keyName: string) => mixed, - ): ?Promise, - keys( - successCallback?: (keyNames: Array) => mixed, - ): ?Promise>, -}; - -type localforageInstance = { - INDEXEDDB: 'asyncStorage', - WEBSQL: 'webSQLStorage', - LOCALSTORAGE: 'localStorageWrapper', - - getItem( - key: string, - successCallback?: (err?: Error, value?: T) => mixed, - ): Promise, - setItem( - key: string, - value: T, - successCallback?: (err?: Error, value?: T) => mixed, - ): Promise, - removeItem( - key: string, - successCallback?: (err?: Error) => mixed, - ): Promise, - clear(successCallback?: ?(numberOfKeys: number) => mixed): Promise, - length(successCallback?: (numberOfKeys: number) => mixed): Promise, - key( - keyIndex: number, - successCallback?: (keyName: string) => mixed, - ): Promise, - keys( - successCallback?: (keyNames: Array) => mixed, - ): Promise>, - iterate( - iteratorCallback: (value: T, key: string, iterationNumber: number) => mixed, - successCallback?: (result: void | [string, T]) => mixed, - ): Promise, - setDriver(driverNames: string | Array): void, - config(config?: PartialConfig): boolean | PartialConfig, - defineDriver(driver: Driver): void, - driver(): string, - ready(): Promise, - supports(driverName: string): boolean, - createInstance(config?: PartialConfig): localforageInstance, - dropInstance(config?: PartialConfig): Promise, -}; - -declare module 'localforage' { - declare module.exports: localforageInstance; -} diff --git a/package.json b/package.json index 13112edb3..3b7d772f9 100644 --- a/package.json +++ b/package.json @@ -128,7 +128,6 @@ "koa-sendfile": "2.0.0", "koa-static": "^4.0.1", "koa-sslify": "2.1.2", - "localforage": "^1.5.0", "lodash": "^4.17.4", "mobx": "^3.1.9", "mobx-react": "^4.1.8", diff --git a/server/auth/google.js b/server/auth/google.js index c4750d923..48b16019b 100644 --- a/server/auth/google.js +++ b/server/auth/google.js @@ -1,11 +1,10 @@ // @flow import crypto from 'crypto'; import Router from 'koa-router'; -import addMonths from 'date-fns/add_months'; -import { stripSubdomain } from '../../shared/utils/domains'; import { capitalize } from 'lodash'; import { OAuth2Client } from 'google-auth-library'; import { User, Team } from '../models'; +import auth from '../middlewares/authentication'; const router = new Router(); const client = new OAuth2Client( @@ -30,7 +29,7 @@ router.get('google', async ctx => { }); // signin callback from Google -router.get('google.callback', async ctx => { +router.get('google.callback', auth({ required: false }), async ctx => { const { code } = ctx.request.query; ctx.assertPresent(code, 'code is required'); const response = await client.getToken(code); @@ -103,21 +102,8 @@ router.get('google.callback', async ctx => { } } - // not awaiting the promise here so that the request is not blocked - user.updateSignedIn(ctx.request.ip); - - ctx.cookies.set('lastSignedIn', 'google', { - httpOnly: false, - expires: new Date('2100'), - domain: stripSubdomain(ctx.request.hostname), - }); - ctx.cookies.set('accessToken', user.getJwtToken(), { - httpOnly: false, - expires: addMonths(new Date(), 1), - domain: stripSubdomain(ctx.request.hostname), - }); - - ctx.redirect(team.url); + // set cookies on response and redirect to team subdomain + ctx.signIn(user, team, 'google'); }); export default router; diff --git a/server/auth/slack.js b/server/auth/slack.js index 5121e0de4..24741e72a 100644 --- a/server/auth/slack.js +++ b/server/auth/slack.js @@ -2,9 +2,8 @@ import Router from 'koa-router'; import auth from '../middlewares/authentication'; import addHours from 'date-fns/add_hours'; -import addMonths from 'date-fns/add_months'; -import { slackAuth } from '../../shared/utils/routeHelpers'; import { stripSubdomain } from '../../shared/utils/domains'; +import { slackAuth } from '../../shared/utils/routeHelpers'; import { Authentication, Integration, User, Team } from '../models'; import * as Slack from '../slack'; @@ -25,7 +24,7 @@ router.get('slack', async ctx => { }); // signin callback from Slack -router.get('slack.callback', async ctx => { +router.get('slack.callback', auth({ required: false }), async ctx => { const { code, error, state } = ctx.request.query; ctx.assertPresent(code || error, 'code is required'); ctx.assertPresent(state, 'state is required'); @@ -72,21 +71,8 @@ router.get('slack.callback', async ctx => { } } - // not awaiting the promise here so that the request is not blocked - user.updateSignedIn(ctx.request.ip); - - ctx.cookies.set('lastSignedIn', 'slack', { - httpOnly: false, - expires: new Date('2100'), - domain: stripSubdomain(ctx.request.hostname), - }); - ctx.cookies.set('accessToken', user.getJwtToken(), { - httpOnly: false, - expires: addMonths(new Date(), 1), - domain: stripSubdomain(ctx.request.hostname), - }); - - ctx.redirect(team.url); + // set cookies on response and redirect to team subdomain + ctx.signIn(user, team, 'slack'); }); router.get('slack.commands', auth(), async ctx => { diff --git a/server/middlewares/authentication.js b/server/middlewares/authentication.js index 67f570ef1..ab68a38d8 100644 --- a/server/middlewares/authentication.js +++ b/server/middlewares/authentication.js @@ -3,6 +3,8 @@ import JWT from 'jsonwebtoken'; import { type Context } from 'koa'; import { User, ApiKey } from '../models'; import { AuthenticationError, UserSuspendedError } from '../errors'; +import addMonths from 'date-fns/add_months'; +import { stripSubdomain } from '../../shared/utils/domains'; export default function auth(options?: { required?: boolean } = {}) { return async function authMiddleware(ctx: Context, next: () => Promise<*>) { @@ -28,8 +30,6 @@ export default function auth(options?: { required?: boolean } = {}) { token = ctx.body.token; } else if (ctx.request.query.token) { token = ctx.request.query.token; - } else if (ctx.cookies.get('accessToken')) { - token = ctx.cookies.get('accessToken'); } if (!token && options.required !== false) { @@ -90,6 +90,33 @@ export default function auth(options?: { required?: boolean } = {}) { ctx.cache[user.id] = user; } + ctx.signIn = (user, team, service) => { + // not awaiting the promise here so that the request is not blocked + user.updateSignedIn(ctx.request.ip); + + const existing = JSON.parse(ctx.cookies.get('sessions') || '{}'); + const domain = stripSubdomain(ctx.request.hostname); + const sessions = JSON.stringify({ + ...existing, + [team.subdomain || 'root']: { + name: team.name, + logo: team.logo, + accessToken: user.getJwtToken(), + }, + }); + ctx.cookies.set('lastSignedIn', service, { + httpOnly: false, + expires: new Date('2100'), + domain, + }); + ctx.cookies.set('sessions', sessions, { + httpOnly: false, + expires: addMonths(new Date(), 3), + domain, + }); + ctx.redirect(team.url); + }; + return next(); }; } diff --git a/server/models/Team.js b/server/models/Team.js index dc04fe78c..758352701 100644 --- a/server/models/Team.js +++ b/server/models/Team.js @@ -51,6 +51,11 @@ const Team = sequelize.define( url.host = `${this.subdomain}.${url.host}`; return url.href.replace(/\/$/, ''); }, + logo() { + return ( + this.avatarUrl || (this.slackData ? this.slackData.image_88 : null) + ); + }, }, } ); diff --git a/server/pages/Home.js b/server/pages/Home.js index 2a83c765f..a7f49386d 100644 --- a/server/pages/Home.js +++ b/server/pages/Home.js @@ -64,7 +64,7 @@ function Home(props: Props) { diff --git a/server/presenters/team.js b/server/presenters/team.js index 581790c9b..fae6bb09b 100644 --- a/server/presenters/team.js +++ b/server/presenters/team.js @@ -7,8 +7,7 @@ function present(ctx: Object, team: Team) { return { id: team.id, name: team.name, - avatarUrl: - team.avatarUrl || (team.slackData ? team.slackData.image_88 : null), + avatarUrl: team.logo, slackConnected: !!team.slackId, googleConnected: !!team.googleId, sharing: team.sharing, diff --git a/server/routes.js b/server/routes.js index aa347d6a3..725a6f1a0 100644 --- a/server/routes.js +++ b/server/routes.js @@ -66,9 +66,21 @@ router.get('/changelog', async ctx => { // home page router.get('/', async ctx => { const lastSignedIn = ctx.cookies.get('lastSignedIn'); - const accessToken = ctx.cookies.get('accessToken'); + const sessions = JSON.parse(ctx.cookies.get('sessions') || '{}'); const domain = parseDomain(ctx.request.hostname); - const subdomain = domain ? domain.subdomain : false; + const subdomain = domain ? domain.subdomain : undefined; + console.log('domain', domain); + console.log('subdomain', subdomain); + + let accessToken; + if (subdomain) { + accessToken = sessions[subdomain] && sessions[subdomain].accessToken; + } else { + accessToken = sessions.root + ? sessions.root.accessToken + : ctx.cookies.get('accessToken'); + } + console.log('accessToken', accessToken); if (accessToken) { return renderapp(ctx); diff --git a/webpack.config.js b/webpack.config.js index 97967498c..761d5cd17 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -58,9 +58,7 @@ module.exports = { }), }, { test: /\.md/, loader: 'raw-loader' }, - ], - // Silence warning https://github.com/localForage/localForage/issues/599 - noParse: [new RegExp('node_modules/localforage/dist/localforage.js')], + ] }, resolve: { modules: [ diff --git a/yarn.lock b/yarn.lock index fc3182b6b..d3219c706 100644 --- a/yarn.lock +++ b/yarn.lock @@ -159,10 +159,6 @@ acorn-jsx@^3.0.0: dependencies: acorn "^3.0.4" -acorn@^1.0.3: - version "1.2.2" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-1.2.2.tgz#c8ce27de0acc76d896d2b1fad3df588d9e82f014" - acorn@^3.0.4: version "3.3.0" resolved "https://registry.yarnpkg.com/acorn/-/acorn-3.3.0.tgz#45e37fb39e8da3f25baee3ff5369e2bb5f22017a" @@ -429,10 +425,6 @@ ast-types-flow@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/ast-types-flow/-/ast-types-flow-0.0.7.tgz#f70b735c6bca1a5c9c22d982c3e39e7feba3bdad" -ast-types@0.8.15: - version "0.8.15" - resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.8.15.tgz#8eef0827f04dff0ec8857ba925abe3fea6194e52" - astral-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" @@ -1214,10 +1206,6 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" -base62@0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/base62/-/base62-0.1.1.tgz#7b4174c2f94449753b11c2651c083da841a7b084" - base64-js@^1.0.2: version "1.2.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.2.1.tgz#a91947da1f4a516ea38e5b4ec0ec3773675e0886" @@ -3121,14 +3109,6 @@ es-to-primitive@^1.1.1: is-date-object "^1.0.1" is-symbol "^1.0.1" -es3ify@^0.1.3: - version "0.1.4" - resolved "https://registry.yarnpkg.com/es3ify/-/es3ify-0.1.4.tgz#ad9fa5df1ae34f3f31e1211b5818b2d51078dfd1" - dependencies: - esprima-fb "~3001.0001.0000-dev-harmony-fb" - jstransform "~3.0.0" - through "~2.3.4" - es5-ext@^0.10.12, es5-ext@^0.10.14, es5-ext@^0.10.30, es5-ext@^0.10.9, es5-ext@~0.10.14, es5-ext@~0.10.2: version "0.10.30" resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.30.tgz#7141a16836697dbabfaaaeee41495ce29f52c939" @@ -3358,10 +3338,6 @@ eslint@^4.14.0: table "^4.0.1" text-table "~0.2.0" -esmangle-evaluator@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/esmangle-evaluator/-/esmangle-evaluator-1.0.1.tgz#620d866ef4861b3311f75766d52a8572bb3c6336" - espree@^3.5.2: version "3.5.2" resolved "https://registry.yarnpkg.com/espree/-/espree-3.5.2.tgz#756ada8b979e9dcfcdb30aad8d1a9304a905e1ca" @@ -3369,14 +3345,6 @@ espree@^3.5.2: acorn "^5.2.1" acorn-jsx "^3.0.0" -esprima-fb@~15001.1001.0-dev-harmony-fb: - version "15001.1001.0-dev-harmony-fb" - resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-15001.1001.0-dev-harmony-fb.tgz#43beb57ec26e8cf237d3dd8b33e42533577f2659" - -esprima-fb@~3001.0001.0000-dev-harmony-fb, esprima-fb@~3001.1.0-dev-harmony-fb: - version "3001.1.0-dev-harmony-fb" - resolved "https://registry.yarnpkg.com/esprima-fb/-/esprima-fb-3001.0001.0000-dev-harmony-fb.tgz#b77d37abcd38ea0b77426bb8bc2922ce6b426411" - esprima@^2.6.0: version "2.7.3" resolved "https://registry.yarnpkg.com/esprima/-/esprima-2.7.3.tgz#96e3b70d5779f6ad49cd032673d1c312767ba581" @@ -3573,15 +3541,6 @@ extsprintf@1.3.0, extsprintf@^1.2.0: version "1.3.0" resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" -falafel@^1.0.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/falafel/-/falafel-1.2.0.tgz#c18d24ef5091174a497f318cd24b026a25cddab4" - dependencies: - acorn "^1.0.3" - foreach "^2.0.5" - isarray "0.0.1" - object-keys "^1.0.6" - fancy-log@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/fancy-log/-/fancy-log-1.3.0.tgz#45be17d02bb9917d60ccffd4995c999e6c8c9948" @@ -4889,13 +4848,6 @@ ini@^1.3.4, ini@~1.3.0: version "1.3.4" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.4.tgz#0537cb79daf59b59a1a517dff706c86ec039162e" -inline-process-browser@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/inline-process-browser/-/inline-process-browser-1.0.0.tgz#46a61b153dd3c9b1624b1a00626edb4f7f414f22" - dependencies: - falafel "^1.0.1" - through2 "^0.6.5" - inquirer@^3.0.6: version "3.3.0" resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-3.3.0.tgz#9dd2f2ad765dcab1ff0443b491442a20ba227dc9" @@ -5839,14 +5791,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -jstransform@~3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/jstransform/-/jstransform-3.0.0.tgz#a2591ab6cee8d97bf3be830dbfa2313b87cd640b" - dependencies: - base62 "0.1.1" - esprima-fb "~3001.1.0-dev-harmony-fb" - source-map "0.1.31" - jsx-ast-utils@^1.4.0: version "1.4.1" resolved "https://registry.yarnpkg.com/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz#3867213e8dd79bf1e8f2300c0cfc1efb182c0df1" @@ -6106,15 +6050,6 @@ levn@^0.3.0, levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" -lie@3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lie/-/lie-3.0.2.tgz#ffda21d7bba26f377cad865d3649b2fc8ce39fea" - dependencies: - es3ify "^0.1.3" - immediate "~3.0.5" - inline-process-browser "^1.0.0" - unreachable-branch-transform "^0.3.0" - lie@~3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e" @@ -6240,12 +6175,6 @@ loader-utils@^1.0.2, loader-utils@^1.1.0: emojis-list "^2.0.0" json5 "^0.5.0" -localforage@^1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.5.0.tgz#6b994e19b56611fa85df3992df397ac4ab66e815" - dependencies: - lie "3.0.2" - locate-path@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" @@ -7335,7 +7264,7 @@ object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" -object-keys@^1.0.10, object-keys@^1.0.6, object-keys@^1.0.8: +object-keys@^1.0.10, object-keys@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.11.tgz#c54601778ad560f1142ce0e01bcca8b56d13426d" @@ -8176,7 +8105,7 @@ prismjs@^1.13.0: optionalDependencies: clipboard "^2.0.0" -private@^0.1.6, private@^0.1.7, private@~0.1.5: +private@^0.1.6, private@^0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/private/-/private-0.1.7.tgz#68ce5e8a1ef0a23bb570cc28537b5332aba63ef1" @@ -8697,15 +8626,6 @@ realpath-native@^1.0.0: dependencies: util.promisify "^1.0.0" -recast@^0.10.1: - version "0.10.43" - resolved "https://registry.yarnpkg.com/recast/-/recast-0.10.43.tgz#b95d50f6d60761a5f6252e15d80678168491ce7f" - dependencies: - ast-types "0.8.15" - esprima-fb "~15001.1001.0-dev-harmony-fb" - private "~0.1.5" - source-map "~0.5.0" - rechoir@^0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" @@ -9604,12 +9524,6 @@ source-map-support@^0.5.0: dependencies: source-map "^0.6.0" -source-map@0.1.31: - version "0.1.31" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.31.tgz#9f704d0d69d9e138a81badf6ebb4fde33d151c61" - dependencies: - amdefine ">=0.0.4" - source-map@0.1.x: version "0.1.43" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.1.43.tgz#c24bc146ca517c1471f5dacbe2571b2b7f9e3346" @@ -9626,7 +9540,7 @@ source-map@0.5.6: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.0, source-map@~0.5.1, source-map@~0.5.6: +source-map@0.5.x, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.1, source-map@~0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" @@ -10077,7 +9991,7 @@ throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" -through2@^0.6.1, through2@^0.6.2, through2@^0.6.5: +through2@^0.6.1: version "0.6.5" resolved "https://registry.yarnpkg.com/through2/-/through2-0.6.5.tgz#41ab9c67b29d57209071410e1d7a7a968cd3ad48" dependencies: @@ -10091,7 +10005,7 @@ through2@^2.0.0, through2@^2.0.1: readable-stream "^2.1.5" xtend "~4.0.1" -through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4: +through@2, through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" @@ -10465,14 +10379,6 @@ unpipe@1.0.0, unpipe@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" -unreachable-branch-transform@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/unreachable-branch-transform/-/unreachable-branch-transform-0.3.0.tgz#d99cc4c6e746d264928845b611db54b0f3474caa" - dependencies: - esmangle-evaluator "^1.0.0" - recast "^0.10.1" - through2 "^0.6.2" - unzipper@^0.8.11: version "0.8.13" resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.8.13.tgz#ea889ca10cdda4dcf604e632f19fc5f81871beae"