Fix empty user id clickhouse (#18238)
- Fixes: - Make Workspace User select work; previously, it didn't work as we were not fetching the workspace users correctly - Send Object Events with valid record id and object id ## Audit logs demo https://github.com/user-attachments/assets/92437037-d253-4810-a138-7c709550755d
This commit is contained in:
committed by
GitHub
parent
86fbf69e95
commit
cfad24da48
@@ -4,6 +4,7 @@ import {
|
||||
AuditException,
|
||||
AuditExceptionCode,
|
||||
} from 'src/engine/core-modules/audit/audit.exception';
|
||||
import { type UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { type WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
|
||||
import { AuditResolver } from './audit.resolver';
|
||||
@@ -55,12 +56,12 @@ describe('AuditResolver', () => {
|
||||
const result = await resolver.trackAnalytics(
|
||||
input,
|
||||
{ id: 'workspace-1' } as WorkspaceEntity,
|
||||
'user-workspace-1',
|
||||
{ id: 'user-1' } as UserEntity,
|
||||
);
|
||||
|
||||
expect(auditService.createContext).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-1',
|
||||
userWorkspaceId: 'user-workspace-1',
|
||||
userId: 'user-1',
|
||||
});
|
||||
expect(mockInsertPageviewEvent).toHaveBeenCalledWith('Test Page', {});
|
||||
expect(result).toBe('Pageview created');
|
||||
@@ -85,12 +86,12 @@ describe('AuditResolver', () => {
|
||||
const result = await resolver.trackAnalytics(
|
||||
input,
|
||||
{ id: 'workspace-2' } as WorkspaceEntity,
|
||||
'user-workspace-2',
|
||||
{ id: 'user-2' } as UserEntity,
|
||||
);
|
||||
|
||||
expect(auditService.createContext).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-2',
|
||||
userWorkspaceId: 'user-workspace-2',
|
||||
userId: 'user-2',
|
||||
});
|
||||
expect(mockInsertWorkspaceEvent).toHaveBeenCalledWith(
|
||||
'Custom Domain Activated',
|
||||
@@ -120,12 +121,12 @@ describe('AuditResolver', () => {
|
||||
const result = await resolver.createObjectEvent(
|
||||
input,
|
||||
{ id: 'workspace-3' } as WorkspaceEntity,
|
||||
'user-workspace-3',
|
||||
{ id: 'user-3' } as UserEntity,
|
||||
);
|
||||
|
||||
expect(auditService.createContext).toHaveBeenCalledWith({
|
||||
workspaceId: 'workspace-3',
|
||||
userWorkspaceId: 'user-workspace-3',
|
||||
userId: 'user-3',
|
||||
});
|
||||
|
||||
expect(mockInsertObjectEvent).toHaveBeenCalledWith(
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { UseFilters, UseGuards, UsePipes } from '@nestjs/common';
|
||||
import { Args, Mutation } from '@nestjs/graphql';
|
||||
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { AuditExceptionFilter } from 'src/engine/core-modules/audit/audit-exception-filter';
|
||||
import {
|
||||
AuditException,
|
||||
@@ -9,10 +10,10 @@ import {
|
||||
import { CreateObjectEventInput } from 'src/engine/core-modules/audit/dtos/create-object-event.input';
|
||||
import { PreventNestToAutoLogGraphqlErrorsFilter } from 'src/engine/core-modules/graphql/filters/prevent-nest-to-auto-log-graphql-errors.filter';
|
||||
import { ResolverValidationPipe } from 'src/engine/core-modules/graphql/pipes/resolver-validation.pipe';
|
||||
import { UserEntity } from 'src/engine/core-modules/user/user.entity';
|
||||
import { WorkspaceEntity } from 'src/engine/core-modules/workspace/workspace.entity';
|
||||
import { AuthUserWorkspaceId } from 'src/engine/decorators/auth/auth-user-workspace-id.decorator';
|
||||
import { AuthUser } from 'src/engine/decorators/auth/auth-user.decorator';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { MetadataResolver } from 'src/engine/api/graphql/graphql-config/decorators/metadata-resolver.decorator';
|
||||
import { NoPermissionGuard } from 'src/engine/guards/no-permission.guard';
|
||||
import { PublicEndpointGuard } from 'src/engine/guards/public-endpoint.guard';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
@@ -37,13 +38,9 @@ export class AuditResolver {
|
||||
createAnalyticsInput: CreateAnalyticsInputV2,
|
||||
@AuthWorkspace({ allowUndefined: true })
|
||||
workspace: WorkspaceEntity | undefined,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
|
||||
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
|
||||
) {
|
||||
return this.trackAnalytics(
|
||||
createAnalyticsInput,
|
||||
workspace,
|
||||
userWorkspaceId,
|
||||
);
|
||||
return this.trackAnalytics(createAnalyticsInput, workspace, user);
|
||||
}
|
||||
|
||||
@Mutation(() => Analytics)
|
||||
@@ -52,7 +49,7 @@ export class AuditResolver {
|
||||
@Args()
|
||||
createObjectEventInput: CreateObjectEventInput,
|
||||
@AuthWorkspace() workspace: WorkspaceEntity | undefined,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
|
||||
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
|
||||
) {
|
||||
if (!workspace) {
|
||||
throw new AuditException(
|
||||
@@ -63,7 +60,7 @@ export class AuditResolver {
|
||||
|
||||
const analyticsContext = this.auditService.createContext({
|
||||
workspaceId: workspace.id,
|
||||
userWorkspaceId,
|
||||
userId: user?.id,
|
||||
});
|
||||
|
||||
return analyticsContext.createObjectEvent(createObjectEventInput.event, {
|
||||
@@ -81,11 +78,11 @@ export class AuditResolver {
|
||||
createAnalyticsInput: CreateAnalyticsInputV2,
|
||||
@AuthWorkspace({ allowUndefined: true })
|
||||
workspace: WorkspaceEntity | undefined,
|
||||
@AuthUserWorkspaceId() userWorkspaceId: string | undefined,
|
||||
@AuthUser({ allowUndefined: true }) user: UserEntity | undefined,
|
||||
) {
|
||||
const analyticsContext = this.auditService.createContext({
|
||||
workspaceId: workspace?.id,
|
||||
userWorkspaceId,
|
||||
userId: user?.id,
|
||||
});
|
||||
|
||||
if (isPageviewAnalyticsInput(createAnalyticsInput)) {
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ export class CreateAuditLogFromInternalEvent {
|
||||
|
||||
const auditService = this.auditService.createContext({
|
||||
workspaceId: workspaceEventBatch.workspaceId,
|
||||
userWorkspaceId: eventData.userWorkspaceId,
|
||||
userId: eventData.userId,
|
||||
});
|
||||
|
||||
// Since these are object record events, we use createObjectEvent
|
||||
|
||||
@@ -25,14 +25,12 @@ export class AuditService {
|
||||
|
||||
createContext(context?: {
|
||||
workspaceId?: string | null | undefined;
|
||||
userWorkspaceId?: string | null | undefined;
|
||||
userId?: string | null | undefined;
|
||||
}) {
|
||||
const contextFields = context
|
||||
? {
|
||||
...(context.workspaceId ? { workspaceId: context.workspaceId } : {}),
|
||||
...(context.userWorkspaceId
|
||||
? { userWorkspaceId: context.userWorkspaceId }
|
||||
: {}),
|
||||
...(context.userId ? { userId: context.userId } : {}),
|
||||
}
|
||||
: {};
|
||||
|
||||
@@ -51,13 +49,27 @@ export class AuditService {
|
||||
properties: TrackEventProperties<T> & {
|
||||
recordId: string;
|
||||
objectMetadataId: string;
|
||||
isCustom?: boolean;
|
||||
},
|
||||
) =>
|
||||
this.preventIfDisabled(() =>
|
||||
) => {
|
||||
const { recordId, objectMetadataId, isCustom, ...restProperties } =
|
||||
properties;
|
||||
|
||||
return this.preventIfDisabled(() =>
|
||||
this.clickHouseService.insert('objectEvent', [
|
||||
{ ...contextFields, ...makeTrackEvent(event, properties) },
|
||||
{
|
||||
...contextFields,
|
||||
...makeTrackEvent(
|
||||
event,
|
||||
restProperties as unknown as TrackEventProperties<T>,
|
||||
),
|
||||
recordId,
|
||||
objectMetadataId,
|
||||
isCustom,
|
||||
},
|
||||
]),
|
||||
),
|
||||
);
|
||||
},
|
||||
createPageviewEvent: (
|
||||
name: string,
|
||||
properties: Partial<PageviewProperties>,
|
||||
|
||||
+1
-1
@@ -15,7 +15,7 @@ export type GenericTrackEvent<E extends string = string> = {
|
||||
properties: any;
|
||||
timestamp: string;
|
||||
version: string;
|
||||
userWorkspaceId?: string;
|
||||
userId?: string;
|
||||
workspaceId?: string;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user