Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic user relationship to user column migration #12102

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
3634687
Create endpoint and controller function for user column migration.
samwho Oct 18, 2023
5747f30
Precondition checks to make sure the migration is from the right colu…
samwho Oct 18, 2023
2002433
Merge branch 'master' into feature/budi-7607-migrate-user-relationshi…
mike12345567 Oct 18, 2023
c25de74
Action Michael's feedback about the structure of this feature.
samwho Oct 18, 2023
c84abb3
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 18, 2023
6e9c643
Merge branch 'feature/budi-7607-migrate-user-relationship-columns-to-…
samwho Oct 18, 2023
6ae5451
Create failing test.
samwho Oct 18, 2023
1771b59
Most of the way to getting my first test passing.
samwho Oct 18, 2023
6517150
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 18, 2023
7772973
First test passes!
samwho Oct 19, 2023
2176fe7
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 19, 2023
a3ad878
Implement many-to-many user column migrations.
samwho Oct 19, 2023
a563cf3
Merge master.
samwho Oct 23, 2023
2d26597
Fix tests after merge.
samwho Oct 23, 2023
86458dc
Merge branch 'feature/budi-7607-migrate-user-relationship-columns-to-…
samwho Oct 23, 2023
9dd1638
Merge base branch.
samwho Oct 23, 2023
06f0a8d
Update pro submodule.
samwho Oct 23, 2023
2e0b528
Update pro submodule.
samwho Oct 23, 2023
9e279be
Put pro back to where it was.
samwho Oct 23, 2023
3fc2ff2
Put pro back to where it was.
samwho Oct 23, 2023
febfab0
Fix tests/types.
samwho Oct 23, 2023
5e6ed0f
Implement many-to-one user column migration.
samwho Oct 23, 2023
6d5308a
Merge pull request #12117 from Budibase/feature/budi-7607-migrate-use…
samwho Oct 23, 2023
87d5e32
Merge pull request #12151 from Budibase/feature/budi-7607-migrate-use…
samwho Oct 23, 2023
42e31d1
Merge master.
samwho Oct 23, 2023
a701933
Frontend changes for the user column migration work.
samwho Oct 23, 2023
2f0a40e
Introduce modal to show warning to users, and toast to show success.
samwho Oct 24, 2023
d3670dd
Add an input to allow the user to choose the new column name.
samwho Oct 24, 2023
f4c6ab7
Make sure the user cannot enter the same column name as the old colum…
samwho Oct 24, 2023
a8ae168
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 24, 2023
fb99850
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 24, 2023
0f5c2cf
Handle a couple more edge cases more gracefully.
samwho Oct 24, 2023
78afba6
Emit table updates to the builder socket, and some minor refactoring.
samwho Oct 25, 2023
52f97fb
Attempt to emit events that include the originator.
samwho Oct 25, 2023
70f39b6
Fix missing sourceId on Table sent to the websocket.
samwho Oct 25, 2023
007e919
Spring cleaning before review.
samwho Oct 25, 2023
e3a702c
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 25, 2023
fbf60ec
Merge base branch.
samwho Oct 25, 2023
5779e97
Add column name input validation.
samwho Oct 25, 2023
402a53c
User constant for user table ID.
samwho Oct 25, 2023
0ac6b17
Remove stray console.log
samwho Oct 25, 2023
c9e3b7a
Remove the previous attempt at syncing grid state, it is no longer ne…
samwho Oct 25, 2023
7acce7b
Remove unused dispatch import.
samwho Oct 25, 2023
2c5dd99
Use FieldSubtype enum instead of raw strings.
samwho Oct 25, 2023
ef84e96
Use RelationshipType enum instead of raw string.
samwho Oct 25, 2023
c509748
Use FieldType constant instead of raw string.
samwho Oct 25, 2023
e03b1be
Make sure new column name cannot be the same as an existing column name.
samwho Oct 25, 2023
4a00649
Simplify the function signature of processInternalTables
samwho Oct 25, 2023
6c3b535
Simplify try-catch in the migrate function.
samwho Oct 25, 2023
455b26b
Making sure the source ID is always set when creating a table - the f…
mike12345567 Oct 25, 2023
fd0d8f1
Making sure single table get also includes sourceId.
mike12345567 Oct 25, 2023
b3c08f0
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 26, 2023
26100ff
Merge branch 'feature/budi-7607-migrate-user-relationship-columns-to-…
samwho Oct 26, 2023
9edaca0
Merge pull request #12158 from Budibase/feature/budi-7607-migrate-use…
samwho Oct 26, 2023
ed0670a
Major update to make the table.type always 'table' and then adding a …
mike12345567 Oct 26, 2023
536d85d
WIP: Improving the use of DatabaseQueryOpts.
samwho Oct 26, 2023
ae356b6
Bump version of @budibase/nano to complete the DatabaseQueryOpts type…
samwho Oct 26, 2023
19eaafd
Fixing some test cases.
mike12345567 Oct 26, 2023
115a67c
Fixing test case.
mike12345567 Oct 26, 2023
fd29b8d
PR comments.
mike12345567 Oct 26, 2023
d0f9895
Updating tests to be more consistent in how they pick to create an in…
mike12345567 Oct 26, 2023
983091e
Fix for tests - row.spec.ts needs to pick correct table create.
mike12345567 Oct 26, 2023
d13cc80
Removing update to gitignore.
mike12345567 Oct 26, 2023
e12cef3
Fixing export.
mike12345567 Oct 26, 2023
854ff47
Final fix - removing external from create table (internal).
mike12345567 Oct 26, 2023
731ff06
Merge pull request #12185 from Budibase/feature/budi-7607-migrate-use…
samwho Oct 27, 2023
9b1a7bd
PR comments - updating pickAPI to use a common function.
mike12345567 Oct 27, 2023
2bfdd97
Merge pull request #12177 from Budibase/feature/make-table-source-id-…
mike12345567 Oct 27, 2023
c0a9b0a
Merge branch 'master' into feature/budi-7607-migrate-user-relationshi…
mike12345567 Oct 27, 2023
d04f219
Merge branch 'master' of github.com:Budibase/budibase into feature/bu…
samwho Oct 27, 2023
45543cb
Catch a few more edge cases with column names, add tests for them.
samwho Oct 27, 2023
d0fecc1
Merge branch 'master' into feature/budi-7607-migrate-user-relationshi…
samwho Oct 30, 2023
9643d9c
Merge branch 'master' into feature/budi-7607-migrate-user-relationshi…
mike12345567 Oct 30, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/backend-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"test:watch": "jest --watchAll"
},
"dependencies": {
"@budibase/nano": "10.1.2",
"@budibase/nano": "10.1.3",
"@budibase/pouchdb-replication-stream": "1.2.10",
"@budibase/shared-core": "0.0.0",
"@budibase/types": "0.0.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/backend-core/src/db/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ export const CONSTANT_INTERNAL_ROW_COLS = [
] as const

export const CONSTANT_EXTERNAL_ROW_COLS = ["_id", "_rev", "tableId"] as const

export function isInternalColumnName(name: string): boolean {
return (CONSTANT_INTERNAL_ROW_COLS as readonly string[]).includes(name)
}
29 changes: 21 additions & 8 deletions packages/backend-core/src/docIds/params.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
ViewName,
} from "../constants"
import { getProdAppID } from "./conversions"
import { DatabaseQueryOpts } from "@budibase/types"

/**
* If creating DB allDocs/query params with only a single top level ID this can be used, this
Expand All @@ -22,8 +23,8 @@ import { getProdAppID } from "./conversions"
export function getDocParams(
docType: string,
docId?: string | null,
otherProps: any = {}
) {
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
if (docId == null) {
docId = ""
}
Expand All @@ -45,8 +46,8 @@ export function getDocParams(
export function getRowParams(
tableId?: string | null,
rowId?: string | null,
otherProps = {}
) {
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
if (tableId == null) {
return getDocParams(DocumentType.ROW, null, otherProps)
}
Expand Down Expand Up @@ -88,7 +89,10 @@ export const isDatasourceId = (id: string) => {
/**
* Gets parameters for retrieving workspaces.
*/
export function getWorkspaceParams(id = "", otherProps = {}) {
export function getWorkspaceParams(
id = "",
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
return {
...otherProps,
startkey: `${DocumentType.WORKSPACE}${SEPARATOR}${id}`,
Expand All @@ -99,7 +103,10 @@ export function getWorkspaceParams(id = "", otherProps = {}) {
/**
* Gets parameters for retrieving users.
*/
export function getGlobalUserParams(globalId: any, otherProps: any = {}) {
export function getGlobalUserParams(
globalId: any,
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
if (!globalId) {
globalId = ""
}
Expand All @@ -117,11 +124,17 @@ export function getGlobalUserParams(globalId: any, otherProps: any = {}) {
/**
* Gets parameters for retrieving users, this is a utility function for the getDocParams function.
*/
export function getUserMetadataParams(userId?: string | null, otherProps = {}) {
export function getUserMetadataParams(
userId?: string | null,
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
return getRowParams(InternalTable.USER_METADATA, userId, otherProps)
}

export function getUsersByAppParams(appId: any, otherProps: any = {}) {
export function getUsersByAppParams(
appId: any,
otherProps: Partial<DatabaseQueryOpts> = {}
): DatabaseQueryOpts {
const prodAppId = getProdAppID(appId)
return {
...otherProps,
Expand Down
6 changes: 1 addition & 5 deletions packages/backend-core/src/users/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,13 +165,9 @@ export class UserDB {
}

static async getUsersByAppAccess(opts: { appId?: string; limit?: number }) {
const params: any = {
include_docs: true,
limit: opts.limit || 50,
}
let response: User[] = await usersCore.searchGlobalUsersByAppAccess(
opts.appId,
params
{ limit: opts.limit || 50 }
)
return response
}
Expand Down
12 changes: 8 additions & 4 deletions packages/backend-core/src/users/users.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
User,
ContextUser,
DatabaseQueryOpts,
CouchFindOptions,
} from "@budibase/types"
import { getGlobalDB } from "../context"
import * as context from "../context"
Expand Down Expand Up @@ -140,7 +141,7 @@ export const getGlobalUserByEmail = async (

export const searchGlobalUsersByApp = async (
appId: any,
opts: any,
opts: DatabaseQueryOpts,
getOpts?: GetOpts
) => {
if (typeof appId !== "string") {
Expand All @@ -166,7 +167,10 @@ export const searchGlobalUsersByApp = async (
Return any user who potentially has access to the application
Admins, developers and app users with the explicitly role.
*/
export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => {
export const searchGlobalUsersByAppAccess = async (
appId: any,
opts?: { limit?: number }
) => {
const roleSelector = `roles.${appId}`

let orQuery: any[] = [
Expand All @@ -187,7 +191,7 @@ export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => {
orQuery.push(roleCheck)
}

let searchOptions = {
let searchOptions: CouchFindOptions = {
selector: {
$or: orQuery,
_id: {
Expand All @@ -198,7 +202,7 @@ export const searchGlobalUsersByAppAccess = async (appId: any, opts: any) => {
}

const resp = await directCouchFind(context.getGlobalDBName(), searchOptions)
return resp?.rows
return resp.rows
}

export const getGlobalUserByAppPage = (appId: string, user: User) => {
Expand Down
2 changes: 1 addition & 1 deletion packages/builder/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ package-lock.json
release/
dist/
routify
.routify/
.routify/
6 changes: 3 additions & 3 deletions packages/builder/src/builderStore/store/frontend.js
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ export const getFrontendStore = () => {
let table = validTables.find(table => {
return (
table.sourceId !== BUDIBASE_INTERNAL_DB_ID &&
table.type === DB_TYPE_INTERNAL
table.sourceType === DB_TYPE_INTERNAL
)
})
if (table) {
Expand All @@ -591,15 +591,15 @@ export const getFrontendStore = () => {
table = validTables.find(table => {
return (
table.sourceId === BUDIBASE_INTERNAL_DB_ID &&
table.type === DB_TYPE_INTERNAL
table.sourceType === DB_TYPE_INTERNAL
)
})
if (table) {
return table
}

// Finally try an external table
return validTables.find(table => table.type === DB_TYPE_EXTERNAL)
return validTables.find(table => table.sourceType === DB_TYPE_EXTERNAL)
},
enrichEmptySettings: (component, opts) => {
if (!component?._component) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
$: linkedTable = $tables.list.find(table => table._id === linkedTableId)
$: schema = linkedTable?.schema
$: table = $tables.list.find(table => table._id === tableId)
$: type = table?.type
$: fetchData(tableId, rowId)
$: {
let rowLabel = row?.[table?.primaryDisplay]
Expand All @@ -41,5 +40,5 @@
</script>

{#if row && row._id === rowId}
<Table {title} {schema} {data} {type} />
<Table {title} {schema} {data} />
{/if}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import GridRelationshipButton from "components/backend/DataTable/buttons/grid/GridRelationshipButton.svelte"
import GridEditColumnModal from "components/backend/DataTable/modals/grid/GridEditColumnModal.svelte"
import GridUsersTableButton from "components/backend/DataTable/modals/grid/GridUsersTableButton.svelte"
import { DB_TYPE_EXTERNAL } from "constants/backend"

const userSchemaOverrides = {
firstName: { displayName: "First name", disabled: true },
Expand All @@ -27,7 +28,7 @@

$: id = $tables.selected?._id
$: isUsersTable = id === TableNames.USERS
$: isInternal = $tables.selected?.type !== "external"
$: isInternal = $tables.selected?.sourceType !== DB_TYPE_EXTERNAL
$: gridDatasource = {
type: "table",
tableId: id,
Expand All @@ -46,10 +47,7 @@
tables.replaceTable(id, e.detail)

// We need to refresh datasources when an external table changes.
// Type "external" may exist - sometimes type is "table" and sometimes it
// is "external" - it has different meanings in different endpoints.
// If we check both these then we hopefully catch all external tables.
if (e.detail?.type === "external" || e.detail?.sql) {
if (e.detail?.sourceType === DB_TYPE_EXTERNAL) {
await datasources.fetch()
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
let hideAutocolumns = true
let data = []
let loading = false
let type = "internal"

$: name = view.name
$: schema = view.schema
Expand Down Expand Up @@ -66,7 +65,6 @@
tableId={view.tableId}
{data}
{loading}
{type}
rowCount={10}
allowEditing={false}
bind:hideAutocolumns
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
<ImportButton
{disabled}
tableId={$datasource?.tableId}
tableType={$definition?.type}
tableType={$definition?.sourceType}
on:importrows={rows.actions.refreshData}
/>
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
ALLOWABLE_NUMBER_TYPES,
SWITCHABLE_TYPES,
PrettyRelationshipDefinitions,
DB_TYPE_EXTERNAL,
} from "constants/backend"
import { getAutoColumnInformation, buildAutoColumn } from "builderStore/utils"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
Expand Down Expand Up @@ -254,10 +255,11 @@
!uneditable &&
editableColumn?.type !== AUTO_TYPE &&
!editableColumn.autocolumn
$: external = table.type === "external"
$: externalTable = table.sourceType === DB_TYPE_EXTERNAL
// in the case of internal tables the sourceId will just be undefined
$: tableOptions = $tables.list.filter(
opt => opt.type === table.type && table.sourceId === opt.sourceId
opt =>
opt.sourceType === table.sourceType && table.sourceId === opt.sourceId
)
$: typeEnabled =
!originalName ||
Expand Down Expand Up @@ -409,7 +411,7 @@
editableColumn.type === FieldType.BB_REFERENCE &&
editableColumn.subtype === FieldSubtype.USERS

if (!external) {
if (!externalTable) {
return [
FIELDS.STRING,
FIELDS.BARCODEQR,
Expand Down Expand Up @@ -441,7 +443,7 @@
isUsers ? FIELDS.USERS : FIELDS.USER,
]
// no-sql or a spreadsheet
if (!external || table.sql) {
if (!externalTable || table.sql) {
fields = [...fields, FIELDS.LINK, FIELDS.ARRAY]
}
return fields
Expand Down Expand Up @@ -486,7 +488,7 @@
})
}
const newError = {}
if (!external && fieldInfo.name?.startsWith("_")) {
if (!externalTable && fieldInfo.name?.startsWith("_")) {
newError.name = `Column name cannot start with an underscore.`
} else if (fieldInfo.name && !fieldInfo.name.match(ValidColumnNameRegex)) {
newError.name = `Illegal character; must be alpha-numeric.`
Expand All @@ -498,7 +500,7 @@
newError.name = `Column name already in use.`
}

if (fieldInfo.type == "auto" && !fieldInfo.subtype) {
if (fieldInfo.type === "auto" && !fieldInfo.subtype) {
newError.subtype = `Auto Column requires a type`
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script>
import { Select, Toggle, Multiselect } from "@budibase/bbui"
import { FIELDS } from "constants/backend"
import { DB_TYPE_INTERNAL, FIELDS } from "constants/backend"
import { API } from "api"
import { parseFile } from "./utils"

Expand Down Expand Up @@ -169,7 +169,7 @@
</div>
{/each}
</div>
{#if tableType === "internal"}
{#if tableType === DB_TYPE_INTERNAL}
<br />
<Toggle
bind:value={updateExistingRows}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import {
BUDIBASE_INTERNAL_DB_ID,
BUDIBASE_DATASOURCE_TYPE,
DB_TYPE_INTERNAL,
} from "constants/backend"

$: tableNames = $tables.list.map(table => table.name)
Expand Down Expand Up @@ -55,8 +56,9 @@
name,
schema: { ...schema },
rows,
type: "internal",
type: "table",
sourceId: targetDatasourceId,
sourceType: DB_TYPE_INTERNAL,
}

// Only set primary display if defined
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
notifications,
} from "@budibase/bbui"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { DB_TYPE_EXTERNAL } from "constants/backend"

export let table

Expand All @@ -27,8 +28,8 @@
let willBeDeleted
let deleteTableName

$: external = table?.type === "external"
$: allowDeletion = !external || table?.created
$: externalTable = table?.sourceType === DB_TYPE_EXTERNAL
$: allowDeletion = !externalTable || table?.created

function showDeleteModal() {
templateScreens = $store.screens.filter(
Expand All @@ -48,7 +49,7 @@
for (let screen of templateScreens) {
await store.actions.screens.delete(screen)
}
if (table.type === "external") {
if (table.sourceType === DB_TYPE_EXTERNAL) {
await datasources.fetch()
}
notifications.success("Table deleted")
Expand Down Expand Up @@ -91,7 +92,7 @@
<div slot="control" class="icon">
<Icon s hoverable name="MoreSmallList" />
</div>
{#if !external}
{#if !externalTable}
<MenuItem icon="Edit" on:click={editorModal.show}>Edit</MenuItem>
{/if}
<MenuItem icon="Delete" on:click={showDeleteModal}>Delete</MenuItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</script>

<div class="table">
<Table {schema} data={rowsCopy} type="external" allowEditing={false} />
<Table {schema} data={rowsCopy} allowEditing={false} />
</div>

<style>
Expand Down
Loading
Loading