Write users and activity to dynamo

This commit is contained in:
Rory Powell 2022-07-18 16:11:52 -04:00
parent 16b81bfc95
commit 617ec1fe02
23 changed files with 296 additions and 65 deletions

View File

@ -26,6 +26,11 @@ export const DeprecatedViews = {
], ],
} }
export type GlobalViewName =
| ViewNames.USER_BY_EMAIL
| ViewNames.BY_API_KEY
| ViewNames.USER_BY_BUILDERS
export enum DocumentTypes { export enum DocumentTypes {
USER = "us", USER = "us",
WORKSPACE = "workspace", WORKSPACE = "workspace",

View File

@ -1,10 +1,13 @@
const { import {
DocumentTypes, DocumentTypes,
ViewNames, ViewNames,
GlobalViewName,
DeprecatedViews, DeprecatedViews,
SEPARATOR, SEPARATOR,
} = require("./utils") } from "./utils"
const { getGlobalDB } = require("../tenancy") import { getGlobalDB } from "../tenancy"
import PouchDB from "pouchdb"
import { Document } from "@budibase/types"
const DESIGN_DB = "_design/database" const DESIGN_DB = "_design/database"
@ -17,12 +20,18 @@ function DesignDoc() {
} }
} }
async function removeDeprecated(db, viewName) { interface DesignDocument {
views: any
}
async function removeDeprecated(db: PouchDB.Database, viewName: ViewNames) {
// @ts-ignore
if (!DeprecatedViews[viewName]) { if (!DeprecatedViews[viewName]) {
return return
} }
try { try {
const designDoc = await db.get(DESIGN_DB) const designDoc = await db.get<DesignDocument>(DESIGN_DB)
// @ts-ignore
for (let deprecatedNames of DeprecatedViews[viewName]) { for (let deprecatedNames of DeprecatedViews[viewName]) {
delete designDoc.views[deprecatedNames] delete designDoc.views[deprecatedNames]
} }
@ -32,7 +41,7 @@ async function removeDeprecated(db, viewName) {
} }
} }
exports.createNewUserEmailView = async () => { export const createNewUserEmailView = async () => {
const db = getGlobalDB() const db = getGlobalDB()
let designDoc let designDoc
try { try {
@ -56,7 +65,7 @@ exports.createNewUserEmailView = async () => {
await db.put(designDoc) await db.put(designDoc)
} }
exports.createApiKeyView = async () => { export const createApiKeyView = async () => {
const db = getGlobalDB() const db = getGlobalDB()
let designDoc let designDoc
try { try {
@ -78,7 +87,7 @@ exports.createApiKeyView = async () => {
await db.put(designDoc) await db.put(designDoc)
} }
exports.createUserBuildersView = async () => { export const createUserBuildersView = async () => {
const db = getGlobalDB() const db = getGlobalDB()
let designDoc let designDoc
try { try {
@ -101,28 +110,32 @@ exports.createUserBuildersView = async () => {
await db.put(designDoc) await db.put(designDoc)
} }
exports.queryGlobalView = async (viewName, params, db = null) => { export const queryGlobalView = async <T extends Document>(
viewName: GlobalViewName,
params: PouchDB.Query.Options<T, T>,
db?: PouchDB.Database
): Promise<T[] | T | undefined> => {
const CreateFuncByName = { const CreateFuncByName = {
[ViewNames.USER_BY_EMAIL]: exports.createNewUserEmailView, [ViewNames.USER_BY_EMAIL]: createNewUserEmailView,
[ViewNames.BY_API_KEY]: exports.createApiKeyView, [ViewNames.BY_API_KEY]: createApiKeyView,
[ViewNames.USER_BY_BUILDERS]: exports.createUserBuildersView, [ViewNames.USER_BY_BUILDERS]: createUserBuildersView,
} }
// can pass DB in if working with something specific // can pass DB in if working with something specific
if (!db) { if (!db) {
db = getGlobalDB() db = getGlobalDB() as PouchDB.Database
} }
try { try {
let response = (await db.query(`database/${viewName}`, params)).rows const response = await db.query<T, T>(`database/${viewName}`, params)
response = response.map(resp => const rows = response.rows
params.include_docs ? resp.doc : resp.value const docs = rows.map(row => (params.include_docs ? row.doc : row.value))
) return docs.length <= 1 ? docs[0] : docs
return response.length <= 1 ? response[0] : response } catch (err: any) {
} catch (err) {
if (err != null && err.name === "not_found") { if (err != null && err.name === "not_found") {
const createFunc = CreateFuncByName[viewName] const createFunc = CreateFuncByName[viewName]
await removeDeprecated(db, viewName) await removeDeprecated(db, viewName)
await createFunc() await createFunc()
return exports.queryGlobalView(viewName, params) return queryGlobalView(viewName, params)
} else { } else {
throw err throw err
} }

View File

@ -13,7 +13,7 @@ import deprovisioning from "./context/deprovision"
import auth from "./auth" import auth from "./auth"
import constants from "./constants" import constants from "./constants"
import * as dbConstants from "./db/constants" import * as dbConstants from "./db/constants"
import logging from "./logging" import * as logging from "./logging"
// mimic the outer package exports // mimic the outer package exports
import * as db from "./pkg/db" import * as db from "./pkg/db"

View File

@ -127,7 +127,7 @@ module.exports = (
} }
if (!user && tenantId) { if (!user && tenantId) {
user = { tenantId } user = { tenantId }
} else { } else if (user) {
delete user.password delete user.password
} }
// be explicit // be explicit

View File

@ -1,37 +1,42 @@
const { ViewNames } = require("./db/utils") import { ViewNames } from "./db/utils"
const { queryGlobalView } = require("./db/views") import { queryGlobalView } from "./db/views"
const { UNICODE_MAX } = require("./db/constants") import { UNICODE_MAX } from "./db/constants"
import { User } from "@budibase/types"
/** /**
* Given an email address this will use a view to search through * Given an email address this will use a view to search through
* all the users to find one with this email address. * all the users to find one with this email address.
* @param {string} email the email to lookup the user by. * @param {string} email the email to lookup the user by.
* @return {Promise<object|null>}
*/ */
exports.getGlobalUserByEmail = async email => { export const getGlobalUserByEmail = async (email: String) => {
if (email == null) { if (email == null) {
throw "Must supply an email address to view" throw "Must supply an email address to view"
} }
const response = await queryGlobalView(ViewNames.USER_BY_EMAIL, { const response = await queryGlobalView<User>(ViewNames.USER_BY_EMAIL, {
key: email.toLowerCase(), key: email.toLowerCase(),
include_docs: true, include_docs: true,
}) })
if (Array.isArray(response)) {
// shouldn't be able to happen, but need to handle just in case
throw new Error(`Multiple users found with email address: ${email}`)
}
return response return response
} }
/** /**
* Performs a starts with search on the global email view. * Performs a starts with search on the global email view.
*/ */
exports.searchGlobalUsersByEmail = async (email, opts) => { export const searchGlobalUsersByEmail = async (email: string, opts: any) => {
if (typeof email !== "string") { if (typeof email !== "string") {
throw new Error("Must provide a string to search by") throw new Error("Must provide a string to search by")
} }
const lcEmail = email.toLowerCase() const lcEmail = email.toLowerCase()
// handle if passing up startkey for pagination // handle if passing up startkey for pagination
const startkey = opts && opts.startkey ? opts.startkey : lcEmail const startkey = opts && opts.startkey ? opts.startkey : lcEmail
let response = await queryGlobalView(ViewNames.USER_BY_EMAIL, { let response = await queryGlobalView<User>(ViewNames.USER_BY_EMAIL, {
...opts, ...opts,
startkey, startkey,
endkey: `${lcEmail}${UNICODE_MAX}`, endkey: `${lcEmail}${UNICODE_MAX}`,

View File

@ -56,6 +56,7 @@ router
) )
.use(currentApp) .use(currentApp)
.use(pro.licensing()) .use(pro.licensing())
.use(pro.activity())
.use(auditLog) .use(auditLog)
// error handling middleware // error handling middleware

View File

@ -111,12 +111,14 @@ module.exports = async (ctx, next) => {
ctx.appId = appId ctx.appId = appId
if (roleId) { if (roleId) {
ctx.roleId = roleId ctx.roleId = roleId
const globalId = ctx.user._id
const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null const userId = ctx.user ? generateUserMetadataID(ctx.user._id) : null
ctx.user = { ctx.user = {
...ctx.user, ...ctx.user,
// override userID with metadata one // override userID with metadata one
_id: userId, _id: userId,
userId, userId,
globalId,
roleId, roleId,
role: await getRole(roleId), role: await getRole(roleId),
} }

View File

@ -1094,12 +1094,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@1.1.7": "@budibase/backend-core@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.7.tgz#371048be47828da1f13e03b6d808bccb7114cdb5" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.15.tgz#c51b1a2411b842c4746b166d852ae1b026228b9f"
integrity sha512-FZnGTQihKugHnaim5osfITwTfIeachtO3ZERRqU68CpoJVI52oyzPixK1oUP2HYFGCcttqIJN90XD/keC1LzQQ== integrity sha512-FGqQ1m5ZJF6+vgxCX4bVDW/kyD70vgogs+3vknz42+P22mMXlEINRGKW+HQt0Z+WTkU+H+6vvhPqN3IW1fbhDQ==
dependencies: dependencies:
"@budibase/types" "^1.1.7" "@budibase/types" "^1.1.15"
"@techpass/passport-openidconnect" "0.3.2" "@techpass/passport-openidconnect" "0.3.2"
aws-sdk "2.1030.0" aws-sdk "2.1030.0"
bcrypt "5.0.1" bcrypt "5.0.1"
@ -1177,13 +1177,13 @@
svelte-flatpickr "^3.2.3" svelte-flatpickr "^3.2.3"
svelte-portal "^1.0.0" svelte-portal "^1.0.0"
"@budibase/pro@1.1.7": "@budibase/pro@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.7.tgz#b9120c60a38d4bbc87dc99ef219a8f23418b9d82" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.15.tgz#e14ad78af428d7f9091494c89ddf7c6cdc30fc62"
integrity sha512-APMPIWbxPWzAWWKBglGa1csbVxllAsF5Lt7e5hrNVfN51rzJ3TvQ56iIUru0xGOWpelDQWd4FXe1/dpN0hSvEA== integrity sha512-dBhjo2a2vlXifFvYhP5iefQm++zZtF2P1QLUGS+UIyiWfJNYA8e0nm0gZ3tE8JZk176Hk6fXmhTrbTKhq5jubA==
dependencies: dependencies:
"@budibase/backend-core" "1.1.7" "@budibase/backend-core" "1.1.15"
"@budibase/types" "1.1.7" "@budibase/types" "1.1.15"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@budibase/standard-components@^0.9.139": "@budibase/standard-components@^0.9.139":
@ -1204,10 +1204,15 @@
svelte-apexcharts "^1.0.2" svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0" svelte-flatpickr "^3.1.0"
"@budibase/types@1.1.7", "@budibase/types@^1.1.7": "@budibase/types@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.7.tgz#d1da67c6c6b09de639130775ed80290148434be0" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.15.tgz#4bfb218cd3e61236df8ef8cb1c4e6fdbc7cd608b"
integrity sha512-WkR9bS4DdVAAzIgzHDsfMLPBcXs+RVwzOXp2eSFrun1fZQfkiAnMO7+EYhYx4+zF6RLBXiF6iYXPDJLzviufGQ== integrity sha512-QD13Vp49bSWP5IPfvDLORVyoyed4y4lez2MeTADWsIHopi69MrjDA9eYuflQsVIvCdkxGVIXMuUms6AeAYqAoA==
"@budibase/types@^1.1.15":
version "1.1.16"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.16.tgz#4dd1f0b1e630abd46749414d74a1fdd07820df54"
integrity sha512-jaOdsCOx0CJ2tyKodTI6PMo9CNHTo1nsMMrRi/XFIFQtGOypkiNoskb5u0Ee3GtpN6LNXgwPdrYnh+vcIL9lRw==
"@bull-board/api@3.7.0": "@bull-board/api@3.7.0":
version "3.7.0" version "3.7.0"

View File

@ -14,6 +14,7 @@
"jest": {}, "jest": {},
"devDependencies": { "devDependencies": {
"@types/node": "14.18.20", "@types/node": "14.18.20",
"@types/koa": "2.13.4",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "4.7.3" "typescript": "4.7.3"
} }

View File

@ -0,0 +1 @@
export * from "./user"

View File

@ -0,0 +1,17 @@
export interface PutAccountUser {
createdAt: number
}
export interface PutAccountUserResponse {
userId: string
createdAt: number
}
export interface PostAccountUserActivity {
timestamp: number
}
export interface PostAccountUserActivityResponse {
userId: string
timestamp: number
}

View File

@ -0,0 +1 @@
export * from "./account"

View File

@ -1 +1,2 @@
export * from "./account" export * from "./account"
export * from "./user"

View File

@ -0,0 +1,20 @@
export interface SaveAccountUser {
accountId: string
userId: string
createdAt: number
}
export interface AccountUser extends SaveAccountUser {
tenantId: string // for backwards compatibility with the accounts table. Really this is a USER#<id>
}
export interface CreateAccountUserActivity {
accountId: string
userId: string
timestamp: number
}
export interface AccountUserActivity extends CreateAccountUserActivity {
PK: string
SK: string
}

View File

@ -14,6 +14,7 @@ export interface User extends Document {
password?: string password?: string
status?: string status?: string
createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now() createdAt?: number // override the default createdAt behaviour - users sdk historically set this to Date.now()
forceResetPassword?: boolean
} }
export interface UserRoles { export interface UserRoles {

View File

@ -2,3 +2,4 @@ export * from "./documents"
export * from "./sdk/events" export * from "./sdk/events"
export * from "./sdk/licensing" export * from "./sdk/licensing"
export * from "./sdk" export * from "./sdk"
export * from "./api"

View File

@ -3,3 +3,4 @@ export * from "./context"
export * from "./events" export * from "./events"
export * from "./licensing" export * from "./licensing"
export * from "./migrations" export * from "./migrations"
export * from "./koa"

View File

@ -0,0 +1,11 @@
import { Context } from "koa"
import { User } from "../documents"
export interface ContextUser extends User {
globalId?: string
}
export interface BBContext extends Context {
user?: ContextUser
body: any
}

View File

@ -2,11 +2,145 @@
# yarn lockfile v1 # yarn lockfile v1
"@types/accepts@*":
version "1.3.5"
resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.5.tgz#c34bec115cfc746e04fe5a059df4ce7e7b391575"
integrity sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==
dependencies:
"@types/node" "*"
"@types/body-parser@*":
version "1.19.2"
resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.19.2.tgz#aea2059e28b7658639081347ac4fab3de166e6f0"
integrity sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==
dependencies:
"@types/connect" "*"
"@types/node" "*"
"@types/connect@*":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.35.tgz#5fcf6ae445e4021d1fc2219a4873cc73a3bb2ad1"
integrity sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==
dependencies:
"@types/node" "*"
"@types/content-disposition@*":
version "0.5.5"
resolved "https://registry.yarnpkg.com/@types/content-disposition/-/content-disposition-0.5.5.tgz#650820e95de346e1f84e30667d168c8fd25aa6e3"
integrity sha512-v6LCdKfK6BwcqMo+wYW05rLS12S0ZO0Fl4w1h4aaZMD7bqT3gVUns6FvLJKGZHQmYn3SX55JWGpziwJRwVgutA==
"@types/cookies@*":
version "0.7.7"
resolved "https://registry.yarnpkg.com/@types/cookies/-/cookies-0.7.7.tgz#7a92453d1d16389c05a5301eef566f34946cfd81"
integrity sha512-h7BcvPUogWbKCzBR2lY4oqaZbO3jXZksexYJVFvkrFeLgbZjQkU4x8pRq6eg2MHXQhY0McQdqmmsxRWlVAHooA==
dependencies:
"@types/connect" "*"
"@types/express" "*"
"@types/keygrip" "*"
"@types/node" "*"
"@types/express-serve-static-core@^4.17.18":
version "4.17.29"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.29.tgz#2a1795ea8e9e9c91b4a4bbe475034b20c1ec711c"
integrity sha512-uMd++6dMKS32EOuw1Uli3e3BPgdLIXmezcfHv7N4c1s3gkhikBplORPpMq3fuWkxncZN1reb16d5n8yhQ80x7Q==
dependencies:
"@types/node" "*"
"@types/qs" "*"
"@types/range-parser" "*"
"@types/express@*":
version "4.17.13"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.13.tgz#a76e2995728999bab51a33fabce1d705a3709034"
integrity sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==
dependencies:
"@types/body-parser" "*"
"@types/express-serve-static-core" "^4.17.18"
"@types/qs" "*"
"@types/serve-static" "*"
"@types/http-assert@*":
version "1.5.3"
resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.5.3.tgz#ef8e3d1a8d46c387f04ab0f2e8ab8cb0c5078661"
integrity sha512-FyAOrDuQmBi8/or3ns4rwPno7/9tJTijVW6aQQjK02+kOQ8zmoNg2XJtAuQhvQcy1ASJq38wirX5//9J1EqoUA==
"@types/http-errors@*":
version "1.8.2"
resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-1.8.2.tgz#7315b4c4c54f82d13fa61c228ec5c2ea5cc9e0e1"
integrity sha512-EqX+YQxINb+MeXaIqYDASb6U6FCHbWjkj4a1CKDBks3d/QiB2+PqBLyO72vLDgAO1wUI4O+9gweRcQK11bTL/w==
"@types/keygrip@*":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@types/keygrip/-/keygrip-1.0.2.tgz#513abfd256d7ad0bf1ee1873606317b33b1b2a72"
integrity sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==
"@types/koa-compose@*":
version "3.2.5"
resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.5.tgz#85eb2e80ac50be95f37ccf8c407c09bbe3468e9d"
integrity sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==
dependencies:
"@types/koa" "*"
"@types/koa@*":
version "2.13.5"
resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.5.tgz#64b3ca4d54e08c0062e89ec666c9f45443b21a61"
integrity sha512-HSUOdzKz3by4fnqagwthW/1w/yJspTgppyyalPVbgZf8jQWvdIXcVW5h2DGtw4zYntOaeRGx49r1hxoPWrD4aA==
dependencies:
"@types/accepts" "*"
"@types/content-disposition" "*"
"@types/cookies" "*"
"@types/http-assert" "*"
"@types/http-errors" "*"
"@types/keygrip" "*"
"@types/koa-compose" "*"
"@types/node" "*"
"@types/koa@2.13.4":
version "2.13.4"
resolved "https://registry.yarnpkg.com/@types/koa/-/koa-2.13.4.tgz#10620b3f24a8027ef5cbae88b393d1b31205726b"
integrity sha512-dfHYMfU+z/vKtQB7NUrthdAEiSvnLebvBjwHtfFmpZmB7em2N3WVQdHgnFq+xvyVgxW5jKDmjWfLD3lw4g4uTw==
dependencies:
"@types/accepts" "*"
"@types/content-disposition" "*"
"@types/cookies" "*"
"@types/http-assert" "*"
"@types/http-errors" "*"
"@types/keygrip" "*"
"@types/koa-compose" "*"
"@types/node" "*"
"@types/mime@^1":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a"
integrity sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==
"@types/node@*":
version "18.0.6"
resolved "https://registry.yarnpkg.com/@types/node/-/node-18.0.6.tgz#0ba49ac517ad69abe7a1508bc9b3a5483df9d5d7"
integrity sha512-/xUq6H2aQm261exT6iZTMifUySEt4GR5KX8eYyY+C4MSNPqSh9oNIP7tz2GLKTlFaiBbgZNxffoR3CVRG+cljw==
"@types/node@14.18.20": "@types/node@14.18.20":
version "14.18.20" version "14.18.20"
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.20.tgz#268f028b36eaf51181c3300252f605488c4f0650" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.20.tgz#268f028b36eaf51181c3300252f605488c4f0650"
integrity sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA== integrity sha512-Q8KKwm9YqEmUBRsqJ2GWJDtXltBDxTdC4m5vTdXBolu2PeQh8LX+f6BTwU+OuXPu37fLxoN6gidqBmnky36FXA==
"@types/qs@*":
version "6.9.7"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.7.tgz#63bb7d067db107cc1e457c303bc25d511febf6cb"
integrity sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==
"@types/range-parser@*":
version "1.2.4"
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
"@types/serve-static@*":
version "1.13.10"
resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.10.tgz#f5e0ce8797d2d7cc5ebeda48a52c96c4fa47a8d9"
integrity sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==
dependencies:
"@types/mime" "^1"
"@types/node" "*"
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"

View File

@ -101,6 +101,7 @@ router
.use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS)) .use(buildTenancyMiddleware(PUBLIC_ENDPOINTS, NO_TENANCY_ENDPOINTS))
.use(buildCsrfMiddleware({ noCsrfPatterns: NO_CSRF_ENDPOINTS })) .use(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) {

View File

@ -1,6 +1,7 @@
import env from "../../environment" import env from "../../environment"
import { events, accounts, tenancy } from "@budibase/backend-core" import { events, accounts, tenancy } from "@budibase/backend-core"
import { User, UserRoles, CloudAccount } from "@budibase/types" import { User, UserRoles, CloudAccount } from "@budibase/types"
import { users as pro } from "@budibase/pro"
export const handleDeleteEvents = async (user: any) => { export const handleDeleteEvents = async (user: any) => {
await events.user.deleted(user) await events.user.deleted(user)
@ -51,7 +52,10 @@ const handleAppRoleEvents = async (user: any, existingUser: any) => {
await unassignAppRoleEvents(user, roles, existingRoles) await unassignAppRoleEvents(user, roles, existingRoles)
} }
export const handleSaveEvents = async (user: any, existingUser: any) => { export const handleSaveEvents = async (
user: User,
existingUser: User | undefined
) => {
const tenantId = tenancy.getTenantId() const tenantId = tenancy.getTenantId()
let tenantAccount: CloudAccount | undefined let tenantAccount: CloudAccount | undefined
if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) { if (!env.SELF_HOSTED && !env.DISABLE_ACCOUNT_PORTAL) {
@ -79,6 +83,7 @@ export const handleSaveEvents = async (user: any, existingUser: any) => {
} }
} else { } else {
await events.user.created(user) await events.user.created(user)
await pro.createAccountUser(user)
} }
if (isAddingBuilder(user, existingUser)) { if (isAddingBuilder(user, existingUser)) {

View File

@ -15,7 +15,7 @@ import {
accounts, accounts,
migrations, migrations,
} from "@budibase/backend-core" } from "@budibase/backend-core"
import { MigrationType } from "@budibase/types" import { MigrationType, User } from "@budibase/types"
const PAGE_LIMIT = 8 const PAGE_LIMIT = 8
@ -88,7 +88,7 @@ interface SaveUserOpts {
} }
export const save = async ( export const save = async (
user: any, user: User,
opts: SaveUserOpts = { opts: SaveUserOpts = {
hashPassword: true, hashPassword: true,
requirePassword: true, requirePassword: true,
@ -99,9 +99,9 @@ export const save = async (
const db = tenancy.getGlobalDB() const db = tenancy.getGlobalDB()
let { email, password, _id } = user let { email, password, _id } = user
// make sure another user isn't using the same email // make sure another user isn't using the same email
let dbUser: any let dbUser: User | undefined
if (opts.bulkCreate) { if (opts.bulkCreate) {
dbUser = null dbUser = undefined
} else if (email) { } else if (email) {
// check budibase users inside the tenant // check budibase users inside the tenant
dbUser = await usersCore.getGlobalUserByEmail(email) dbUser = await usersCore.getGlobalUserByEmail(email)

View File

@ -291,12 +291,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@1.1.7": "@budibase/backend-core@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.7.tgz#371048be47828da1f13e03b6d808bccb7114cdb5" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.1.15.tgz#c51b1a2411b842c4746b166d852ae1b026228b9f"
integrity sha512-FZnGTQihKugHnaim5osfITwTfIeachtO3ZERRqU68CpoJVI52oyzPixK1oUP2HYFGCcttqIJN90XD/keC1LzQQ== integrity sha512-FGqQ1m5ZJF6+vgxCX4bVDW/kyD70vgogs+3vknz42+P22mMXlEINRGKW+HQt0Z+WTkU+H+6vvhPqN3IW1fbhDQ==
dependencies: dependencies:
"@budibase/types" "^1.1.7" "@budibase/types" "^1.1.15"
"@techpass/passport-openidconnect" "0.3.2" "@techpass/passport-openidconnect" "0.3.2"
aws-sdk "2.1030.0" aws-sdk "2.1030.0"
bcrypt "5.0.1" bcrypt "5.0.1"
@ -324,19 +324,24 @@
uuid "8.3.2" uuid "8.3.2"
zlib "1.0.5" zlib "1.0.5"
"@budibase/pro@1.1.7": "@budibase/pro@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.7.tgz#b9120c60a38d4bbc87dc99ef219a8f23418b9d82" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.1.15.tgz#e14ad78af428d7f9091494c89ddf7c6cdc30fc62"
integrity sha512-APMPIWbxPWzAWWKBglGa1csbVxllAsF5Lt7e5hrNVfN51rzJ3TvQ56iIUru0xGOWpelDQWd4FXe1/dpN0hSvEA== integrity sha512-dBhjo2a2vlXifFvYhP5iefQm++zZtF2P1QLUGS+UIyiWfJNYA8e0nm0gZ3tE8JZk176Hk6fXmhTrbTKhq5jubA==
dependencies: dependencies:
"@budibase/backend-core" "1.1.7" "@budibase/backend-core" "1.1.15"
"@budibase/types" "1.1.7" "@budibase/types" "1.1.15"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@budibase/types@1.1.7", "@budibase/types@^1.1.7": "@budibase/types@1.1.15":
version "1.1.7" version "1.1.15"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.7.tgz#d1da67c6c6b09de639130775ed80290148434be0" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.15.tgz#4bfb218cd3e61236df8ef8cb1c4e6fdbc7cd608b"
integrity sha512-WkR9bS4DdVAAzIgzHDsfMLPBcXs+RVwzOXp2eSFrun1fZQfkiAnMO7+EYhYx4+zF6RLBXiF6iYXPDJLzviufGQ== integrity sha512-QD13Vp49bSWP5IPfvDLORVyoyed4y4lez2MeTADWsIHopi69MrjDA9eYuflQsVIvCdkxGVIXMuUms6AeAYqAoA==
"@budibase/types@^1.1.15":
version "1.1.16"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-1.1.16.tgz#4dd1f0b1e630abd46749414d74a1fdd07820df54"
integrity sha512-jaOdsCOx0CJ2tyKodTI6PMo9CNHTo1nsMMrRi/XFIFQtGOypkiNoskb5u0Ee3GtpN6LNXgwPdrYnh+vcIL9lRw==
"@cspotcode/source-map-consumer@0.8.0": "@cspotcode/source-map-consumer@0.8.0":
version "0.8.0" version "0.8.0"