Add developer usage restrictions to SSO user creation

This commit is contained in:
Rory Powell 2022-03-18 08:01:31 +00:00
parent e695a57853
commit 661367333d
20 changed files with 168 additions and 200 deletions

View File

@ -2,24 +2,27 @@ const GoogleStrategy = require("passport-google-oauth").OAuth2Strategy
const { authenticateThirdParty } = require("./third-party-common")
async function authenticate(accessToken, refreshToken, profile, done) {
const thirdPartyUser = {
provider: profile.provider, // should always be 'google'
providerType: "google",
userId: profile.id,
profile: profile,
email: profile._json.email,
oauth2: {
accessToken: accessToken,
refreshToken: refreshToken,
},
}
const buildVerifyFn = async saveUserFn => {
return (accessToken, refreshToken, profile, done) => {
const thirdPartyUser = {
provider: profile.provider, // should always be 'google'
providerType: "google",
userId: profile.id,
profile: profile,
email: profile._json.email,
oauth2: {
accessToken: accessToken,
refreshToken: refreshToken,
},
}
return authenticateThirdParty(
thirdPartyUser,
true, // require local accounts to exist
done
)
return authenticateThirdParty(
thirdPartyUser,
true, // require local accounts to exist
done,
saveUserFn
)
}
}
/**
@ -27,11 +30,7 @@ async function authenticate(accessToken, refreshToken, profile, done) {
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
* @returns Dynamically configured Passport Google Strategy
*/
exports.strategyFactory = async function (
config,
callbackUrl,
verify = authenticate
) {
exports.strategyFactory = async function (config, callbackUrl, saveUserFn) {
try {
const { clientID, clientSecret } = config
@ -41,6 +40,7 @@ exports.strategyFactory = async function (
)
}
const verify = buildVerifyFn(saveUserFn)
return new GoogleStrategy(
{
clientID: config.clientID,
@ -55,4 +55,4 @@ exports.strategyFactory = async function (
}
}
// expose for testing
exports.authenticate = authenticate
exports.authenticate = buildVerifyFn

View File

@ -2,46 +2,49 @@ const fetch = require("node-fetch")
const OIDCStrategy = require("@techpass/passport-openidconnect").Strategy
const { authenticateThirdParty } = require("./third-party-common")
/**
* @param {*} issuer The identity provider base URL
* @param {*} sub The user ID
* @param {*} profile The user profile information. Created by passport from the /userinfo response
* @param {*} jwtClaims The parsed id_token claims
* @param {*} accessToken The access_token for contacting the identity provider - may or may not be a JWT
* @param {*} refreshToken The refresh_token for obtaining a new access_token - usually not a JWT
* @param {*} idToken The id_token - always a JWT
* @param {*} params The response body from requesting an access_token
* @param {*} done The passport callback: err, user, info
*/
async function authenticate(
issuer,
sub,
profile,
jwtClaims,
accessToken,
refreshToken,
idToken,
params,
done
) {
const thirdPartyUser = {
// store the issuer info to enable sync in future
provider: issuer,
providerType: "oidc",
userId: profile.id,
profile: profile,
email: getEmail(profile, jwtClaims),
oauth2: {
accessToken: accessToken,
refreshToken: refreshToken,
},
}
return authenticateThirdParty(
thirdPartyUser,
false, // don't require local accounts to exist
const buildVerifyFn = saveUserFn => {
/**
* @param {*} issuer The identity provider base URL
* @param {*} sub The user ID
* @param {*} profile The user profile information. Created by passport from the /userinfo response
* @param {*} jwtClaims The parsed id_token claims
* @param {*} accessToken The access_token for contacting the identity provider - may or may not be a JWT
* @param {*} refreshToken The refresh_token for obtaining a new access_token - usually not a JWT
* @param {*} idToken The id_token - always a JWT
* @param {*} params The response body from requesting an access_token
* @param {*} done The passport callback: err, user, info
*/
return async (
issuer,
sub,
profile,
jwtClaims,
accessToken,
refreshToken,
idToken,
params,
done
)
) => {
const thirdPartyUser = {
// store the issuer info to enable sync in future
provider: issuer,
providerType: "oidc",
userId: profile.id,
profile: profile,
email: getEmail(profile, jwtClaims),
oauth2: {
accessToken: accessToken,
refreshToken: refreshToken,
},
}
return authenticateThirdParty(
thirdPartyUser,
false, // don't require local accounts to exist
done,
saveUserFn
)
}
}
/**
@ -86,7 +89,7 @@ function validEmail(value) {
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
* @returns Dynamically configured Passport OIDC Strategy
*/
exports.strategyFactory = async function (config, callbackUrl) {
exports.strategyFactory = async function (config, callbackUrl, saveUserFn) {
try {
const { clientID, clientSecret, configUrl } = config
@ -106,6 +109,7 @@ exports.strategyFactory = async function (config, callbackUrl) {
const body = await response.json()
const verify = buildVerifyFn(saveUserFn)
return new OIDCStrategy(
{
issuer: body.issuer,
@ -116,7 +120,7 @@ exports.strategyFactory = async function (config, callbackUrl) {
clientSecret: clientSecret,
callbackURL: callbackUrl,
},
authenticate
verify
)
} catch (err) {
console.error(err)
@ -125,4 +129,4 @@ exports.strategyFactory = async function (config, callbackUrl) {
}
// expose for testing
exports.authenticate = authenticate
exports.authenticate = buildVerifyFn

View File

@ -1,7 +1,6 @@
const env = require("../../environment")
const jwt = require("jsonwebtoken")
const { generateGlobalUserID } = require("../../db/utils")
const { saveUser } = require("../../utils")
const { authError } = require("./utils")
const { newid } = require("../../hashing")
const { createASession } = require("../../security/sessions")
@ -16,8 +15,11 @@ exports.authenticateThirdParty = async function (
thirdPartyUser,
requireLocalAccount = true,
done,
saveUserFn = saveUser
saveUserFn
) {
if (!saveUserFn) {
throw new Error("Save user function must be provided")
}
if (!thirdPartyUser.provider) {
return authError(done, "third party user provider required")
}

View File

@ -181,12 +181,6 @@ exports.saveUser = async (
hashPassword = true,
requirePassword = true
) => {
// // new user
// // check license restrictions
// if (!user._id && user.builder) {
// await limits.checkMaxDevelopers()
// }
if (!tenantId) {
throw "No tenancy specified."
}

View File

@ -11,7 +11,7 @@ const { getAppDB } = require("@budibase/backend-core/context")
import { isTest } from "../../../environment"
import { cleanupAttachments } from "../../../utilities/rowProcessor"
import { runStaticFormulaChecks } from "./bulkFormula"
import * as Pro from "@budibase/pro"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export async function save(ctx: any) {
const db = getAppDB()
@ -120,10 +120,10 @@ export async function destroy(ctx: any) {
await db.bulkDocs(
rows.rows.map((row: any) => ({ ...row.doc, _deleted: true }))
)
await Pro.Licensing.Quotas.updateUsage(
await quotas.updateUsage(
-rows.rows.length,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.ROWS,
QuotaUsageType.STATIC
)
// update linked rows

View File

@ -26,7 +26,7 @@ import { getViews, saveView } from "../view/utils"
import viewTemplate from "../view/viewBuilder"
const { getAppDB } = require("@budibase/backend-core/context")
import { cloneDeep } from "lodash/fp"
import * as Pro from "@budibase/pro"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export async function clearColumns(table: any, columnNames: any) {
const db = getAppDB()
@ -117,7 +117,7 @@ export async function handleDataImport(user: any, table: any, dataImport: any) {
existingTable: table,
})
let finalData = []
let finalData: any = []
for (let i = 0; i < data.length; i++) {
let row = data[i]
row._id = generateRowID(table._id)
@ -147,19 +147,11 @@ export async function handleDataImport(user: any, table: any, dataImport: any) {
finalData.push(row)
}
await Pro.Licensing.Quotas.updateUsage(
await quotas.tryUpdateUsage(
() => db.bulkDocs(finalData),
finalData.length,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC,
{
dryRun: true,
}
)
await db.bulkDocs(finalData)
await Pro.Licensing.Quotas.updateUsage(
finalData.length,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.ROWS,
QuotaUsageType.STATIC
)
let response = await db.put(table)
table._rev = response._rev

View File

@ -12,7 +12,7 @@ const zlib = require("zlib")
const { mainRoutes, staticRoutes } = require("./routes")
const pkg = require("../../package.json")
const env = require("../environment")
const Pro = require("@budibase/pro")
const { middleware: pro } = require("@budibase/pro")
const router = new Router()
@ -56,7 +56,7 @@ router
.use(currentApp)
// this middleware will try to use the app ID to determine the tenancy
.use(buildAppTenancyMiddleware())
.use(Pro.Middleware.Licensing())
.use(pro.licensing())
.use(auditLog)
// error handling middleware

View File

@ -1,6 +1,6 @@
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
import { save } from "../../api/controllers/row"
import { cleanUpRow, getError } from "../automationUtils"
import * as Pro from "@budibase/pro"
import { buildCtx } from "./utils"
export const definition = {
@ -78,19 +78,11 @@ export async function run({ inputs, appId, emitter }: any) {
try {
inputs.row = await cleanUpRow(inputs.row.tableId, inputs.row)
await Pro.Licensing.Quotas.updateUsage(
await quotas.tryUpdateUsage(
() => save(ctx),
1,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC,
{
dryRun: true,
}
)
await save(ctx)
await Pro.Licensing.Quotas.updateUsage(
1,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.ROWS,
QuotaUsageType.STATIC
)
return {
row: inputs.row,

View File

@ -1,7 +1,7 @@
import { destroy } from "../../api/controllers/row"
import * as Pro from "@budibase/pro"
import { buildCtx } from "./utils"
import { getError } from "../automationUtils"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export const definition = {
description: "Delete a row from your database",
@ -73,11 +73,7 @@ export async function run({ inputs, appId, emitter }: any) {
})
try {
await Pro.Licensing.Quotas.updateUsage(
-1,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
)
await quotas.updateUsage(-1, StaticQuotaName.ROWS, QuotaUsageType.STATIC)
await destroy(ctx)
return {
response: ctx.body,

View File

@ -1,4 +1,4 @@
import * as Pro from "@budibase/pro"
import { quotas, StaticQuotaName, QuotaUsageType } from "@budibase/pro"
const { getUniqueRows } = require("../utilities/usageQuota/rows")
const {
isExternalTable,
@ -14,12 +14,12 @@ const METHOD_MAP: any = {
const DOMAIN_MAP: any = {
rows: {
name: Pro.StaticQuotaName.ROWS,
type: Pro.QuotaUsageType.STATIC,
name: StaticQuotaName.ROWS,
type: QuotaUsageType.STATIC,
},
applications: {
name: Pro.StaticQuotaName.APPS,
type: Pro.QuotaUsageType.STATIC,
name: StaticQuotaName.APPS,
type: QuotaUsageType.STATIC,
},
}
@ -32,7 +32,7 @@ function getQuotaInfo(url: string) {
}
module.exports = async (ctx: any, next: any) => {
if (!Pro.Licensing.Quotas.useQuotas()) {
if (!quotas.useQuotas()) {
return next()
}
@ -79,7 +79,7 @@ const performRequest = async (
const usageContext = {
skipNext: false,
skipUsage: false,
[Pro.StaticQuotaName.APPS]: {},
[StaticQuotaName.APPS]: {},
}
const quotaName = quotaInfo.name
@ -96,7 +96,7 @@ const performRequest = async (
// run the request
if (!usageContext.skipNext) {
await Pro.Licensing.Quotas.updateUsage(usage, quotaName, quotaInfo.type, {
await quotas.updateUsage(usage, quotaName, quotaInfo.type, {
dryRun: true,
})
await next()
@ -114,7 +114,7 @@ const performRequest = async (
// update the usage
if (!usageContext.skipUsage) {
await Pro.Licensing.Quotas.updateUsage(usage, quotaName, quotaInfo.type)
await quotas.updateUsage(usage, quotaName, quotaInfo.type)
}
}
@ -128,18 +128,18 @@ const appPreDelete = async (ctx: any, usageContext: any) => {
// store the row count to delete
const rows = await getUniqueRows([ctx.appId])
if (rows.length) {
usageContext[Pro.StaticQuotaName.APPS] = { rowCount: rows.length }
usageContext[StaticQuotaName.APPS] = { rowCount: rows.length }
}
}
const appPostDelete = async (ctx: any, usageContext: any) => {
// delete the app rows from usage
const rowCount = usageContext[Pro.StaticQuotaName.APPS].rowCount
const rowCount = usageContext[StaticQuotaName.APPS].rowCount
if (rowCount) {
await Pro.Licensing.Quotas.updateUsage(
await quotas.updateUsage(
-rowCount,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.ROWS,
QuotaUsageType.STATIC
)
}
}
@ -149,24 +149,24 @@ const appPostCreate = async (ctx: any) => {
if (ctx.request.body.useTemplate === "true") {
const rows = await getUniqueRows([ctx.response.body.appId])
const rowCount = rows ? rows.length : 0
await Pro.Licensing.Quotas.updateUsage(
await quotas.updateUsage(
rowCount,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.ROWS,
QuotaUsageType.STATIC
)
}
}
const PRE_DELETE: any = {
[Pro.StaticQuotaName.APPS]: appPreDelete,
[StaticQuotaName.APPS]: appPreDelete,
}
const POST_DELETE: any = {
[Pro.StaticQuotaName.APPS]: appPostDelete,
[StaticQuotaName.APPS]: appPostDelete,
}
const PRE_CREATE: any = {}
const POST_CREATE: any = {
[Pro.StaticQuotaName.APPS]: appPostCreate,
[StaticQuotaName.APPS]: appPostCreate,
}

View File

@ -1,7 +1,7 @@
import * as Pro from "@budibase/pro"
import { quotas } from "@budibase/pro"
export const runQuotaMigration = async (migration: Function) => {
if (!Pro.Licensing.Quotas.useQuotas()) {
if (!quotas.useQuotas()) {
return
}
await migration()

View File

@ -1,6 +1,6 @@
import { getTenantId } from "@budibase/backend-core/tenancy"
import { getAllApps } from "@budibase/backend-core/db"
import * as Pro from "@budibase/pro"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export const run = async () => {
// get app count
@ -11,9 +11,5 @@ export const run = async () => {
// sync app count
const tenantId = getTenantId()
console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`)
await Pro.Licensing.Quotas.setUsage(
appCount,
Pro.StaticQuotaName.APPS,
Pro.QuotaUsageType.STATIC
)
await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC)
}

View File

@ -1,6 +1,6 @@
import { getTenantId } from "@budibase/backend-core/tenancy"
import { utils } from "@budibase/backend-core"
import * as Pro from "@budibase/pro"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export const run = async () => {
// get developer count
@ -11,9 +11,9 @@ export const run = async () => {
console.log(
`[Tenant: ${tenantId}] Syncing developer count: ${developerCount}`
)
await Pro.Licensing.Quotas.setUsage(
await quotas.setUsage(
developerCount,
Pro.StaticQuotaName.DEVELOPERS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.DEVELOPERS,
QuotaUsageType.STATIC
)
}

View File

@ -1,6 +1,6 @@
import { getTenantId } from "@budibase/backend-core/tenancy"
import { getAllApps } from "@budibase/backend-core/db"
import * as Pro from "@budibase/pro"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export const run = async () => {
// get app count
@ -13,9 +13,9 @@ export const run = async () => {
console.log(
`[Tenant: ${tenantId}] Syncing published app count: ${prodAppCount}`
)
await Pro.Licensing.Quotas.setUsage(
await quotas.setUsage(
prodAppCount,
Pro.StaticQuotaName.PUBLISHED_APPS,
Pro.QuotaUsageType.STATIC
StaticQuotaName.PUBLISHED_APPS,
QuotaUsageType.STATIC
)
}

View File

@ -1,7 +1,7 @@
import { getTenantId } from "@budibase/backend-core/tenancy"
import { getAllApps } from "@budibase/backend-core/db"
import * as Pro from "@budibase/pro"
import { getUniqueRows } from "../../../utilities/usageQuota/rows"
import { quotas, QuotaUsageType, StaticQuotaName } from "@budibase/pro"
export const run = async () => {
// get all rows in all apps
@ -15,9 +15,5 @@ export const run = async () => {
// sync row count
const tenantId = getTenantId()
console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`)
await Pro.Licensing.Quotas.setUsage(
rowCount,
Pro.StaticQuotaName.ROWS,
Pro.QuotaUsageType.STATIC
)
await quotas.setUsage(rowCount, StaticQuotaName.ROWS, QuotaUsageType.STATIC)
}

View File

@ -1,7 +0,0 @@
import * as pro from "@budibase/pro"
export const run = () => {
if (process.env.PRO) {
console.log(pro)
}
}

View File

@ -21,8 +21,9 @@ const {
isMultiTenant,
} = require("@budibase/backend-core/tenancy")
const env = require("../../../environment")
import { users } from "@budibase/pro"
const ssoCallbackUrl = async (config, type) => {
const ssoCallbackUrl = async (config: any, type: any) => {
// incase there is a callback URL from before
if (config && config.callbackURL) {
return config.callbackURL
@ -42,15 +43,15 @@ const ssoCallbackUrl = async (config, type) => {
return `${publicConfig.platformUrl}${callbackUrl}`
}
exports.googleCallbackUrl = async config => {
export const googleCallbackUrl = async (config: any) => {
return ssoCallbackUrl(config, "google")
}
exports.oidcCallbackUrl = async config => {
export const oidcCallbackUrl = async (config: any) => {
return ssoCallbackUrl(config, "oidc")
}
async function authInternal(ctx, user, err = null, info = null) {
async function authInternal(ctx: any, user: any, err = null, info = null) {
if (err) {
console.error("Authentication error", err)
return ctx.throw(403, info ? info : "Unauthorized")
@ -71,27 +72,30 @@ async function authInternal(ctx, user, err = null, info = null) {
}
}
exports.authenticate = async (ctx, next) => {
return passport.authenticate("local", async (err, user, info) => {
await authInternal(ctx, user, err, info)
ctx.status = 200
})(ctx, next)
export const authenticate = async (ctx: any, next: any) => {
return passport.authenticate(
"local",
async (err: any, user: any, info: any) => {
await authInternal(ctx, user, err, info)
ctx.status = 200
}
)(ctx, next)
}
exports.setInitInfo = ctx => {
export const setInitInfo = (ctx: any) => {
const initInfo = ctx.request.body
setCookie(ctx, initInfo, Cookies.Init)
ctx.status = 200
}
exports.getInitInfo = ctx => {
export const getInitInfo = (ctx: any) => {
ctx.body = getCookie(ctx, Cookies.Init) || {}
}
/**
* Reset the user password, used as part of a forgotten password flow.
*/
exports.reset = async ctx => {
export const reset = async (ctx: any) => {
const { email } = ctx.request.body
const configured = await isEmailConfigured()
if (!configured) {
@ -121,7 +125,7 @@ exports.reset = async ctx => {
/**
* Perform the user password update if the provided reset code is valid.
*/
exports.resetUpdate = async ctx => {
export const resetUpdate = async (ctx: any) => {
const { resetCode, password } = ctx.request.body
try {
const { userId } = await checkResetPasswordCode(resetCode)
@ -137,14 +141,14 @@ exports.resetUpdate = async ctx => {
}
}
exports.logout = async ctx => {
export const logout = async (ctx: any) => {
if (ctx.user && ctx.user._id) {
await platformLogout({ ctx, userId: ctx.user._id })
}
ctx.body = { message: "User logged out." }
}
exports.datasourcePreAuth = async (ctx, next) => {
export const datasourcePreAuth = async (ctx: any, next: any) => {
const provider = ctx.params.provider
const middleware = require(`@budibase/backend-core/middleware`)
const handler = middleware.datasource[provider]
@ -162,7 +166,7 @@ exports.datasourcePreAuth = async (ctx, next) => {
return handler.preAuth(passport, ctx, next)
}
exports.datasourceAuth = async (ctx, next) => {
export const datasourceAuth = async (ctx: any, next: any) => {
const authStateCookie = getCookie(ctx, Cookies.DatasourceAuth)
const provider = authStateCookie.provider
const middleware = require(`@budibase/backend-core/middleware`)
@ -174,7 +178,7 @@ exports.datasourceAuth = async (ctx, next) => {
* The initial call that google authentication makes to take you to the google login screen.
* On a successful login, you will be redirected to the googleAuth callback route.
*/
exports.googlePreAuth = async (ctx, next) => {
export const googlePreAuth = async (ctx: any, next: any) => {
const db = getGlobalDB()
const config = await core.db.getScopedConfig(db, {
@ -182,14 +186,14 @@ exports.googlePreAuth = async (ctx, next) => {
workspace: ctx.query.workspace,
})
let callbackUrl = await exports.googleCallbackUrl(config)
const strategy = await google.strategyFactory(config, callbackUrl)
const strategy = await google.strategyFactory(config, callbackUrl, users.save)
return passport.authenticate(strategy, {
scope: ["profile", "email"],
})(ctx, next)
}
exports.googleAuth = async (ctx, next) => {
export const googleAuth = async (ctx: any, next: any) => {
const db = getGlobalDB()
const config = await core.db.getScopedConfig(db, {
@ -197,12 +201,12 @@ exports.googleAuth = async (ctx, next) => {
workspace: ctx.query.workspace,
})
const callbackUrl = await exports.googleCallbackUrl(config)
const strategy = await google.strategyFactory(config, callbackUrl)
const strategy = await google.strategyFactory(config, callbackUrl, users.save)
return passport.authenticate(
strategy,
{ successRedirect: "/", failureRedirect: "/error" },
async (err, user, info) => {
async (err: any, user: any, info: any) => {
await authInternal(ctx, user, err, info)
ctx.redirect("/")
@ -210,14 +214,14 @@ exports.googleAuth = async (ctx, next) => {
)(ctx, next)
}
async function oidcStrategyFactory(ctx, configId) {
async function oidcStrategyFactory(ctx: any, configId: any) {
const db = getGlobalDB()
const config = await core.db.getScopedConfig(db, {
type: Configs.OIDC,
group: ctx.query.group,
})
const chosenConfig = config.configs.filter(c => c.uuid === configId)[0]
const chosenConfig = config.configs.filter((c: any) => c.uuid === configId)[0]
let callbackUrl = await exports.oidcCallbackUrl(chosenConfig)
return oidc.strategyFactory(chosenConfig, callbackUrl)
@ -227,7 +231,7 @@ async function oidcStrategyFactory(ctx, configId) {
* The initial call that OIDC authentication makes to take you to the configured OIDC login screen.
* On a successful login, you will be redirected to the oidcAuth callback route.
*/
exports.oidcPreAuth = async (ctx, next) => {
export const oidcPreAuth = async (ctx: any, next: any) => {
const { configId } = ctx.params
const strategy = await oidcStrategyFactory(ctx, configId)
@ -239,14 +243,14 @@ exports.oidcPreAuth = async (ctx, next) => {
})(ctx, next)
}
exports.oidcAuth = async (ctx, next) => {
export const oidcAuth = async (ctx: any, next: any) => {
const configId = getCookie(ctx, Cookies.OIDC_CONFIG)
const strategy = await oidcStrategyFactory(ctx, configId)
return passport.authenticate(
strategy,
{ successRedirect: "/", failureRedirect: "/error" },
async (err, user, info) => {
async (err: any, user: any, info: any) => {
await authInternal(ctx, user, err, info)
ctx.redirect("/")

View File

@ -1,4 +1,4 @@
import * as Pro from "@budibase/pro"
import { licensing, quotas } from "@budibase/pro"
export const activate = async (ctx: any) => {
const { licenseKey } = ctx.request.body
@ -6,17 +6,17 @@ export const activate = async (ctx: any) => {
ctx.throw(400, "licenseKey is required")
}
await Pro.Licensing.activateLicenseKey(licenseKey)
await licensing.activateLicenseKey(licenseKey)
ctx.status = 200
}
export const refresh = async (ctx: any) => {
await Pro.Licensing.Cache.refresh()
await licensing.cache.refresh()
ctx.status = 200
}
export const getInfo = async (ctx: any) => {
const licenseInfo = await Pro.Licensing.getLicenseInfo()
const licenseInfo = await licensing.getLicenseInfo()
if (licenseInfo) {
licenseInfo.licenseKey = "*"
ctx.body = licenseInfo
@ -25,6 +25,6 @@ export const getInfo = async (ctx: any) => {
}
export const getQuotaUsage = async (ctx: any) => {
const usage = await Pro.Licensing.Quotas.getQuotaUsage()
const usage = await quotas.getQuotaUsage()
ctx.body = usage
}

View File

@ -5,7 +5,6 @@ const {
const {
hash,
getGlobalUserByEmail,
saveUser,
platformLogout,
} = require("@budibase/backend-core/utils")
import { EmailTemplatePurpose } from "../../../constants"
@ -23,8 +22,8 @@ const {
const { removeUserFromInfoDB } = require("@budibase/backend-core/deprovision")
import env from "../../../environment"
import { syncUserInApps } from "../../../utilities/appService"
import { quotas, users } from "@budibase/pro"
const { errors } = require("@budibase/backend-core")
import * as Pro from "@budibase/pro"
const allUsers = async () => {
const db = getGlobalDB()
@ -38,7 +37,7 @@ const allUsers = async () => {
export const save = async (ctx: any) => {
try {
const user = await saveUser(ctx.request.body, getTenantId())
const user = await users.save(ctx.request.body, getTenantId())
// let server know to sync user
await syncUserInApps(user._id)
ctx.body = user
@ -81,7 +80,7 @@ export const adminUser = async (ctx: any) => {
} catch (err) {
// don't worry about errors
}
await db.put(Pro.Licensing.Quotas.generateNewQuotaUsage())
await db.put(quotas.generateNewQuotaUsage())
}
if (response.rows.some((row: any) => row.doc.admin)) {
@ -105,7 +104,7 @@ export const adminUser = async (ctx: any) => {
tenantId,
}
try {
ctx.body = await saveUser(user, tenantId, hashPassword, requirePassword)
ctx.body = await users.save(user, tenantId, hashPassword, requirePassword)
} catch (err: any) {
ctx.throw(err.status || 400, err)
}
@ -286,7 +285,7 @@ export const inviteAccept = async (ctx: any) => {
try {
// info is an extension of the user object that was stored by global
const { email, info }: any = await checkInviteCode(inviteCode)
ctx.body = await saveUser(
ctx.body = await users.save(
{
firstName,
lastName,

View File

@ -8,7 +8,7 @@ const {
buildTenancyMiddleware,
buildCsrfMiddleware,
} = require("@budibase/backend-core/auth")
const Pro = require("@budibase/pro")
const { middleware: pro } = require("@budibase/pro")
const { errors } = require("@budibase/backend-core")
const PUBLIC_ENDPOINTS = [
@ -93,7 +93,7 @@ router
.use(buildAuthMiddleware(PUBLIC_ENDPOINTS))
.use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
.use(buildCsrfMiddleware({ noCsrfPatterns: NO_CSRF_ENDPOINTS }))
.use(Pro.Middleware.Licensing())
.use(pro.licensing())
// for now no public access is allowed to worker (bar health check)
.use((ctx, next) => {
if (ctx.publicEndpoint) {