Add developer usage restrictions to SSO user creation
This commit is contained in:
parent
893f82ac4d
commit
62b360b9ea
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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."
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
import * as pro from "@budibase/pro"
|
||||
|
||||
export const run = () => {
|
||||
if (process.env.PRO) {
|
||||
console.log(pro)
|
||||
}
|
||||
}
|
|
@ -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("/")
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue