diff --git a/lerna.json b/lerna.json index 066df19dac..8b1fa18d23 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.28.1", + "version": "2.28.3", "npmClient": "yarn", "packages": [ "packages/*", diff --git a/package.json b/package.json index 08176fae90..5377dfc5a1 100644 --- a/package.json +++ b/package.json @@ -37,8 +37,8 @@ "build": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream", "build:apps": "yarn build --scope @budibase/server --scope @budibase/worker", "build:cli": "yarn build --scope @budibase/cli", - "build:oss": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --ignore @budibase/account-portal --ignore @budibase/account-portal-server --ignore @budibase/account-portal-ui", - "build:account-portal": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --scope @budibase/account-portal --scope @budibase/account-portal-server --scope @budibase/account-portal-ui", + "build:oss": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --ignore @budibase/account-portal-server --ignore @budibase/account-portal-ui", + "build:account-portal": "NODE_OPTIONS=--max-old-space-size=1500 lerna run build --stream --scope @budibase/account-portal-server --scope @budibase/account-portal-ui", "build:dev": "lerna run --stream prebuild && yarn nx run-many --target=build --output-style=dynamic --watch --preserveWatchOutput", "check:types": "lerna run --concurrency 2 check:types", "build:sdk": "lerna run --stream build:sdk", diff --git a/packages/builder/src/dataBinding.js b/packages/builder/src/dataBinding.js index 64257e7a7b..6defe94108 100644 --- a/packages/builder/src/dataBinding.js +++ b/packages/builder/src/dataBinding.js @@ -30,6 +30,7 @@ import ActionDefinitions from "components/design/settings/controls/ButtonActionE import { environment, licensing } from "stores/portal" import { convertOldFieldFormat } from "components/design/settings/controls/FieldConfiguration/utils" import { FIELDS } from "constants/backend" +import { FieldType } from "@budibase/types" const { ContextScopes } = Constants @@ -555,6 +556,9 @@ const getComponentBindingCategory = (component, context, def) => { export const getUserBindings = () => { let bindings = [] const { schema } = getSchemaForDatasourcePlus(TableNames.USERS) + // add props that are not in the user metadata table schema + // but will be there for logged-in user + schema["globalId"] = { type: FieldType.STRING } const keys = Object.keys(schema).sort() const safeUser = makePropSafe("user") diff --git a/packages/client/src/components/app/blocks/FormBlockComponent.svelte b/packages/client/src/components/app/blocks/FormBlockComponent.svelte index 396dfcf808..f931319118 100644 --- a/packages/client/src/components/app/blocks/FormBlockComponent.svelte +++ b/packages/client/src/components/app/blocks/FormBlockComponent.svelte @@ -68,6 +68,15 @@ maximum: schema?.constraints?.length?.maximum, } }, + [FieldType.DATETIME]: (_field, schema) => { + const props = { + valueAsTimestamp: !schema?.timeOnly, + } + if (schema?.dateOnly) { + props.enableTime = false + } + return props + }, } const fieldSchema = getFieldSchema(field) diff --git a/packages/client/src/components/app/forms/DateTimeField.svelte b/packages/client/src/components/app/forms/DateTimeField.svelte index 499f0443cb..7b6ed734fe 100644 --- a/packages/client/src/components/app/forms/DateTimeField.svelte +++ b/packages/client/src/components/app/forms/DateTimeField.svelte @@ -16,15 +16,37 @@ export let onChange export let span export let helpText = null + export let valueAsTimestamp = false let fieldState let fieldApi const handleChange = e => { - const changed = fieldApi.setValue(e.detail) - if (onChange && changed) { - onChange({ value: e.detail }) + let value = e.detail + if (timeOnly && valueAsTimestamp) { + if (!isValidDate(value)) { + // Handle time only fields that are timestamps under the hood + value = timeToDateISOString(value) + } } + + const changed = fieldApi.setValue(value) + if (onChange && changed) { + onChange({ value }) + } + } + + const isValidDate = value => !isNaN(new Date(value)) + + const timeToDateISOString = value => { + let [hours, minutes] = value.split(":").map(Number) + + const date = new Date() + date.setHours(hours) + date.setMinutes(minutes) + date.setSeconds(0) + date.setMilliseconds(0) + return date.toISOString() } diff --git a/packages/server/src/api/controllers/auth.ts b/packages/server/src/api/controllers/auth.ts index 9b1b78ed9e..4ff592534d 100644 --- a/packages/server/src/api/controllers/auth.ts +++ b/packages/server/src/api/controllers/auth.ts @@ -1,7 +1,7 @@ import { outputProcessing } from "../../utilities/rowProcessor" import { InternalTables } from "../../db/utils" import { getFullUser } from "../../utilities/users" -import { roles, context } from "@budibase/backend-core" +import { roles, context, db as dbCore } from "@budibase/backend-core" import { ContextUser, Row, UserCtx } from "@budibase/types" import sdk from "../../sdk" import { processUser } from "../../utilities/global" @@ -27,6 +27,8 @@ export async function fetchSelf(ctx: UserCtx) { const appId = context.getAppId() let user: ContextUser = await getFullUser(userId) + // add globalId of user + user.globalId = dbCore.getGlobalIDFromUserMetadataID(userId) // this shouldn't be returned by the app self delete user.roles // forward the csrf token from the session diff --git a/packages/server/src/api/routes/tests/auth.spec.js b/packages/server/src/api/routes/tests/auth.spec.js index 5fbead99b7..64952db17c 100644 --- a/packages/server/src/api/routes/tests/auth.spec.js +++ b/packages/server/src/api/routes/tests/auth.spec.js @@ -1,5 +1,8 @@ const setup = require("./utilities") -const { generateUserMetadataID } = require("../../../db/utils") +const { + generateUserMetadataID, + getGlobalIDFromUserMetadataID, +} = require("../../../db/utils") describe("/authenticate", () => { let request = setup.getRequest() @@ -20,5 +23,16 @@ describe("/authenticate", () => { .expect(200) expect(res.body._id).toEqual(generateUserMetadataID(config.user._id)) }) + + it("should container the global user ID", async () => { + const res = await request + .get(`/api/self`) + .set(config.defaultHeaders()) + .expect("Content-Type", /json/) + .expect(200) + expect(res.body.globalId).toEqual( + getGlobalIDFromUserMetadataID(config.user._id) + ) + }) }) })