Move day pass middleware from authenticated to licensing, sent activity to account portal
This commit is contained in:
parent
ba211b8490
commit
4f66dc0df3
|
@ -112,11 +112,6 @@ export = (
|
||||||
}
|
}
|
||||||
user.csrfToken = session.csrfToken
|
user.csrfToken = session.csrfToken
|
||||||
|
|
||||||
// check day passes for the current user
|
|
||||||
if (opts.checkDayPass) {
|
|
||||||
await opts.checkDayPass(ctx, user, session.tenantId)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!session.lastAccessedAt ||
|
!session.lastAccessedAt ||
|
||||||
session.lastAccessedAt < timeMinusOneMinute()
|
session.lastAccessedAt < timeMinusOneMinute()
|
||||||
|
|
|
@ -11,7 +11,7 @@ const zlib = require("zlib")
|
||||||
const { mainRoutes, staticRoutes, publicRoutes } = require("./routes")
|
const { mainRoutes, staticRoutes, publicRoutes } = require("./routes")
|
||||||
const pkg = require("../../package.json")
|
const pkg = require("../../package.json")
|
||||||
const env = require("../environment")
|
const env = require("../environment")
|
||||||
const { middleware: pro, quotas } = require("@budibase/pro")
|
const { middleware: pro } = require("@budibase/pro")
|
||||||
const { shutdown } = require("./routes/public")
|
const { shutdown } = require("./routes/public")
|
||||||
|
|
||||||
const router = new Router()
|
const router = new Router()
|
||||||
|
@ -44,7 +44,6 @@ router
|
||||||
.use(
|
.use(
|
||||||
buildAuthMiddleware(null, {
|
buildAuthMiddleware(null, {
|
||||||
publicAllowed: true,
|
publicAllowed: true,
|
||||||
checkDayPass: quotas.checkDayPass,
|
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
// nothing in the server should allow query string tenants
|
// nothing in the server should allow query string tenants
|
||||||
|
@ -55,9 +54,8 @@ router
|
||||||
noTenancyRequired: true,
|
noTenancyRequired: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.use(currentApp)
|
|
||||||
.use(pro.licensing())
|
.use(pro.licensing())
|
||||||
.use(pro.activity())
|
.use(currentApp)
|
||||||
.use(auditLog)
|
.use(auditLog)
|
||||||
|
|
||||||
// error handling middleware
|
// error handling middleware
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { Context } from "koa"
|
import { Context } from "koa"
|
||||||
import { User } from "../documents"
|
import { User } from "../documents"
|
||||||
|
import { License } from "../sdk"
|
||||||
|
|
||||||
export interface ContextUser extends User {
|
export interface ContextUser extends User {
|
||||||
globalId?: string
|
globalId?: string
|
||||||
|
license: License
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface BBContext extends Context {
|
export interface BBContext extends Context {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
import { PriceDuration } from "./plan"
|
||||||
|
|
||||||
|
export interface CustomerBilling {
|
||||||
|
balance: number | null | undefined
|
||||||
|
currency: string | null | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SubscriptionBilling {
|
||||||
|
amount: number
|
||||||
|
quantity: number
|
||||||
|
duration: PriceDuration
|
||||||
|
cancelAt: number | null | undefined
|
||||||
|
currentPeriodStart: number
|
||||||
|
currentPeriodEnd: number
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Billing {
|
||||||
|
customer: CustomerBilling
|
||||||
|
subscription?: SubscriptionBilling
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export enum Feature {
|
||||||
|
USER_GROUPS = "userGroups",
|
||||||
|
}
|
|
@ -1 +1,5 @@
|
||||||
export * from "./license"
|
export * from "./license"
|
||||||
|
export * from "./plan"
|
||||||
|
export * from "./quota"
|
||||||
|
export * from "./feature"
|
||||||
|
export * from "./billing"
|
||||||
|
|
|
@ -1 +1,8 @@
|
||||||
export interface License {}
|
import { AccountPlan, Quotas, Feature, Billing } from "."
|
||||||
|
|
||||||
|
export interface License {
|
||||||
|
features: Feature[]
|
||||||
|
quotas: Quotas
|
||||||
|
plan: AccountPlan
|
||||||
|
billing?: Billing
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
export interface AccountPlan {
|
||||||
|
type: PlanType
|
||||||
|
price?: Price
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PlanType {
|
||||||
|
FREE = "free",
|
||||||
|
PRO = "pro",
|
||||||
|
BUSINESS = "business",
|
||||||
|
ENTERPRISE = "enterprise",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum PriceDuration {
|
||||||
|
MONTHLY = "monthly",
|
||||||
|
YEARLY = "yearly",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Price {
|
||||||
|
amount: number
|
||||||
|
amountMonthly: number
|
||||||
|
currency: string
|
||||||
|
duration: PriceDuration
|
||||||
|
priceId: string
|
||||||
|
dayPasses: number
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
import { PlanType } from "."
|
||||||
|
|
||||||
|
export enum QuotaUsageType {
|
||||||
|
STATIC = "static",
|
||||||
|
MONTHLY = "monthly",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum QuotaType {
|
||||||
|
USAGE = "usage",
|
||||||
|
CONSTANT = "constant",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum StaticQuotaName {
|
||||||
|
ROWS = "rows",
|
||||||
|
APPS = "apps",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum MonthlyQuotaName {
|
||||||
|
QUERIES = "queries",
|
||||||
|
AUTOMATIONS = "automations",
|
||||||
|
DAY_PASSES = "dayPasses",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ConstantQuotaName {
|
||||||
|
QUERY_TIMEOUT_SECONDS = "queryTimeoutSeconds",
|
||||||
|
AUTOMATION_LOG_RETENTION_DAYS = "automationLogRetentionDays",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type QuotaName = StaticQuotaName | MonthlyQuotaName | ConstantQuotaName
|
||||||
|
|
||||||
|
export const isStaticQuota = (
|
||||||
|
quotaType: QuotaType,
|
||||||
|
usageType: QuotaUsageType,
|
||||||
|
name: QuotaName
|
||||||
|
): name is StaticQuotaName => {
|
||||||
|
return quotaType === QuotaType.USAGE && usageType === QuotaUsageType.STATIC
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isMonthlyQuota = (
|
||||||
|
quotaType: QuotaType,
|
||||||
|
usageType: QuotaUsageType,
|
||||||
|
name: QuotaName
|
||||||
|
): name is MonthlyQuotaName => {
|
||||||
|
return quotaType === QuotaType.USAGE && usageType === QuotaUsageType.MONTHLY
|
||||||
|
}
|
||||||
|
|
||||||
|
export const isConstantQuota = (
|
||||||
|
quotaType: QuotaType,
|
||||||
|
name: QuotaName
|
||||||
|
): name is ConstantQuotaName => {
|
||||||
|
return quotaType === QuotaType.CONSTANT
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PlanQuotas = {
|
||||||
|
[PlanType.FREE]: Quotas
|
||||||
|
[PlanType.PRO]: Quotas
|
||||||
|
[PlanType.BUSINESS]: Quotas
|
||||||
|
[PlanType.ENTERPRISE]: Quotas
|
||||||
|
}
|
||||||
|
|
||||||
|
export type Quotas = {
|
||||||
|
[QuotaType.USAGE]: {
|
||||||
|
[QuotaUsageType.MONTHLY]: {
|
||||||
|
[MonthlyQuotaName.QUERIES]: Quota
|
||||||
|
[MonthlyQuotaName.AUTOMATIONS]: Quota
|
||||||
|
[MonthlyQuotaName.DAY_PASSES]: Quota
|
||||||
|
}
|
||||||
|
[QuotaUsageType.STATIC]: {
|
||||||
|
[StaticQuotaName.ROWS]: Quota
|
||||||
|
[StaticQuotaName.APPS]: Quota
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[QuotaType.CONSTANT]: {
|
||||||
|
[ConstantQuotaName.QUERY_TIMEOUT_SECONDS]: Quota
|
||||||
|
[ConstantQuotaName.AUTOMATION_LOG_RETENTION_DAYS]: Quota
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Quota {
|
||||||
|
name: string
|
||||||
|
value: number
|
||||||
|
}
|
|
@ -144,6 +144,7 @@ exports.updateSelf = async ctx => {
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the old password from the user before sending events
|
// remove the old password from the user before sending events
|
||||||
|
user._rev = response.rev
|
||||||
delete user.password
|
delete user.password
|
||||||
await events.user.updated(user)
|
await events.user.updated(user)
|
||||||
if (passwordChange) {
|
if (passwordChange) {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Router from "@koa/router"
|
||||||
const compress = require("koa-compress")
|
const compress = require("koa-compress")
|
||||||
const zlib = require("zlib")
|
const zlib = require("zlib")
|
||||||
import { routes } from "./routes"
|
import { routes } from "./routes"
|
||||||
import { middleware as pro, quotas } from "@budibase/pro"
|
import { middleware as pro } from "@budibase/pro"
|
||||||
import { errors, auth, middleware } from "@budibase/backend-core"
|
import { errors, auth, middleware } from "@budibase/backend-core"
|
||||||
import { APIError } from "@budibase/types"
|
import { APIError } from "@budibase/types"
|
||||||
|
|
||||||
|
@ -92,15 +92,10 @@ router
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
.use("/health", ctx => (ctx.status = 200))
|
.use("/health", ctx => (ctx.status = 200))
|
||||||
.use(
|
.use(auth.buildAuthMiddleware(PUBLIC_ENDPOINTS))
|
||||||
auth.buildAuthMiddleware(PUBLIC_ENDPOINTS, {
|
|
||||||
checkDayPass: quotas.checkDayPass,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
.use(auth.buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
|
.use(auth.buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
|
||||||
.use(auth.buildCsrfMiddleware({ noCsrfPatterns: NO_CSRF_ENDPOINTS }))
|
.use(auth.buildCsrfMiddleware({ noCsrfPatterns: NO_CSRF_ENDPOINTS }))
|
||||||
.use(pro.licensing())
|
.use(pro.licensing())
|
||||||
.use(pro.activity())
|
|
||||||
// for now no public access is allowed to worker (bar health check)
|
// for now no public access is allowed to worker (bar health check)
|
||||||
.use((ctx, next) => {
|
.use((ctx, next) => {
|
||||||
if (ctx.publicEndpoint) {
|
if (ctx.publicEndpoint) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
jest.mock("nodemailer")
|
jest.mock("nodemailer")
|
||||||
import { TestConfiguration, API } from "../../../../tests"
|
import { TestConfiguration, API, mocks } from "../../../../tests"
|
||||||
import { events } from "@budibase/backend-core"
|
import { events } from "@budibase/backend-core"
|
||||||
|
|
||||||
describe("/api/global/self", () => {
|
describe("/api/global/self", () => {
|
||||||
|
@ -26,6 +26,9 @@ describe("/api/global/self", () => {
|
||||||
delete user.password
|
delete user.password
|
||||||
const res = await api.self.updateSelf(user)
|
const res = await api.self.updateSelf(user)
|
||||||
|
|
||||||
|
const dbUser = await config.getUser(user.email)
|
||||||
|
user._rev = dbUser._rev
|
||||||
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
||||||
expect(res.body._id).toBe(user._id)
|
expect(res.body._id).toBe(user._id)
|
||||||
expect(events.user.updated).toBeCalledTimes(1)
|
expect(events.user.updated).toBeCalledTimes(1)
|
||||||
expect(events.user.updated).toBeCalledWith(user)
|
expect(events.user.updated).toBeCalledWith(user)
|
||||||
|
@ -39,6 +42,9 @@ describe("/api/global/self", () => {
|
||||||
user.password = "newPassword"
|
user.password = "newPassword"
|
||||||
const res = await api.self.updateSelf(user)
|
const res = await api.self.updateSelf(user)
|
||||||
|
|
||||||
|
const dbUser = await config.getUser(user.email)
|
||||||
|
user._rev = dbUser._rev
|
||||||
|
user.dayPassRecordedAt = mocks.date.MOCK_DATE.toISOString()
|
||||||
delete user.password
|
delete user.password
|
||||||
expect(res.body._id).toBe(user._id)
|
expect(res.body._id).toBe(user._id)
|
||||||
expect(events.user.updated).toBeCalledTimes(1)
|
expect(events.user.updated).toBeCalledTimes(1)
|
||||||
|
|
Loading…
Reference in New Issue