diff --git a/packages/backend-core/src/middleware/authenticated.ts b/packages/backend-core/src/middleware/authenticated.ts index 062070785d..54e41bff57 100644 --- a/packages/backend-core/src/middleware/authenticated.ts +++ b/packages/backend-core/src/middleware/authenticated.ts @@ -10,6 +10,7 @@ import { getGlobalDB, doInTenant } from "../tenancy" import { decrypt } from "../security/encryption" const identity = require("../context/identity") const env = require("../environment") +import { User } from "@budibase/types" const ONE_MINUTE = env.SESSION_UPDATE_PERIOD || 60 * 1000 @@ -67,7 +68,11 @@ async function checkApiKey(apiKey: string, populateUser?: Function) { */ export = ( noAuthPatterns = [], - opts: { publicAllowed: boolean; populateUser?: Function } = { + opts: { + publicAllowed: boolean + populateUser?: Function + checkDayPass?: (ctx: any, user: User, tenantId: string) => Promise + } = { publicAllowed: false, } ) => { @@ -106,7 +111,16 @@ export = ( user = await getUser(userId, session.tenantId) } user.csrfToken = session.csrfToken - if (session?.lastAccessedAt < timeMinusOneMinute()) { + + // check day passes for the current user + if (opts.checkDayPass) { + await opts.checkDayPass(ctx, user, session.tenantId) + } + + if ( + !session.lastAccessedAt || + session.lastAccessedAt < timeMinusOneMinute() + ) { // make sure we denote that the session is still in use await updateSessionTTL(session) } diff --git a/packages/backend-core/src/security/sessions.ts b/packages/backend-core/src/security/sessions.ts index f621b99dc2..33230afc60 100644 --- a/packages/backend-core/src/security/sessions.ts +++ b/packages/backend-core/src/security/sessions.ts @@ -2,28 +2,12 @@ const redis = require("../redis/init") const { v4: uuidv4 } = require("uuid") const { logWarn } = require("../logging") const env = require("../environment") - -interface CreateSession { - sessionId: string - tenantId: string - csrfToken?: string -} - -interface Session extends CreateSession { - userId: string - lastAccessedAt: string - createdAt: string - // make optional attributes required - csrfToken: string -} - -interface SessionKey { - key: string -} - -interface ScannedSession { - value: Session -} +import { + Session, + ScannedSession, + SessionKey, + CreateSession, +} from "@budibase/types" // a week in seconds const EXPIRY_SECONDS = 86400 * 7 diff --git a/packages/backend-core/src/users.ts b/packages/backend-core/src/users.ts index 5d6d45a582..0793eeb1d9 100644 --- a/packages/backend-core/src/users.ts +++ b/packages/backend-core/src/users.ts @@ -13,7 +13,9 @@ import { User } from "@budibase/types" * all the users to find one with this email address. * @param {string} email the email to lookup the user by. */ -export const getGlobalUserByEmail = async (email: String) => { +export const getGlobalUserByEmail = async ( + email: String +): Promise => { if (email == null) { throw "Must supply an email address to view" } diff --git a/packages/backend-core/src/utils.js b/packages/backend-core/src/utils.js index 0587267e9a..6b59c7cb72 100644 --- a/packages/backend-core/src/utils.js +++ b/packages/backend-core/src/utils.js @@ -42,6 +42,18 @@ async function resolveAppUrl(ctx) { return app && app.appId ? app.appId : undefined } +exports.isServingApp = ctx => { + // dev app + if (ctx.path.startsWith(`/${APP_PREFIX}`)) { + return true + } + // prod app + if (ctx.path.startsWith(PROD_APP_PREFIX)) { + return true + } + return false +} + /** * Given a request tries to find the appId, which can be located in various places * @param {object} ctx The main request body to look through. diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 3b748a6591..a72b51fcf8 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -18,7 +18,6 @@ const { DocumentType } = require("../../../db/utils") const { getAppDB, getAppId } = require("@budibase/backend-core/context") const { setCookie, clearCookie } = require("@budibase/backend-core/utils") const AWS = require("aws-sdk") - const fs = require("fs") const { downloadTarballDirect, diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js index d156ca2997..ffcea09985 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.js @@ -11,7 +11,7 @@ const zlib = require("zlib") const { mainRoutes, staticRoutes, publicRoutes } = require("./routes") const pkg = require("../../package.json") const env = require("../environment") -const { middleware: pro } = require("@budibase/pro") +const { middleware: pro, quotas } = require("@budibase/pro") const { shutdown } = require("./routes/public") const router = new Router() @@ -44,6 +44,7 @@ router .use( buildAuthMiddleware(null, { publicAllowed: true, + checkDayPass: quotas.checkDayPass, }) ) // nothing in the server should allow query string tenants diff --git a/packages/types/src/documents/global/user.ts b/packages/types/src/documents/global/user.ts index ac16194a21..6c93bac1ac 100644 --- a/packages/types/src/documents/global/user.ts +++ b/packages/types/src/documents/global/user.ts @@ -16,6 +16,7 @@ export interface User extends Document { createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now() userGroups?: string[] forceResetPassword?: boolean + dayPassRecordedAt?: string } export interface UserRoles { diff --git a/packages/types/src/sdk/auth.ts b/packages/types/src/sdk/auth.ts index dd3c2124b5..6a040abf77 100644 --- a/packages/types/src/sdk/auth.ts +++ b/packages/types/src/sdk/auth.ts @@ -3,3 +3,25 @@ export interface AuthToken { tenantId: string sessionId: string } + +export interface CreateSession { + sessionId: string + tenantId: string + csrfToken?: string +} + +export interface Session extends CreateSession { + userId: string + lastAccessedAt: string + createdAt: string + // make optional attributes required + csrfToken: string +} + +export interface SessionKey { + key: string +} + +export interface ScannedSession { + value: Session +} diff --git a/packages/worker/src/api/index.ts b/packages/worker/src/api/index.ts index 692eff685c..5d809ba5b8 100644 --- a/packages/worker/src/api/index.ts +++ b/packages/worker/src/api/index.ts @@ -2,7 +2,7 @@ import Router from "@koa/router" const compress = require("koa-compress") const zlib = require("zlib") import { routes } from "./routes" -import { middleware as pro } from "@budibase/pro" +import { middleware as pro, quotas } from "@budibase/pro" import { errors, auth, middleware } from "@budibase/backend-core" import { APIError } from "@budibase/types" @@ -92,7 +92,11 @@ router }) ) .use("/health", ctx => (ctx.status = 200)) - .use(auth.buildAuthMiddleware(PUBLIC_ENDPOINTS)) + .use( + auth.buildAuthMiddleware(PUBLIC_ENDPOINTS, { + checkDayPass: quotas.checkDayPass, + }) + ) .use(auth.buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS)) .use(auth.buildCsrfMiddleware({ noCsrfPatterns: NO_CSRF_ENDPOINTS })) .use(pro.licensing())