From be433cd0fd6f2a73ea0fd602f8e794f80f6763dc Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Wed, 5 Jul 2023 21:09:16 -0700 Subject: [PATCH 1/3] update CH migration. --- db/clickhouse/migrations/01_edit_keys.sql | 9 +++++++-- db/clickhouse/migrations/02_add_upload_id.sql | 2 -- 2 files changed, 7 insertions(+), 4 deletions(-) delete mode 100644 db/clickhouse/migrations/02_add_upload_id.sql diff --git a/db/clickhouse/migrations/01_edit_keys.sql b/db/clickhouse/migrations/01_edit_keys.sql index b948ff38..952151ec 100644 --- a/db/clickhouse/migrations/01_edit_keys.sql +++ b/db/clickhouse/migrations/01_edit_keys.sql @@ -1,4 +1,9 @@ +-- edit event_data values ALTER TABLE "event_data" RENAME COLUMN "event_date_value" TO "date_value"; -ALTER TABLE "event_data" RENAME COLUMN "event_numeric_value" TO "numeric_value"; +ALTER TABLE "event_data" RENAME COLUMN "event_numeric_value" TO "number_value"; ALTER TABLE "event_data" RENAME COLUMN "event_string_value" TO "string_value"; -ALTER TABLE "event_data" RENAME COLUMN "event_data_type" TO "data_type"; \ No newline at end of file +ALTER TABLE "event_data" RENAME COLUMN "event_data_type" TO "data_type"; + +-- add job_id +ALTER TABLE "website_event" ADD COLUMN "job_id" UUID AFTER "created_at"; +ALTER TABLE "event_data" ADD COLUMN "job_id" UUID AFTER "created_at"; \ No newline at end of file diff --git a/db/clickhouse/migrations/02_add_upload_id.sql b/db/clickhouse/migrations/02_add_upload_id.sql deleted file mode 100644 index 44b5906e..00000000 --- a/db/clickhouse/migrations/02_add_upload_id.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE "website_event" ADD COLUMN "job_id" UUID AFTER "created_at"; -ALTER TABLE "event_data" ADD COLUMN "job_id" UUID AFTER "created_at"; \ No newline at end of file From 0a3ee2277a719a5f910009d73f42f7ab55c9f79f Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 6 Jul 2023 21:02:56 -0700 Subject: [PATCH 2/3] Fix numeric to number. --- db/clickhouse/schema.sql | 6 ++--- .../migrations/03_session_data/migration.sql | 10 ++++----- db/mysql/schema.prisma | 20 ++++++++--------- .../migrations/03_session_data/migration.sql | 4 ++-- db/postgresql/schema.prisma | 22 +++++++++---------- lib/clickhouse.ts | 8 +++---- lib/prisma.ts | 8 +++---- queries/analytics/eventData/saveEventData.ts | 2 +- 8 files changed, 40 insertions(+), 40 deletions(-) diff --git a/db/clickhouse/schema.sql b/db/clickhouse/schema.sql index 8ee02af8..a33db3c4 100644 --- a/db/clickhouse/schema.sql +++ b/db/clickhouse/schema.sql @@ -119,7 +119,7 @@ CREATE TABLE umami.event_data event_name String, event_key String, string_value Nullable(String), - numeric_value Nullable(Decimal64(4)), --922337203685477.5625 + number_value Nullable(Decimal64(4)), --922337203685477.5625 date_value Nullable(DateTime('UTC')), data_type UInt32, created_at DateTime('UTC'), @@ -137,7 +137,7 @@ CREATE TABLE umami.event_data_queue ( event_name String, event_key String, string_value Nullable(String), - numeric_value Nullable(Decimal64(4)), --922337203685477.5625 + number_value Nullable(Decimal64(4)), --922337203685477.5625 date_value Nullable(DateTime('UTC')), data_type UInt32, created_at DateTime('UTC'), @@ -161,7 +161,7 @@ SELECT website_id, event_name, event_key, string_value, - numeric_value, + number_value, date_value, data_type, created_at diff --git a/db/mysql/migrations/03_session_data/migration.sql b/db/mysql/migrations/03_session_data/migration.sql index 3618080d..161b455f 100644 --- a/db/mysql/migrations/03_session_data/migration.sql +++ b/db/mysql/migrations/03_session_data/migration.sql @@ -15,7 +15,7 @@ ALTER TABLE `event_data` RENAME COLUMN `event_data_type` TO `data_type`; ALTER TABLE `event_data` RENAME COLUMN `event_date_value` TO `date_value`; ALTER TABLE `event_data` RENAME COLUMN `event_id` TO `event_data_id`; -ALTER TABLE `event_data` RENAME COLUMN `event_numeric_value` TO `numeric_value`; +ALTER TABLE `event_data` RENAME COLUMN `event_numeric_value` TO `number_value`; ALTER TABLE `event_data` RENAME COLUMN `event_string_value` TO `string_value`; -- CreateTable @@ -24,10 +24,10 @@ CREATE TABLE `session_data` ( `website_id` VARCHAR(36) NOT NULL, `session_id` VARCHAR(36) NOT NULL, `event_key` VARCHAR(500) NOT NULL, - `event_string_value` VARCHAR(500) NULL, - `event_numeric_value` DECIMAL(19, 4) NULL, - `event_date_value` TIMESTAMP(0) NULL, - `event_data_type` INTEGER UNSIGNED NOT NULL, + `string_value` VARCHAR(500) NULL, + `number_value` DECIMAL(19, 4) NULL, + `date_value` TIMESTAMP(0) NULL, + `data_type` INTEGER UNSIGNED NOT NULL, `created_at` TIMESTAMP(0) NULL DEFAULT CURRENT_TIMESTAMP(0), INDEX `session_data_created_at_idx`(`created_at`), diff --git a/db/mysql/schema.prisma b/db/mysql/schema.prisma index 88d5ef80..98ee8ae0 100644 --- a/db/mysql/schema.prisma +++ b/db/mysql/schema.prisma @@ -101,7 +101,7 @@ model EventData { websiteId String @map("website_id") @db.VarChar(36) eventKey String @map("event_key") @db.VarChar(500) stringValue String? @map("string_value") @db.VarChar(500) - numericValue Decimal? @map("numeric_value") @db.Decimal(19, 4) + numberValue Decimal? @map("number_value") @db.Decimal(19, 4) dateValue DateTime? @map("date_value") @db.Timestamp(0) dataType Int @map("data_type") @db.UnsignedInt createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0) @@ -117,15 +117,15 @@ model EventData { } model SessionData { - id String @id() @map("session_data_id") @db.VarChar(36) - websiteId String @map("website_id") @db.VarChar(36) - sessionId String @map("session_id") @db.VarChar(36) - eventKey String @map("event_key") @db.VarChar(500) - eventStringValue String? @map("event_string_value") @db.VarChar(500) - eventNumericValue Decimal? @map("event_numeric_value") @db.Decimal(19, 4) - eventDateValue DateTime? @map("event_date_value") @db.Timestamp(0) - eventDataType Int @map("event_data_type") @db.UnsignedInt - createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0) + id String @id() @map("session_data_id") @db.VarChar(36) + websiteId String @map("website_id") @db.VarChar(36) + sessionId String @map("session_id") @db.VarChar(36) + eventKey String @map("event_key") @db.VarChar(500) + stringValue String? @map("string_value") @db.VarChar(500) + numberValue Decimal? @map("number_value") @db.Decimal(19, 4) + dateValue DateTime? @map("date_value") @db.Timestamp(0) + dataType Int @map("data_type") @db.UnsignedInt + createdAt DateTime? @default(now()) @map("created_at") @db.Timestamp(0) website Website @relation(fields: [websiteId], references: [id]) session Session @relation(fields: [sessionId], references: [id]) diff --git a/db/postgresql/migrations/03_session_data/migration.sql b/db/postgresql/migrations/03_session_data/migration.sql index 233c3793..0a93d39c 100644 --- a/db/postgresql/migrations/03_session_data/migration.sql +++ b/db/postgresql/migrations/03_session_data/migration.sql @@ -2,7 +2,7 @@ ALTER TABLE "event_data" RENAME COLUMN "event_data_type" TO "data_type"; ALTER TABLE "event_data" RENAME COLUMN "event_date_value" TO "date_value"; ALTER TABLE "event_data" RENAME COLUMN "event_id" TO "event_data_id"; -ALTER TABLE "event_data" RENAME COLUMN "event_numeric_value" TO "numeric_value"; +ALTER TABLE "event_data" RENAME COLUMN "event_numeric_value" TO "number_value"; ALTER TABLE "event_data" RENAME COLUMN "event_string_value" TO "string_value"; -- CreateTable @@ -12,7 +12,7 @@ CREATE TABLE "session_data" ( "session_id" UUID NOT NULL, "session_key" VARCHAR(500) NOT NULL, "string_value" VARCHAR(500), - "numeric_value" DECIMAL(19,4), + "number_value" DECIMAL(19,4), "date_value" TIMESTAMPTZ(6), "data_type" INTEGER NOT NULL, "created_at" TIMESTAMPTZ(6) DEFAULT CURRENT_TIMESTAMP, diff --git a/db/postgresql/schema.prisma b/db/postgresql/schema.prisma index bfd71fd1..5753c6ef 100644 --- a/db/postgresql/schema.prisma +++ b/db/postgresql/schema.prisma @@ -101,7 +101,7 @@ model EventData { websiteEventId String @map("website_event_id") @db.Uuid eventKey String @map("event_key") @db.VarChar(500) stringValue String? @map("string_value") @db.VarChar(500) - numericValue Decimal? @map("numeric_value") @db.Decimal(19, 4) + numberValue Decimal? @map("number_value") @db.Decimal(19, 4) dateValue DateTime? @map("date_value") @db.Timestamptz(6) dataType Int @map("data_type") @db.Integer createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) @@ -116,16 +116,16 @@ model EventData { } model SessionData { - id String @id() @map("session_data_id") @db.Uuid - websiteId String @map("website_id") @db.Uuid - sessionId String @map("session_id") @db.Uuid - sessionKey String @map("session_key") @db.VarChar(500) - stringValue String? @map("string_value") @db.VarChar(500) - numericValue Decimal? @map("numeric_value") @db.Decimal(19, 4) - dateValue DateTime? @map("date_value") @db.Timestamptz(6) - dataType Int @map("data_type") @db.Integer - createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) - deletedAt DateTime? @default(now()) @map("deleted_at") @db.Timestamptz(6) + id String @id() @map("session_data_id") @db.Uuid + websiteId String @map("website_id") @db.Uuid + sessionId String @map("session_id") @db.Uuid + sessionKey String @map("session_key") @db.VarChar(500) + stringValue String? @map("string_value") @db.VarChar(500) + numberValue Decimal? @map("number_value") @db.Decimal(19, 4) + dateValue DateTime? @map("date_value") @db.Timestamptz(6) + dataType Int @map("data_type") @db.Integer + createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6) + deletedAt DateTime? @default(now()) @map("deleted_at") @db.Timestamptz(6) website Website @relation(fields: [websiteId], references: [id]) session Session @relation(fields: [sessionId], references: [id]) diff --git a/lib/clickhouse.ts b/lib/clickhouse.ts index c91cf3da..eb73d83c 100644 --- a/lib/clickhouse.ts +++ b/lib/clickhouse.ts @@ -82,17 +82,17 @@ function getEventDataFilterQuery( switch (type) { case 'number': - ac.push(`and event_numeric_value = {eventValue${i}:UInt64})`); + ac.push(`and number_value = {eventValue${i}:UInt64})`); break; case 'string': - ac.push(`and event_string_value = {eventValue${i}:String})`); + ac.push(`and string_value = {eventValue${i}:String})`); break; case 'boolean': - ac.push(`and event_string_value = {eventValue${i}:String})`); + ac.push(`and string_value = {eventValue${i}:String})`); value = cv ? 'true' : 'false'; break; case 'date': - ac.push(`and event_date_value = {eventValue${i}:DateTime('UTC')})`); + ac.push(`and date_value = {eventValue${i}:DateTime('UTC')})`); break; } diff --git a/lib/prisma.ts b/lib/prisma.ts index 910c1c71..875f5897 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -94,20 +94,20 @@ function getEventDataFilterQuery( switch (type) { case 'number': - ac.push(`and event_numeric_value = $${params.length + 1})`); + ac.push(`and number_value = $${params.length + 1})`); params.push(value); break; case 'string': - ac.push(`and event_string_value = $${params.length + 1})`); + ac.push(`and string_value = $${params.length + 1})`); params.push(decodeURIComponent(cv.eventValue as string)); break; case 'boolean': - ac.push(`and event_string_value = $${params.length + 1})`); + ac.push(`and string_value = $${params.length + 1})`); params.push(decodeURIComponent(cv.eventValue as string)); value = cv ? 'true' : 'false'; break; case 'date': - ac.push(`and event_date_value = $${params.length + 1})`); + ac.push(`and date_value = $${params.length + 1})`); params.push(cv.eventValue); break; } diff --git a/queries/analytics/eventData/saveEventData.ts b/queries/analytics/eventData/saveEventData.ts index e9f8d21e..0ccc9421 100644 --- a/queries/analytics/eventData/saveEventData.ts +++ b/queries/analytics/eventData/saveEventData.ts @@ -81,7 +81,7 @@ async function clickhouseQuery(data: { a.dynamicDataType === DATA_TYPE.array ? a.value : null, - numeric_value: a.dynamicDataType === DATA_TYPE.number ? a.value : null, + number_value: a.dynamicDataType === DATA_TYPE.number ? a.value : null, date_value: a.dynamicDataType === DATA_TYPE.date ? getDateFormat(a.value) : null, data_type: a.dynamicDataType, created_at: createdAt, From 9ec27012289c4eddd9921890357e07f5ea388d79 Mon Sep 17 00:00:00 2001 From: Brian Cao Date: Thu, 6 Jul 2023 23:02:16 -0700 Subject: [PATCH 3/3] Add view-only user. --- components/messages.js | 1 + .../pages/settings/profile/ProfileDetails.js | 19 ++++++++++-- components/pages/settings/teams/TeamsList.js | 29 ++++++++++++------- .../pages/settings/users/UserAddForm.js | 4 +++ .../pages/settings/users/UserEditForm.js | 4 +++ .../pages/settings/websites/WebsitesList.js | 27 ++++++++++------- lib/constants.ts | 2 ++ 7 files changed, 61 insertions(+), 25 deletions(-) diff --git a/components/messages.js b/components/messages.js index e183281b..7ddbdd2d 100644 --- a/components/messages.js +++ b/components/messages.js @@ -15,6 +15,7 @@ export const labels = defineMessages({ password: { id: 'label.password', defaultMessage: 'Password' }, role: { id: 'label.role', defaultMessage: 'Role' }, user: { id: 'label.user', defaultMessage: 'User' }, + viewOnly: { id: 'label.view-only', defaultMessage: 'View only' }, admin: { id: 'label.admin', defaultMessage: 'Administrator' }, confirm: { id: 'label.confirm', defaultMessage: 'Confirm' }, details: { id: 'label.details', defaultMessage: 'Details' }, diff --git a/components/pages/settings/profile/ProfileDetails.js b/components/pages/settings/profile/ProfileDetails.js index d8fdf26e..d1690220 100644 --- a/components/pages/settings/profile/ProfileDetails.js +++ b/components/pages/settings/profile/ProfileDetails.js @@ -7,6 +7,7 @@ import PasswordChangeButton from './PasswordChangeButton'; import useUser from 'hooks/useUser'; import useMessages from 'hooks/useMessages'; import useConfig from 'hooks/useConfig'; +import { ROLES } from 'lib/constants'; export function ProfileDetails() { const { user } = useUser(); @@ -19,12 +20,24 @@ export function ProfileDetails() { const { username, role } = user; + const renderRole = value => { + if (value === ROLES.user) { + return formatMessage(labels.user); + } + if (value === ROLES.admin) { + return formatMessage(labels.admin); + } + if (value === ROLES.viewOnly) { + return formatMessage(labels.viewOnly); + } + + return formatMessage(labels.unknown); + }; + return (
{username} - - {formatMessage(labels[role] || labels.unknown)} - + {renderRole(role)} {!cloudMode && ( diff --git a/components/pages/settings/teams/TeamsList.js b/components/pages/settings/teams/TeamsList.js index 783696b1..0c82639b 100644 --- a/components/pages/settings/teams/TeamsList.js +++ b/components/pages/settings/teams/TeamsList.js @@ -9,8 +9,11 @@ import Icons from 'components/icons'; import TeamJoinForm from './TeamJoinForm'; import useApi from 'hooks/useApi'; import useMessages from 'hooks/useMessages'; +import { ROLES } from 'lib/constants'; +import useUser from 'hooks/useUser'; export default function TeamsList() { + const { user } = useUser(); const { formatMessage, labels, messages } = useMessages(); const [update, setUpdate] = useState(0); const { get, useQuery } = useApi(); @@ -48,17 +51,21 @@ export default function TeamsList() { ); const createButton = ( - - - - {close => } - - + <> + {user.role !== ROLES.viewOnly && ( + + + + {close => } + + + )} + ); return ( diff --git a/components/pages/settings/users/UserAddForm.js b/components/pages/settings/users/UserAddForm.js index 63b247a1..bb408749 100644 --- a/components/pages/settings/users/UserAddForm.js +++ b/components/pages/settings/users/UserAddForm.js @@ -35,6 +35,9 @@ export function UserAddForm({ onSave, onClose }) { if (value === ROLES.admin) { return formatMessage(labels.admin); } + if (value === ROLES.viewOnly) { + return formatMessage(labels.viewOnly); + } }; return ( @@ -52,6 +55,7 @@ export function UserAddForm({ onSave, onClose }) { + {formatMessage(labels.viewOnly)} {formatMessage(labels.user)} {formatMessage(labels.admin)} diff --git a/components/pages/settings/users/UserEditForm.js b/components/pages/settings/users/UserEditForm.js index d5e671e0..887531e8 100644 --- a/components/pages/settings/users/UserEditForm.js +++ b/components/pages/settings/users/UserEditForm.js @@ -35,6 +35,9 @@ export function UserEditForm({ userId, data, onSave }) { if (value === ROLES.admin) { return formatMessage(labels.admin); } + if (value === ROLES.viewOnly) { + return formatMessage(labels.viewOnly); + } }; return ( @@ -57,6 +60,7 @@ export function UserEditForm({ userId, data, onSave }) { + {formatMessage(labels.viewOnly)} {formatMessage(labels.user)} {formatMessage(labels.admin)} diff --git a/components/pages/settings/websites/WebsitesList.js b/components/pages/settings/websites/WebsitesList.js index 23abd897..de423d0b 100644 --- a/components/pages/settings/websites/WebsitesList.js +++ b/components/pages/settings/websites/WebsitesList.js @@ -7,6 +7,7 @@ import WebsitesTable from 'components/pages/settings/websites/WebsitesTable'; import useApi from 'hooks/useApi'; import useUser from 'hooks/useUser'; import useMessages from 'hooks/useMessages'; +import { ROLES } from 'lib/constants'; export function WebsitesList() { const { formatMessage, labels, messages } = useMessages(); @@ -26,17 +27,21 @@ export function WebsitesList() { }; const addButton = ( - - - - {close => } - - + <> + {user.role !== ROLES.viewOnly && ( + + + + {close => } + + + )} + ); return ( diff --git a/lib/constants.ts b/lib/constants.ts index 8917f735..5772e147 100644 --- a/lib/constants.ts +++ b/lib/constants.ts @@ -92,6 +92,7 @@ export const KAFKA_TOPIC = { export const ROLES = { admin: 'admin', user: 'user', + viewOnly: 'view-only', teamOwner: 'team-owner', teamMember: 'team-member', } as const; @@ -114,6 +115,7 @@ export const ROLE_PERMISSIONS = { PERMISSIONS.websiteDelete, PERMISSIONS.teamCreate, ], + [ROLES.viewOnly]: [], [ROLES.teamOwner]: [PERMISSIONS.teamUpdate, PERMISSIONS.teamDelete], [ROLES.teamMember]: [], } as const;