@tachybase/plugin-audit-logs 1.6.24 → 1.6.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/collections.d.ts +30 -0
- package/dist/client/index.js +1 -1
- package/dist/externalVersion.js +1 -1
- package/dist/locale/en-US.json +6 -0
- package/dist/locale/zh-CN.json +6 -0
- package/dist/server/collections/auditLogs.js +28 -0
- package/dist/server/constants.d.ts +6 -0
- package/dist/server/constants.js +18 -0
- package/dist/server/hooks/after-create.d.ts +3 -0
- package/dist/server/hooks/after-create.js +8 -3
- package/dist/server/hooks/after-destroy.d.ts +3 -0
- package/dist/server/hooks/after-destroy.js +8 -3
- package/dist/server/hooks/after-update.d.ts +3 -0
- package/dist/server/hooks/after-update.js +10 -5
- package/dist/server/hooks/audit-context.d.ts +11 -0
- package/dist/server/hooks/audit-context.js +39 -0
- package/dist/server/index.js +40 -4
- package/dist/server/migrations/20260617203100-add-tenant-fields.d.ts +6 -0
- package/dist/server/migrations/20260617203100-add-tenant-fields.js +112 -0
- package/dist/server/migrations/20260629120000-add-security-event-details.d.ts +6 -0
- package/dist/server/migrations/20260629120000-add-security-event-details.js +53 -0
- package/dist/server/normalize-audit-log-values.d.ts +8 -0
- package/dist/server/normalize-audit-log-values.js +37 -0
- package/dist/server/security-event-listener.d.ts +30 -0
- package/dist/server/security-event-listener.js +103 -0
- package/package.json +2 -2
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the use audit logs collection collection schema for the client.
|
|
3
|
+
*/
|
|
1
4
|
export declare const useAuditLogsCollection: () => {
|
|
2
5
|
name: string;
|
|
3
6
|
title: string;
|
|
@@ -150,8 +153,32 @@ export declare const useAuditLogsCollection: () => {
|
|
|
150
153
|
enum?: undefined;
|
|
151
154
|
};
|
|
152
155
|
sourceKey?: undefined;
|
|
156
|
+
} | {
|
|
157
|
+
name: string;
|
|
158
|
+
type: string;
|
|
159
|
+
interface: string;
|
|
160
|
+
uiSchema: {
|
|
161
|
+
type: string;
|
|
162
|
+
title: string;
|
|
163
|
+
'x-component': string;
|
|
164
|
+
'x-component-props': {
|
|
165
|
+
ellipsis: boolean;
|
|
166
|
+
showTime?: undefined;
|
|
167
|
+
fieldNames?: undefined;
|
|
168
|
+
};
|
|
169
|
+
'x-read-pretty': boolean;
|
|
170
|
+
enum?: undefined;
|
|
171
|
+
};
|
|
172
|
+
collectionName?: undefined;
|
|
173
|
+
target?: undefined;
|
|
174
|
+
targetKey?: undefined;
|
|
175
|
+
sourceKey?: undefined;
|
|
176
|
+
foreignKey?: undefined;
|
|
153
177
|
})[];
|
|
154
178
|
};
|
|
179
|
+
/**
|
|
180
|
+
* Builds the use audit changes collection collection schema for the client.
|
|
181
|
+
*/
|
|
155
182
|
export declare const useAuditChangesCollection: () => {
|
|
156
183
|
name: string;
|
|
157
184
|
title: string;
|
|
@@ -165,6 +192,9 @@ export declare const useAuditChangesCollection: () => {
|
|
|
165
192
|
};
|
|
166
193
|
}[];
|
|
167
194
|
};
|
|
195
|
+
/**
|
|
196
|
+
* Builds the use collections collection collection schema for the client.
|
|
197
|
+
*/
|
|
168
198
|
export declare const useCollectionsCollection: () => {
|
|
169
199
|
name: string;
|
|
170
200
|
title: string;
|
package/dist/client/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(l,e){typeof exports=="object"&&typeof module!="undefined"?e(exports,require("@tachybase/client"),require("react/jsx-runtime"),require("@ant-design/icons"),require("react-i18next"),require("@tachybase/schema"),require("@tego/client"),require("react")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","react/jsx-runtime","@ant-design/icons","react-i18next","@tachybase/schema","@tego/client","react"],e):(l=typeof globalThis!="undefined"?globalThis:l||self,e(l["@tachybase/plugin-audit-logs"]={},l["@tachybase/client"],l.jsxRuntime,l["@ant-design/icons"],l["react-i18next"],l["@tachybase/schema"],l["@tego/client"],l.react))})(this,function(l,e,i,d,I,p,b,h){"use strict";var re=Object.defineProperty,ne=Object.defineProperties;var ae=Object.getOwnPropertyDescriptors;var T=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var B=(l,e,i)=>e in l?re(l,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):l[e]=i,m=(l,e)=>{for(var i in e||(e={}))D.call(e,i)&&B(l,i,e[i]);if(T)for(var i of T(e))N.call(e,i)&&B(l,i,e[i]);return l},x=(l,e)=>ne(l,ae(e));var j=(l,e)=>{var i={};for(var d in l)D.call(l,d)&&e.indexOf(d)<0&&(i[d]=l[d]);if(l!=null&&T)for(var d of T(l))e.indexOf(d)<0&&N.call(l,d)&&(i[d]=l[d]);return i};var q=(l,e,i)=>new Promise((d,I)=>{var p=y=>{try{h(i.next(y))}catch(g){I(g)}},b=y=>{try{h(i.throw(y))}catch(g){I(g)}},h=y=>y.done?d(y.value):Promise.resolve(y.value).then(p,b);h((i=i.apply(l,e)).next())});const y="@tachybase/plugin-audit-logs";function g(){return I.useTranslation(y)}const t=o=>e.tval(o,{ns:y}),w=()=>{const{insert:o}=e.useSchemaInitializer(),{t:r}=g(),a=e.useSchemaInitializerItem(),n=e.createTableBlockSchema({collection:"auditLogs",rowKey:"id",tableActionInitializers:"auditLogsTable:configureActions",tableColumnInitializers:"auditLogsTable:configureColumns",tableActionColumnInitializers:"auditLogsTable:configureItemActions",tableBlockProvider:"AuditLogsBlockProvider",disableTemplate:!0});return i.jsx(e.SchemaInitializerItem,m({icon:i.jsx(d.TableOutlined,{}),onClick:()=>{o(n)},title:r("Audit Logs")},a))},E=()=>({name:"auditLogs",title:t("Audit logs"),fields:[{name:"createdAt",type:"date",interface:"createdAt",uiSchema:{type:"datetime",title:t("Created at"),"x-component":"DatePicker","x-component-props":{showTime:!0,ellipsis:!0},"x-read-pretty":!0}},{name:"type",type:"string",interface:"select",uiSchema:{type:"string",title:t("Action type"),"x-component":"Select","x-component-props":{ellipsis:!0},"x-read-pretty":!0,enum:[{label:t("Create record"),value:"create",color:"lime"},{label:t("Update record"),value:"update",color:"gold"},{label:t("Delete record"),value:"destroy",color:"magenta"}]}},{name:"recordId",type:"string",interface:"input",uiSchema:{title:t("Record ID"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}},{collectionName:"auditLogs",name:"collection",type:"belongsTo",interface:"m2o",target:"collections",targetKey:"name",sourceKey:"id",foreignKey:"collectionName",uiSchema:{type:"object",title:t("Collection"),"x-component":"AssociationField","x-component-props":{fieldNames:{value:"name",label:"title"},ellipsis:!0},"x-read-pretty":!0}},{name:"collectionName",type:"string",interface:"string",uiSchema:{type:"string",title:t("Collection name"),"x-component":"Input"}},{name:"user",collectionName:"auditLogs",type:"belongsTo",interface:"createdBy",targetKey:"id",foreignKey:"createdById",target:"users",uiSchema:{type:"object",title:t("User"),"x-component":"AssociationField","x-component-props":{fieldNames:{value:"id",label:"nickname"},ellipsis:!0},"x-read-pretty":!0}},{name:"changes",collectionName:"auditLogs",type:"hasMany",interface:"subTable",target:"auditChanges",foreignKey:"auditLogId",targetKey:"id",uiSchema:{type:"object",title:t("Details of changes")}},{type:"bigInt",name:"id",interface:"number",uiSchema:{type:"number",title:"ID","x-component":"InputNumber"}}]}),O=()=>({name:"auditChanges",title:t("Audit Changes"),fields:[{name:"field",type:"json",interface:"input",uiSchema:{title:t("Field"),"x-component":"AuditLogsField"}},{type:"json",name:"before",interface:"input",uiSchema:{title:t("Before change"),"x-component":"AuditLogsValue"}},{type:"json",name:"after",interface:"input",uiSchema:{title:t("After change"),"x-component":"AuditLogsValue"}}]}),K=()=>({name:"collections",title:t("Collections"),fields:[{name:"name",type:"string",interface:"input",uiSchema:{title:t("Collection name"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}},{name:"title",type:"string",interface:"input",uiSchema:{title:t("Collection display name"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}}]}),M=a=>{var n=a,{children:o}=n,r=j(n,["children"]);const s=O(),c=E(),u=K();return i.jsx(e.ExtendCollectionsProvider,{collections:[c,s,u],children:i.jsx(e.TableBlockProvider,x(m({name:"audit-logs"},r),{children:o}))})},U=p.observer(()=>{var a,n,s,c;const o=p.useField(),r=e.useCompile();return o.value?i.jsx(e.EllipsisWithTooltip,{ellipsis:!0,children:(n=(a=o.value)==null?void 0:a.uiSchema)!=null&&n.title?r((c=(s=o.value)==null?void 0:s.uiSchema)==null?void 0:c.title):o.value.name}):null},{displayName:"AuditLogsField"}),W=p.observer(()=>{var a,n;const o=p.useField(),r=e.useRecord();return(a=r.field)!=null&&a.uiSchema?i.jsx(e.FormProvider,{children:i.jsx(e.SchemaComponent,{schema:x(m({name:r.field.name},(n=r.field)==null?void 0:n.uiSchema),{default:o.value,"x-read-pretty":!0})})}):i.jsx(e.EllipsisWithTooltip,{ellipsis:!0,children:o.value?JSON.stringify(o.value):null})},{displayName:"AuditLogsValue"}),_=()=>{const o={type:"string","x-component":"AssociationField","x-decorator":"FormItem","x-collection-field":"auditLogs.changes","x-read-pretty":!0,"x-component-props":{multiple:!0,fieldNames:{value:"id",label:"id"},mode:"SubTable"},properties:{block:{type:"void","x-component":"AssociationField.SubTable",properties:{[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{field:{"x-collection-field":"auditChanges.field","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}},[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{before:{"x-collection-field":"auditChanges.before","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}},[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{after:{"x-collection-field":"auditChanges.after","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}}}}}},r={type:"void",title:t("View"),"x-action":"view","x-toolbar":"ActionSchemaToolbar","x-settings":"actionSettings:view","x-component":"Action","x-component-props":{openMode:"drawer"},properties:{drawer:{type:"void",title:t("View record"),"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{tabs:{type:"void","x-component":"Tabs","x-component-props":{},properties:{tab1:{type:"void",title:t("Details"),"x-component":"Tabs.TabPane","x-designer":"Tabs.Designer","x-component-props":{},properties:{grid:{type:"void","x-component":"Grid",properties:{"7ypqrxaqysp":{type:"void","x-component":"Grid.Row",properties:{"1fc2l8dwe7m":{type:"void","x-component":"Grid.Col",properties:{"5ley6xifrsb":{type:"void","x-acl-action":"auditLogs:get","x-decorator":"FormBlockProvider","x-decorator-props":{resource:"auditLogs",collection:"auditLogs",readPretty:!0,action:"get",params:{appends:["collection","user","changes"]},useParams:"{{ useParamsFromRecord }}",useSourceId:"{{ useSourceIdFromParentRecord }}"},"x-component":"CardItem",properties:{bv710pbf9w6:{type:"void","x-component":"FormV2","x-read-pretty":!0,"x-component-props":{useProps:"{{ useFormBlockProps }}"},properties:{grid:{type:"void","x-component":"Grid",properties:{g4c24abnbd9:{type:"void","x-component":"Grid.Row",properties:{fkt9dj5lu1k:{type:"void","x-component":"Grid.Col",properties:{createdAt:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.createdAt","x-component-props":{},"x-read-pretty":!0}}}}},l267bkv423v:{type:"void","x-component":"Grid.Row",properties:{tehaepm5xqy:{type:"void","x-component":"Grid.Col",properties:{type:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.type","x-component-props":{},"x-read-pretty":!0}}}}},zhmn2tkzdh2:{type:"void","x-component":"Grid.Row",properties:{yuwyej17i64:{type:"void","x-component":"Grid.Col",properties:{recordId:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.recordId","x-component-props":{}}}}}},"6q933ic06mj":{type:"void","x-component":"Grid.Row",properties:{nwtbkqd99zl2:{type:"void","x-component":"Grid.Col",properties:{"collection.title":{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.collection.title","x-component-props":{}}}},nwtbkqd99zl1:{type:"void","x-component":"Grid.Col",properties:{"collection.name":{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.collection.name","x-component-props":{}}}}}},xd4kzulndqk:{type:"void","x-component":"Grid.Row",properties:{k3sd72n83zd:{type:"void","x-component":"Grid.Col",properties:{user:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.user","x-component-props":{},"x-read-pretty":!0,properties:{viewer:{type:"void",title:t("View record"),"x-component":"RecordPicker.Viewer","x-component-props":{className:"tb-action-popup"},properties:{tabs:{type:"void","x-component":"Tabs","x-component-props":{},"x-initializer":"popup:addTab",properties:{tab1:{type:"void",title:t("Details"),"x-component":"Tabs.TabPane","x-designer":"Tabs.Designer","x-component-props":{},properties:{grid:{type:"void","x-component":"Grid","x-initializer":"popup:common:addBlock"}}}}}}}}}}}}},"3lghgclbtcg":{type:"void","x-component":"Grid.Row",properties:{"8l1v1auwlx0":{type:"void","x-component":"Grid.Col",properties:{changes:o}}}}}}}}}}}}}}}}}}}}}}}};return i.jsx(e.ActionInitializer,{schema:r})},J=()=>{var C,k,V,G;const{name:o,title:r}=e.useCollection_deprecated(),a=p.useField(),n=p.useFieldSchema(),{form:s}=e.useFormBlockContext(),{service:c}=e.useTableBlockContext(),{t:u}=g(),{dn:S}=e.useDesignable();return i.jsxs(e.GeneralSchemaDesigner,{title:r||o,children:[i.jsx(e.SchemaSettingsDataScope,{collectionName:o,defaultFilter:((k=(C=n==null?void 0:n["x-decorator-props"])==null?void 0:C.params)==null?void 0:k.filter)||{},form:s,onSubmit:({filter:f})=>{var A;const v=a.decoratorProps.params||{};v.filter=f,a.decoratorProps.params=v,n["x-decorator-props"].params=v,c.run(x(m({},(A=c.params)==null?void 0:A[0]),{filter:f,page:1})),S.emit("patch",{schema:{"x-uid":n["x-uid"],"x-decorator-props":n["x-decorator-props"]}})}}),i.jsx(e.SchemaSettingsSelectItem,{title:u("Records per page"),value:((G=(V=a.decoratorProps)==null?void 0:V.params)==null?void 0:G.pageSize)||20,options:[{label:"10",value:10},{label:"20",value:20},{label:"50",value:50},{label:"100",value:100},{label:"200",value:200}],onChange:f=>{var A;const v=a.decoratorProps.params||{};v.pageSize=f,a.decoratorProps.params=v,n["x-decorator-props"].params=v,c.run(x(m({},(A=c.params)==null?void 0:A[0]),{pageSize:f,page:1})),S.emit("patch",{schema:{"x-uid":n["x-uid"],"x-decorator-props":n["x-decorator-props"]}})}}),i.jsx(e.SchemaSettingsDivider,{}),i.jsx(e.SchemaSettingsRemove,{removeParentsIfNoChildren:!0,breakRemoveOn:{"x-component":"Grid"}})]})},R={name:"auditLogs",title:t("Audit logs"),fields:[{name:"createdAt",type:"date",interface:"createdAt",uiSchema:{type:"datetime",title:t("Created at"),"x-component":"DatePicker","x-component-props":{showTime:!0},"x-read-pretty":!0}},{name:"type",type:"string",interface:"select",uiSchema:{type:"string",title:t("Action type"),"x-component":"Select","x-read-pretty":!0,enum:[{label:t("Create record"),value:"create",color:"lime"},{label:t("Update record"),value:"update",color:"gold"},{label:t("Delete record"),value:"destroy",color:"magenta"}]}}]},H=p.observer(()=>{var r,a;const o=p.useField();return i.jsx("div",{children:((r=o==null?void 0:o.value)==null?void 0:r.nickname)||((a=o.value)==null?void 0:a.id)})},{displayName:"Username"}),Q=p.observer(()=>{const o=p.useField(),{title:r,name:a}=o.value||{},n=e.useCompile();return i.jsx("div",{children:r?n(r):a})},{displayName:"Collection"}),X=p.observer(()=>{var a,n,s,c;const o=p.useField(),r=e.useCompile();return o.value?i.jsx("div",{children:(n=(a=o.value)==null?void 0:a.uiSchema)!=null&&n.title?r((c=(s=o.value)==null?void 0:s.uiSchema)==null?void 0:c.title):o.value.name}):null},{displayName:"Field"}),Y=p.observer(()=>{var a,n;const o=p.useField(),r=b.ArrayTable.useRecord();return(a=r.field)!=null&&a.uiSchema?i.jsx(e.FormProvider,{children:i.jsx(e.SchemaComponent,{schema:x(m({name:r.field.name},(n=r.field)==null?void 0:n.uiSchema),{default:o.value,"x-read-pretty":!0})})}):i.jsx("div",{children:o.value?JSON.stringify(o.value):null})},{displayName:"Value"}),F=h.createContext(null);F.displayName="IsAssociationBlock";const L=()=>{const o=h.useContext(F),r={};return o||(r.column31={type:"void","x-component":"TableV2.Column",title:t("Record ID"),properties:{recordId:{"x-component":"Input","x-read-pretty":!0}}}),i.jsx(e.SchemaComponent,{memoized:!0,components:{ArrayTable:b.ArrayTable,Username:H,Collection:Q,Field:X,Value:Y},schema:{type:"void",name:"lfm4trkw8j3","x-component":"div",properties:{actions:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:16}},properties:{filter:{type:"void",title:t("Filter"),"x-action":"filter","x-component":"Filter.Action","x-component-props":{icon:"FilterOutlined",useProps:"{{ useFilterActionProps }}"},"x-align":"left"}}},y84dlntcaup:{type:"array","x-component":"TableV2","x-component-props":{rowKey:"id",rowSelection:{type:"checkbox"},useProps:"{{ useTableBlockProps }}"},properties:x(m({actions:{type:"void",title:t("Actions"),"x-action-column":"actions","x-decorator":"TableV2.Column.ActionBar","x-component":"TableV2.Column","x-designer":"TableV2.ActionColumnDesigner","x-initializer":"table:configureItemActions",properties:{actions:{type:"void","x-decorator":"DndContext","x-component":"Space","x-component-props":{split:"|"},properties:{o80rypwmeeg:{type:"void",title:t("View"),"x-toolbar":"ActionSchemaToolbar","x-settings":"actionSettings:view","x-component":"Action.Link","x-component-props":{openMode:"drawer"},properties:{drawer:{type:"void",title:t("View record"),"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{grid:{type:"void","x-component":"Grid",properties:{tdlav8o9o17:{type:"void","x-component":"Grid.Row",properties:{"7bsnaf47i6g":{type:"void","x-component":"Grid.Col",properties:{"6s2qbihe3tu":{type:"void","x-acl-action":"auditLogs:get","x-decorator":"FormBlockProvider","x-decorator-props":{resource:"auditLogs",collection:"auditLogs",readPretty:!0,action:"get",params:{appends:["collection","user","changes"]},useParams:"{{ useParamsFromRecord }}",useSourceId:"{{ useSourceIdFromParentRecord }}"},"x-component":"CardItem",properties:{mevpuonrda0:{type:"void","x-component":"FormV2","x-read-pretty":!0,"x-component-props":{useProps:"{{ useFormBlockProps }}"},properties:{grid:{type:"void","x-component":"Grid",properties:{row1:{type:"void","x-component":"Grid.Row",properties:{col11:{type:"void","x-component":"Grid.Col",properties:{collection:{type:"string",title:t("Collection display name"),"x-component":"Collection","x-decorator":"FormItem","x-read-pretty":!0}}}}},row2:{type:"void","x-component":"Grid.Row",properties:{col21:{type:"void","x-component":"Grid.Col",properties:{type:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-read-pretty":!0}}}}},row3:{type:"void","x-component":"Grid.Row",properties:{col31:{type:"void","x-component":"Grid.Col",properties:{createdAt:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-read-pretty":!0}}}}},row4:{type:"void","x-component":"Grid.Row",properties:{col41:{type:"void","x-component":"Grid.Col",properties:{user:{type:"string",title:t("User"),"x-component":"Username","x-decorator":"FormItem","x-read-pretty":!0}}}}},row5:{type:"void","x-component":"Grid.Row",properties:{col51:{type:"void","x-component":"Grid.Col",properties:{changes:{type:"array",title:t("Field value changes"),"x-decorator":"FormItem","x-component":"ArrayTable","x-component-props":{pagination:{pageSize:10},scroll:{x:"100%"}},items:{type:"object",properties:{column3:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:t("Field")},properties:{field:{type:"string","x-component":"Field"}}},column4:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:t("Before change")},properties:{before:{type:"string","x-decorator":"FormItem","x-component":"Value"}}},column5:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:t("After change")},properties:{after:{type:"string","x-decorator":"FormItem","x-component":"Value"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},column1:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{createdAt:{"x-component":"CollectionField","x-read-pretty":!0}}},column2:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{type:{"x-component":"CollectionField","x-read-pretty":!0}}},column3:{type:"void","x-component":"TableV2.Column",title:t("Collection display name"),properties:{collection:{"x-component":"Collection","x-read-pretty":!0}}}},r),{column4:{type:"void","x-component":"TableV2.Column",title:t("User"),properties:{user:{"x-component":"Username","x-read-pretty":!0}}}})}}}})};L.Decorator=p.observer(o=>{var c;const r=e.useCollection_deprecated(),a=e.useRecord();let n=(c=o==null?void 0:o.params)==null?void 0:c.filter;if(r.name){const u=a==null?void 0:a[r.filterTargetKey||"id"];n?n={$and:[n,{collectionName:r.name,recordId:`${u}`}]}:n={collectionName:r.name,recordId:`${u}`}}const s={collection:"auditLogs",resource:"auditLogs",action:"list",params:x(m({pageSize:20,appends:["collection","user"]},o.params),{filter:n,sort:"-createdAt"}),rowKey:"id",showIndex:!0,dragSort:!1};return i.jsx(F.Provider,{value:!!r.name,children:i.jsx(e.ExtendCollectionsProvider,{collections:[R],children:i.jsx(e.TableBlockProvider,x(m({},s),{children:o.children}))})})},{displayName:"AuditLogs.Decorator"}),L.Designer=J;const Z=()=>{const o={type:"void",title:t("Actions"),"x-decorator":"TableV2.Column.ActionBar","x-component":"TableV2.Column","x-designer":"TableV2.ActionColumnDesigner","x-initializer":"auditLogsTable:configureItemActions","x-action-column":"actions",properties:{actions:{type:"void","x-decorator":"DndContext","x-component":"Space","x-component-props":{split:"|"},properties:{}}}},r=e.useSchemaInitializerItem();return i.jsx(e.InitializerWithSwitch,x(m({},r),{schema:o,item:r,type:"x-action-column"}))},P=o=>i.jsx(e.SchemaComponentOptions,{components:{AuditLogs:L,AuditLogsBlockProvider:M,AuditLogsBlockInitializer:w,AuditLogsValue:W,AuditLogsField:U,AuditLogsViewActionInitializer:_,AuditLogsTableActionColumnInitializer:Z},children:o.children}),$=new e.SchemaInitializer({name:"auditLogsTable:configureItemActions",insertPosition:"beforeEnd",Component:o=>i.jsx(d.MenuOutlined,x(m({},o),{style:{cursor:"pointer"}})),useInsert(){const o=p.useFieldSchema(),r=e.useAPIClient(),{refresh:a}=e.useDesignable(),{t:n}=g();return s=>{const c=o.reduceProperties((S,C)=>C["x-component"]==="Space"?C:S,null);if(!c)return;const u=e.createDesignable({t:n,api:r,refresh:a,current:c});u.loadAPIClientEvents(),u.insertBeforeEnd(s)}},items:[{name:"enableActions",type:"itemGroup",title:t("Enable actions"),children:[{name:"view",type:"item",title:t("View"),Component:"AuditLogsViewActionInitializer",schema:{"x-component":"Action.Link","x-action":"view","x-decorator":"ACLActionProvider"}}]},{name:"divider",type:"divider"},{name:"columnWidth",type:"item",title:t("Column width"),Component:e.Resizable}]}),ee=new e.SchemaInitializer({name:"auditLogsTable:configureActions",title:t("Configure actions"),icon:"SettingOutlined",style:{marginLeft:8},items:[{type:"itemGroup",title:t("Enable actions"),name:"enableActions",children:[{name:"filter",title:t("Filter"),Component:"FilterActionInitializer",schema:{"x-align":"left"}},{name:"refresh",title:t("Refresh"),Component:"RefreshActionInitializer",schema:{"x-align":"right"}}]}]}),oe=()=>{const o=e.useInheritsTableColumnInitializerFields(),{t:r}=g(),a=e.useCompile();if(!(o!=null&&o.length))return null;const n=[];return o.forEach(s=>{Object.values(s)[0].length&&n.push({type:"itemGroup",divider:!0,title:r("Parent collection fields")+"("+a(`${Object.keys(s)[0]}`)+")",children:Object.values(s)[0].filter(c=>{var u;return!((u=c==null?void 0:c.field)!=null&&u.isForeignKey)})})}),i.jsx(e.SchemaInitializerChildren,{children:n})},te=()=>{const o=e.useAssociatedTableColumnInitializerFields(),{t:r}=g();if(!(o!=null&&o.length))return null;const a=[{type:"itemGroup",divider:!0,title:r("Display association fields"),children:o}];return i.jsx(e.SchemaInitializerChildren,{children:a})},ie=new e.SchemaInitializer({name:"auditLogsTable:configureColumns",insertPosition:"beforeEnd",icon:"SettingOutlined",title:t("Configure columns"),wrap(o){return o["x-action-column"]?o:{type:"void","x-toolbar":"TableColumnSchemaToolbar","x-settings":"fieldSettings:TableColumn","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{[o.name]:m({},o)}}},items:[{name:"displayFields",type:"itemGroup",title:t("Display fields"),useChildren:e.useTableColumnInitializerFields},{name:"parentCollectionFields",Component:oe},{name:"associationFields",Component:te},{name:"actionColumn",title:t("Action column"),Component:"AuditLogsTableActionColumnInitializer"}]});class z extends e.Plugin{load(){return q(this,null,function*(){this.app.use(P),this.app.schemaInitializerManager.add(ee),this.app.schemaInitializerManager.add($),this.app.schemaInitializerManager.add(ie);const r=this.app.schemaInitializerManager.get("page:addBlock"),a=this.app.schemaInitializerManager.get("popup:common:addBlock"),n={title:t("Audit logs"),Component:"AuditLogsBlockInitializer"};r.add("otherBlocks.auditLogs",n),a.add("otherBlocks.auditLogs",n)})}}l.AuditLogsBlockInitializer=w,l.AuditLogsPlugin=z,l.AuditLogsProvider=P,l.default=z,Object.defineProperties(l,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
1
|
+
(function(l,e){typeof exports=="object"&&typeof module!="undefined"?e(exports,require("@tachybase/client"),require("react/jsx-runtime"),require("@ant-design/icons"),require("react-i18next"),require("@tachybase/schema"),require("@tego/client"),require("react")):typeof define=="function"&&define.amd?define(["exports","@tachybase/client","react/jsx-runtime","@ant-design/icons","react-i18next","@tachybase/schema","@tego/client","react"],e):(l=typeof globalThis!="undefined"?globalThis:l||self,e(l["@tachybase/plugin-audit-logs"]={},l["@tachybase/client"],l.jsxRuntime,l["@ant-design/icons"],l["react-i18next"],l["@tachybase/schema"],l["@tego/client"],l.react))})(this,function(l,e,i,d,I,p,b,h){"use strict";var re=Object.defineProperty,ne=Object.defineProperties;var ae=Object.getOwnPropertyDescriptors;var T=Object.getOwnPropertySymbols;var D=Object.prototype.hasOwnProperty,N=Object.prototype.propertyIsEnumerable;var B=(l,e,i)=>e in l?re(l,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):l[e]=i,m=(l,e)=>{for(var i in e||(e={}))D.call(e,i)&&B(l,i,e[i]);if(T)for(var i of T(e))N.call(e,i)&&B(l,i,e[i]);return l},x=(l,e)=>ne(l,ae(e));var j=(l,e)=>{var i={};for(var d in l)D.call(l,d)&&e.indexOf(d)<0&&(i[d]=l[d]);if(l!=null&&T)for(var d of T(l))e.indexOf(d)<0&&N.call(l,d)&&(i[d]=l[d]);return i};var q=(l,e,i)=>new Promise((d,I)=>{var p=y=>{try{h(i.next(y))}catch(g){I(g)}},b=y=>{try{h(i.throw(y))}catch(g){I(g)}},h=y=>y.done?d(y.value):Promise.resolve(y.value).then(p,b);h((i=i.apply(l,e)).next())});const y="@tachybase/plugin-audit-logs";function g(){return I.useTranslation(y)}const o=t=>e.tval(t,{ns:y}),w=()=>{const{insert:t}=e.useSchemaInitializer(),{t:r}=g(),a=e.useSchemaInitializerItem(),n=e.createTableBlockSchema({collection:"auditLogs",rowKey:"id",tableActionInitializers:"auditLogsTable:configureActions",tableColumnInitializers:"auditLogsTable:configureColumns",tableActionColumnInitializers:"auditLogsTable:configureItemActions",tableBlockProvider:"AuditLogsBlockProvider",disableTemplate:!0});return i.jsx(e.SchemaInitializerItem,m({icon:i.jsx(d.TableOutlined,{}),onClick:()=>{t(n)},title:r("Audit Logs")},a))},O=()=>({name:"auditLogs",title:o("Audit logs"),fields:[{name:"createdAt",type:"date",interface:"createdAt",uiSchema:{type:"datetime",title:o("Created at"),"x-component":"DatePicker","x-component-props":{showTime:!0,ellipsis:!0},"x-read-pretty":!0}},{name:"type",type:"string",interface:"select",uiSchema:{type:"string",title:o("Action type"),"x-component":"Select","x-component-props":{ellipsis:!0},"x-read-pretty":!0,enum:[{label:o("Create record"),value:"create",color:"lime"},{label:o("Update record"),value:"update",color:"gold"},{label:o("Delete record"),value:"destroy",color:"magenta"},{label:o("Tenant access denied"),value:"tenant_access_denied",color:"red"},{label:o("Cross-tenant attempt"),value:"tenant_cross_tenant_attempt",color:"red"},{label:o("Bulk export alert"),value:"tenant_bulk_export_alert",color:"orange"},{label:o("Tenant impersonation"),value:"tenant_impersonation",color:"blue"}]}},{name:"recordId",type:"string",interface:"input",uiSchema:{title:o("Record ID"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}},{collectionName:"auditLogs",name:"collection",type:"belongsTo",interface:"m2o",target:"collections",targetKey:"name",sourceKey:"id",foreignKey:"collectionName",uiSchema:{type:"object",title:o("Collection"),"x-component":"AssociationField","x-component-props":{fieldNames:{value:"name",label:"title"},ellipsis:!0},"x-read-pretty":!0}},{name:"collectionName",type:"string",interface:"string",uiSchema:{type:"string",title:o("Collection name"),"x-component":"Input"}},{name:"tenantId",type:"string",interface:"input",uiSchema:{type:"string",title:o("Tenant ID"),"x-component":"Input"}},{name:"user",collectionName:"auditLogs",type:"belongsTo",interface:"createdBy",targetKey:"id",foreignKey:"createdById",target:"users",uiSchema:{type:"object",title:o("User"),"x-component":"AssociationField","x-component-props":{fieldNames:{value:"id",label:"nickname"},ellipsis:!0},"x-read-pretty":!0}},{name:"changes",collectionName:"auditLogs",type:"hasMany",interface:"subTable",target:"auditChanges",foreignKey:"auditLogId",targetKey:"id",uiSchema:{type:"object",title:o("Details of changes")}},{name:"details",type:"json",interface:"input",uiSchema:{type:"object",title:o("Security event details"),"x-component":"Input.JSON","x-component-props":{ellipsis:!0},"x-read-pretty":!0}},{type:"bigInt",name:"id",interface:"number",uiSchema:{type:"number",title:"ID","x-component":"InputNumber"}}]}),E=()=>({name:"auditChanges",title:o("Audit Changes"),fields:[{name:"field",type:"json",interface:"input",uiSchema:{title:o("Field"),"x-component":"AuditLogsField"}},{type:"json",name:"before",interface:"input",uiSchema:{title:o("Before change"),"x-component":"AuditLogsValue"}},{type:"json",name:"after",interface:"input",uiSchema:{title:o("After change"),"x-component":"AuditLogsValue"}}]}),_=()=>({name:"collections",title:o("Collections"),fields:[{name:"name",type:"string",interface:"input",uiSchema:{title:o("Collection name"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}},{name:"title",type:"string",interface:"input",uiSchema:{title:o("Collection display name"),type:"string","x-component":"Input","x-component-props":{ellipsis:!0}}}]}),K=a=>{var n=a,{children:t}=n,r=j(n,["children"]);const s=E(),c=O(),u=_();return i.jsx(e.ExtendCollectionsProvider,{collections:[c,s,u],children:i.jsx(e.TableBlockProvider,x(m({name:"audit-logs"},r),{children:t}))})},M=p.observer(()=>{var a,n,s,c;const t=p.useField(),r=e.useCompile();return t.value?i.jsx(e.EllipsisWithTooltip,{ellipsis:!0,children:(n=(a=t.value)==null?void 0:a.uiSchema)!=null&&n.title?r((c=(s=t.value)==null?void 0:s.uiSchema)==null?void 0:c.title):t.value.name}):null},{displayName:"AuditLogsField"}),U=p.observer(()=>{var a,n;const t=p.useField(),r=e.useRecord();return(a=r.field)!=null&&a.uiSchema?i.jsx(e.FormProvider,{children:i.jsx(e.SchemaComponent,{schema:x(m({name:r.field.name},(n=r.field)==null?void 0:n.uiSchema),{default:t.value,"x-read-pretty":!0})})}):i.jsx(e.EllipsisWithTooltip,{ellipsis:!0,children:t.value?JSON.stringify(t.value):null})},{displayName:"AuditLogsValue"}),W=()=>{const t={type:"string","x-component":"AssociationField","x-decorator":"FormItem","x-collection-field":"auditLogs.changes","x-read-pretty":!0,"x-component-props":{multiple:!0,fieldNames:{value:"id",label:"id"},mode:"SubTable"},properties:{block:{type:"void","x-component":"AssociationField.SubTable",properties:{[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{field:{"x-collection-field":"auditChanges.field","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}},[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{before:{"x-collection-field":"auditChanges.before","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}},[b.uid()]:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{after:{"x-collection-field":"auditChanges.after","x-component":"CollectionField","x-read-pretty":!0,"x-component-props":{ellipsis:!0}}}}}}}},r={type:"void",title:o("View"),"x-action":"view","x-toolbar":"ActionSchemaToolbar","x-settings":"actionSettings:view","x-component":"Action","x-component-props":{openMode:"drawer"},properties:{drawer:{type:"void",title:o("View record"),"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{tabs:{type:"void","x-component":"Tabs","x-component-props":{},properties:{tab1:{type:"void",title:o("Details"),"x-component":"Tabs.TabPane","x-designer":"Tabs.Designer","x-component-props":{},properties:{grid:{type:"void","x-component":"Grid",properties:{"7ypqrxaqysp":{type:"void","x-component":"Grid.Row",properties:{"1fc2l8dwe7m":{type:"void","x-component":"Grid.Col",properties:{"5ley6xifrsb":{type:"void","x-acl-action":"auditLogs:get","x-decorator":"FormBlockProvider","x-decorator-props":{resource:"auditLogs",collection:"auditLogs",readPretty:!0,action:"get",params:{appends:["collection","user","changes"]},useParams:"{{ useParamsFromRecord }}",useSourceId:"{{ useSourceIdFromParentRecord }}"},"x-component":"CardItem",properties:{bv710pbf9w6:{type:"void","x-component":"FormV2","x-read-pretty":!0,"x-component-props":{useProps:"{{ useFormBlockProps }}"},properties:{grid:{type:"void","x-component":"Grid",properties:{g4c24abnbd9:{type:"void","x-component":"Grid.Row",properties:{fkt9dj5lu1k:{type:"void","x-component":"Grid.Col",properties:{createdAt:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.createdAt","x-component-props":{},"x-read-pretty":!0}}}}},l267bkv423v:{type:"void","x-component":"Grid.Row",properties:{tehaepm5xqy:{type:"void","x-component":"Grid.Col",properties:{type:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.type","x-component-props":{},"x-read-pretty":!0}}}}},zhmn2tkzdh2:{type:"void","x-component":"Grid.Row",properties:{yuwyej17i64:{type:"void","x-component":"Grid.Col",properties:{recordId:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.recordId","x-component-props":{}}}}}},"6q933ic06mj":{type:"void","x-component":"Grid.Row",properties:{nwtbkqd99zl2:{type:"void","x-component":"Grid.Col",properties:{"collection.title":{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.collection.title","x-component-props":{}}}},nwtbkqd99zl1:{type:"void","x-component":"Grid.Col",properties:{"collection.name":{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.collection.name","x-component-props":{}}}}}},xd4kzulndqk:{type:"void","x-component":"Grid.Row",properties:{k3sd72n83zd:{type:"void","x-component":"Grid.Col",properties:{user:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-collection-field":"auditLogs.user","x-component-props":{},"x-read-pretty":!0,properties:{viewer:{type:"void",title:o("View record"),"x-component":"RecordPicker.Viewer","x-component-props":{className:"tb-action-popup"},properties:{tabs:{type:"void","x-component":"Tabs","x-component-props":{},"x-initializer":"popup:addTab",properties:{tab1:{type:"void",title:o("Details"),"x-component":"Tabs.TabPane","x-designer":"Tabs.Designer","x-component-props":{},properties:{grid:{type:"void","x-component":"Grid","x-initializer":"popup:common:addBlock"}}}}}}}}}}}}},"3lghgclbtcg":{type:"void","x-component":"Grid.Row",properties:{"8l1v1auwlx0":{type:"void","x-component":"Grid.Col",properties:{changes:t}}}}}}}}}}}}}}}}}}}}}}}};return i.jsx(e.ActionInitializer,{schema:r})},J=()=>{var C,k,V,G;const{name:t,title:r}=e.useCollection_deprecated(),a=p.useField(),n=p.useFieldSchema(),{form:s}=e.useFormBlockContext(),{service:c}=e.useTableBlockContext(),{t:u}=g(),{dn:S}=e.useDesignable();return i.jsxs(e.GeneralSchemaDesigner,{title:r||t,children:[i.jsx(e.SchemaSettingsDataScope,{collectionName:t,defaultFilter:((k=(C=n==null?void 0:n["x-decorator-props"])==null?void 0:C.params)==null?void 0:k.filter)||{},form:s,onSubmit:({filter:f})=>{var A;const v=a.decoratorProps.params||{};v.filter=f,a.decoratorProps.params=v,n["x-decorator-props"].params=v,c.run(x(m({},(A=c.params)==null?void 0:A[0]),{filter:f,page:1})),S.emit("patch",{schema:{"x-uid":n["x-uid"],"x-decorator-props":n["x-decorator-props"]}})}}),i.jsx(e.SchemaSettingsSelectItem,{title:u("Records per page"),value:((G=(V=a.decoratorProps)==null?void 0:V.params)==null?void 0:G.pageSize)||20,options:[{label:"10",value:10},{label:"20",value:20},{label:"50",value:50},{label:"100",value:100},{label:"200",value:200}],onChange:f=>{var A;const v=a.decoratorProps.params||{};v.pageSize=f,a.decoratorProps.params=v,n["x-decorator-props"].params=v,c.run(x(m({},(A=c.params)==null?void 0:A[0]),{pageSize:f,page:1})),S.emit("patch",{schema:{"x-uid":n["x-uid"],"x-decorator-props":n["x-decorator-props"]}})}}),i.jsx(e.SchemaSettingsDivider,{}),i.jsx(e.SchemaSettingsRemove,{removeParentsIfNoChildren:!0,breakRemoveOn:{"x-component":"Grid"}})]})},R={name:"auditLogs",title:o("Audit logs"),fields:[{name:"createdAt",type:"date",interface:"createdAt",uiSchema:{type:"datetime",title:o("Created at"),"x-component":"DatePicker","x-component-props":{showTime:!0},"x-read-pretty":!0}},{name:"type",type:"string",interface:"select",uiSchema:{type:"string",title:o("Action type"),"x-component":"Select","x-read-pretty":!0,enum:[{label:o("Create record"),value:"create",color:"lime"},{label:o("Update record"),value:"update",color:"gold"},{label:o("Delete record"),value:"destroy",color:"magenta"}]}}]},H=p.observer(()=>{var r,a;const t=p.useField();return i.jsx("div",{children:((r=t==null?void 0:t.value)==null?void 0:r.nickname)||((a=t.value)==null?void 0:a.id)})},{displayName:"Username"}),Q=p.observer(()=>{const t=p.useField(),{title:r,name:a}=t.value||{},n=e.useCompile();return i.jsx("div",{children:r?n(r):a})},{displayName:"Collection"}),X=p.observer(()=>{var a,n,s,c;const t=p.useField(),r=e.useCompile();return t.value?i.jsx("div",{children:(n=(a=t.value)==null?void 0:a.uiSchema)!=null&&n.title?r((c=(s=t.value)==null?void 0:s.uiSchema)==null?void 0:c.title):t.value.name}):null},{displayName:"Field"}),Y=p.observer(()=>{var a,n;const t=p.useField(),r=b.ArrayTable.useRecord();return(a=r.field)!=null&&a.uiSchema?i.jsx(e.FormProvider,{children:i.jsx(e.SchemaComponent,{schema:x(m({name:r.field.name},(n=r.field)==null?void 0:n.uiSchema),{default:t.value,"x-read-pretty":!0})})}):i.jsx("div",{children:t.value?JSON.stringify(t.value):null})},{displayName:"Value"}),F=h.createContext(null);F.displayName="IsAssociationBlock";const L=()=>{const t=h.useContext(F),r={};return t||(r.column31={type:"void","x-component":"TableV2.Column",title:o("Record ID"),properties:{recordId:{"x-component":"Input","x-read-pretty":!0}}}),i.jsx(e.SchemaComponent,{memoized:!0,components:{ArrayTable:b.ArrayTable,Username:H,Collection:Q,Field:X,Value:Y},schema:{type:"void",name:"lfm4trkw8j3","x-component":"div",properties:{actions:{type:"void","x-component":"ActionBar","x-component-props":{style:{marginBottom:16}},properties:{filter:{type:"void",title:o("Filter"),"x-action":"filter","x-component":"Filter.Action","x-component-props":{icon:"FilterOutlined",useProps:"{{ useFilterActionProps }}"},"x-align":"left"}}},y84dlntcaup:{type:"array","x-component":"TableV2","x-component-props":{rowKey:"id",rowSelection:{type:"checkbox"},useProps:"{{ useTableBlockProps }}"},properties:x(m({actions:{type:"void",title:o("Actions"),"x-action-column":"actions","x-decorator":"TableV2.Column.ActionBar","x-component":"TableV2.Column","x-designer":"TableV2.ActionColumnDesigner","x-initializer":"table:configureItemActions",properties:{actions:{type:"void","x-decorator":"DndContext","x-component":"Space","x-component-props":{split:"|"},properties:{o80rypwmeeg:{type:"void",title:o("View"),"x-toolbar":"ActionSchemaToolbar","x-settings":"actionSettings:view","x-component":"Action.Link","x-component-props":{openMode:"drawer"},properties:{drawer:{type:"void",title:o("View record"),"x-component":"Action.Container","x-component-props":{className:"tb-action-popup"},properties:{grid:{type:"void","x-component":"Grid",properties:{tdlav8o9o17:{type:"void","x-component":"Grid.Row",properties:{"7bsnaf47i6g":{type:"void","x-component":"Grid.Col",properties:{"6s2qbihe3tu":{type:"void","x-acl-action":"auditLogs:get","x-decorator":"FormBlockProvider","x-decorator-props":{resource:"auditLogs",collection:"auditLogs",readPretty:!0,action:"get",params:{appends:["collection","user","changes"]},useParams:"{{ useParamsFromRecord }}",useSourceId:"{{ useSourceIdFromParentRecord }}"},"x-component":"CardItem",properties:{mevpuonrda0:{type:"void","x-component":"FormV2","x-read-pretty":!0,"x-component-props":{useProps:"{{ useFormBlockProps }}"},properties:{grid:{type:"void","x-component":"Grid",properties:{row1:{type:"void","x-component":"Grid.Row",properties:{col11:{type:"void","x-component":"Grid.Col",properties:{collection:{type:"string",title:o("Collection display name"),"x-component":"Collection","x-decorator":"FormItem","x-read-pretty":!0}}}}},row2:{type:"void","x-component":"Grid.Row",properties:{col21:{type:"void","x-component":"Grid.Col",properties:{type:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-read-pretty":!0}}}}},row3:{type:"void","x-component":"Grid.Row",properties:{col31:{type:"void","x-component":"Grid.Col",properties:{createdAt:{type:"string","x-component":"CollectionField","x-decorator":"FormItem","x-read-pretty":!0}}}}},row4:{type:"void","x-component":"Grid.Row",properties:{col41:{type:"void","x-component":"Grid.Col",properties:{user:{type:"string",title:o("User"),"x-component":"Username","x-decorator":"FormItem","x-read-pretty":!0}}}}},row5:{type:"void","x-component":"Grid.Row",properties:{col51:{type:"void","x-component":"Grid.Col",properties:{changes:{type:"array",title:o("Field value changes"),"x-decorator":"FormItem","x-component":"ArrayTable","x-component-props":{pagination:{pageSize:10},scroll:{x:"100%"}},items:{type:"object",properties:{column3:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:o("Field")},properties:{field:{type:"string","x-component":"Field"}}},column4:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:o("Before change")},properties:{before:{type:"string","x-decorator":"FormItem","x-component":"Value"}}},column5:{type:"void","x-component":"ArrayTable.Column","x-component-props":{width:200,title:o("After change")},properties:{after:{type:"string","x-decorator":"FormItem","x-component":"Value"}}}}}}}}}}}}}}}}}}}}}}}}}}}}}},column1:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{createdAt:{"x-component":"CollectionField","x-read-pretty":!0}}},column2:{type:"void","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{type:{"x-component":"CollectionField","x-read-pretty":!0}}},column3:{type:"void","x-component":"TableV2.Column",title:o("Collection display name"),properties:{collection:{"x-component":"Collection","x-read-pretty":!0}}}},r),{column4:{type:"void","x-component":"TableV2.Column",title:o("User"),properties:{user:{"x-component":"Username","x-read-pretty":!0}}}})}}}})};L.Decorator=p.observer(t=>{var c;const r=e.useCollection_deprecated(),a=e.useRecord();let n=(c=t==null?void 0:t.params)==null?void 0:c.filter;if(r.name){const u=a==null?void 0:a[r.filterTargetKey||"id"];n?n={$and:[n,{collectionName:r.name,recordId:`${u}`}]}:n={collectionName:r.name,recordId:`${u}`}}const s={collection:"auditLogs",resource:"auditLogs",action:"list",params:x(m({pageSize:20,appends:["collection","user"]},t.params),{filter:n,sort:"-createdAt"}),rowKey:"id",showIndex:!0,dragSort:!1};return i.jsx(F.Provider,{value:!!r.name,children:i.jsx(e.ExtendCollectionsProvider,{collections:[R],children:i.jsx(e.TableBlockProvider,x(m({},s),{children:t.children}))})})},{displayName:"AuditLogs.Decorator"}),L.Designer=J;const Z=()=>{const t={type:"void",title:o("Actions"),"x-decorator":"TableV2.Column.ActionBar","x-component":"TableV2.Column","x-designer":"TableV2.ActionColumnDesigner","x-initializer":"auditLogsTable:configureItemActions","x-action-column":"actions",properties:{actions:{type:"void","x-decorator":"DndContext","x-component":"Space","x-component-props":{split:"|"},properties:{}}}},r=e.useSchemaInitializerItem();return i.jsx(e.InitializerWithSwitch,x(m({},r),{schema:t,item:r,type:"x-action-column"}))},P=t=>i.jsx(e.SchemaComponentOptions,{components:{AuditLogs:L,AuditLogsBlockProvider:K,AuditLogsBlockInitializer:w,AuditLogsValue:U,AuditLogsField:M,AuditLogsViewActionInitializer:W,AuditLogsTableActionColumnInitializer:Z},children:t.children}),$=new e.SchemaInitializer({name:"auditLogsTable:configureItemActions",insertPosition:"beforeEnd",Component:t=>i.jsx(d.MenuOutlined,x(m({},t),{style:{cursor:"pointer"}})),useInsert(){const t=p.useFieldSchema(),r=e.useAPIClient(),{refresh:a}=e.useDesignable(),{t:n}=g();return s=>{const c=t.reduceProperties((S,C)=>C["x-component"]==="Space"?C:S,null);if(!c)return;const u=e.createDesignable({t:n,api:r,refresh:a,current:c});u.loadAPIClientEvents(),u.insertBeforeEnd(s)}},items:[{name:"enableActions",type:"itemGroup",title:o("Enable actions"),children:[{name:"view",type:"item",title:o("View"),Component:"AuditLogsViewActionInitializer",schema:{"x-component":"Action.Link","x-action":"view","x-decorator":"ACLActionProvider"}}]},{name:"divider",type:"divider"},{name:"columnWidth",type:"item",title:o("Column width"),Component:e.Resizable}]}),ee=new e.SchemaInitializer({name:"auditLogsTable:configureActions",title:o("Configure actions"),icon:"SettingOutlined",style:{marginLeft:8},items:[{type:"itemGroup",title:o("Enable actions"),name:"enableActions",children:[{name:"filter",title:o("Filter"),Component:"FilterActionInitializer",schema:{"x-align":"left"}},{name:"refresh",title:o("Refresh"),Component:"RefreshActionInitializer",schema:{"x-align":"right"}}]}]}),te=()=>{const t=e.useInheritsTableColumnInitializerFields(),{t:r}=g(),a=e.useCompile();if(!(t!=null&&t.length))return null;const n=[];return t.forEach(s=>{Object.values(s)[0].length&&n.push({type:"itemGroup",divider:!0,title:r("Parent collection fields")+"("+a(`${Object.keys(s)[0]}`)+")",children:Object.values(s)[0].filter(c=>{var u;return!((u=c==null?void 0:c.field)!=null&&u.isForeignKey)})})}),i.jsx(e.SchemaInitializerChildren,{children:n})},oe=()=>{const t=e.useAssociatedTableColumnInitializerFields(),{t:r}=g();if(!(t!=null&&t.length))return null;const a=[{type:"itemGroup",divider:!0,title:r("Display association fields"),children:t}];return i.jsx(e.SchemaInitializerChildren,{children:a})},ie=new e.SchemaInitializer({name:"auditLogsTable:configureColumns",insertPosition:"beforeEnd",icon:"SettingOutlined",title:o("Configure columns"),wrap(t){return t["x-action-column"]?t:{type:"void","x-toolbar":"TableColumnSchemaToolbar","x-settings":"fieldSettings:TableColumn","x-decorator":"TableV2.Column.Decorator","x-component":"TableV2.Column",properties:{[t.name]:m({},t)}}},items:[{name:"displayFields",type:"itemGroup",title:o("Display fields"),useChildren:e.useTableColumnInitializerFields},{name:"parentCollectionFields",Component:te},{name:"associationFields",Component:oe},{name:"actionColumn",title:o("Action column"),Component:"AuditLogsTableActionColumnInitializer"}]});class z extends e.Plugin{load(){return q(this,null,function*(){this.app.use(P),this.app.schemaInitializerManager.add(ee),this.app.schemaInitializerManager.add($),this.app.schemaInitializerManager.add(ie);const r=this.app.schemaInitializerManager.get("page:addBlock"),a=this.app.schemaInitializerManager.get("popup:common:addBlock"),n={title:o("Audit logs"),Component:"AuditLogsBlockInitializer"};r.add("otherBlocks.auditLogs",n),a.add("otherBlocks.auditLogs",n)})}}l.AuditLogsBlockInitializer=w,l.AuditLogsPlugin=z,l.AuditLogsProvider=P,l.default=z,Object.defineProperties(l,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
package/dist/externalVersion.js
CHANGED
package/dist/locale/en-US.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"Audit Logs": "Audit Logs",
|
|
9
9
|
"Audit logs": "Audit logs",
|
|
10
10
|
"Before change": "Before change",
|
|
11
|
+
"Bulk export alert": "Bulk export alert",
|
|
11
12
|
"Cancel": "Cancel",
|
|
12
13
|
"Collection": "Collection",
|
|
13
14
|
"Collection display name": "Collection display name",
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
"Create record": "Create record",
|
|
20
21
|
"Created at": "Created at",
|
|
21
22
|
"Created by": "Created by",
|
|
23
|
+
"Cross-tenant attempt": "Cross-tenant attempt",
|
|
22
24
|
"Data changes": "Data changes",
|
|
23
25
|
"Delete": "Delete",
|
|
24
26
|
"Delete record": "Delete record",
|
|
@@ -35,7 +37,11 @@
|
|
|
35
37
|
"Record ID": "Record ID",
|
|
36
38
|
"Records per page": "Records per page",
|
|
37
39
|
"Refresh": "Refresh",
|
|
40
|
+
"Security event details": "Security event details",
|
|
38
41
|
"Submit": "Submit",
|
|
42
|
+
"Tenant ID": "Tenant ID",
|
|
43
|
+
"Tenant access denied": "Tenant access denied",
|
|
44
|
+
"Tenant impersonation": "Tenant impersonation",
|
|
39
45
|
"Update": "Update",
|
|
40
46
|
"Update record": "Update record",
|
|
41
47
|
"User": "User",
|
package/dist/locale/zh-CN.json
CHANGED
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"Audit Logs": "审计日志",
|
|
9
9
|
"Audit logs": "审计日志",
|
|
10
10
|
"Before change": "变化前",
|
|
11
|
+
"Bulk export alert": "大批量导出告警",
|
|
11
12
|
"Cancel": "取消",
|
|
12
13
|
"Collection": "数据集",
|
|
13
14
|
"Collection display name": "数据集显示名称",
|
|
@@ -19,6 +20,7 @@
|
|
|
19
20
|
"Create record": "新增数据",
|
|
20
21
|
"Created at": "创建于",
|
|
21
22
|
"Created by": "由创建",
|
|
23
|
+
"Cross-tenant attempt": "跨租户访问尝试",
|
|
22
24
|
"Data changes": "数据变化",
|
|
23
25
|
"Delete": "删除",
|
|
24
26
|
"Delete record": "删除数据",
|
|
@@ -35,7 +37,11 @@
|
|
|
35
37
|
"Record ID": "数据 ID",
|
|
36
38
|
"Records per page": "每页数据",
|
|
37
39
|
"Refresh": "刷新",
|
|
40
|
+
"Security event details": "安全事件详情",
|
|
38
41
|
"Submit": "提交",
|
|
42
|
+
"Tenant ID": "租户 ID",
|
|
43
|
+
"Tenant access denied": "租户访问被拒绝",
|
|
44
|
+
"Tenant impersonation": "租户冒用代入",
|
|
39
45
|
"Update": "编辑",
|
|
40
46
|
"Update record": "编辑数据",
|
|
41
47
|
"User": "用户",
|
|
@@ -26,6 +26,7 @@ var auditLogs_default = (0, import_server.defineCollection)({
|
|
|
26
26
|
group: "log"
|
|
27
27
|
},
|
|
28
28
|
name: "auditLogs",
|
|
29
|
+
tenancy: "tenantScoped",
|
|
29
30
|
createdBy: false,
|
|
30
31
|
updatedBy: false,
|
|
31
32
|
updatedAt: false,
|
|
@@ -48,6 +49,33 @@ var auditLogs_default = (0, import_server.defineCollection)({
|
|
|
48
49
|
type: "string",
|
|
49
50
|
name: "collectionName"
|
|
50
51
|
},
|
|
52
|
+
{
|
|
53
|
+
type: "string",
|
|
54
|
+
name: "tenantId",
|
|
55
|
+
index: true
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
type: "string",
|
|
59
|
+
name: "actorUserId",
|
|
60
|
+
index: true
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: "string",
|
|
64
|
+
name: "impersonatedTenantId",
|
|
65
|
+
index: true
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
type: "string",
|
|
69
|
+
name: "tenantContextSource"
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
type: "boolean",
|
|
73
|
+
name: "isTenantImpersonation"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
type: "json",
|
|
77
|
+
name: "details"
|
|
78
|
+
},
|
|
51
79
|
{
|
|
52
80
|
type: "belongsTo",
|
|
53
81
|
name: "collection",
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
export declare const LOG_TYPE_CREATE = "create";
|
|
2
2
|
export declare const LOG_TYPE_UPDATE = "update";
|
|
3
3
|
export declare const LOG_TYPE_DESTROY = "destroy";
|
|
4
|
+
export declare const AUDIT_TYPE_TENANT_ACCESS_DENIED = "tenant_access_denied";
|
|
5
|
+
export declare const AUDIT_TYPE_TENANT_CROSS_TENANT = "tenant_cross_tenant_attempt";
|
|
6
|
+
export declare const AUDIT_TYPE_TENANT_BULK_EXPORT = "tenant_bulk_export_alert";
|
|
7
|
+
export declare const AUDIT_TYPE_TENANT_IMPERSONATION = "tenant_impersonation";
|
|
8
|
+
export declare const EVENT_TENANT_SECURITY = "tenant.securityViolation";
|
|
9
|
+
export declare const BULK_EXPORT_THRESHOLD = 1000;
|
package/dist/server/constants.js
CHANGED
|
@@ -17,6 +17,12 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
var constants_exports = {};
|
|
19
19
|
__export(constants_exports, {
|
|
20
|
+
AUDIT_TYPE_TENANT_ACCESS_DENIED: () => AUDIT_TYPE_TENANT_ACCESS_DENIED,
|
|
21
|
+
AUDIT_TYPE_TENANT_BULK_EXPORT: () => AUDIT_TYPE_TENANT_BULK_EXPORT,
|
|
22
|
+
AUDIT_TYPE_TENANT_CROSS_TENANT: () => AUDIT_TYPE_TENANT_CROSS_TENANT,
|
|
23
|
+
AUDIT_TYPE_TENANT_IMPERSONATION: () => AUDIT_TYPE_TENANT_IMPERSONATION,
|
|
24
|
+
BULK_EXPORT_THRESHOLD: () => BULK_EXPORT_THRESHOLD,
|
|
25
|
+
EVENT_TENANT_SECURITY: () => EVENT_TENANT_SECURITY,
|
|
20
26
|
LOG_TYPE_CREATE: () => LOG_TYPE_CREATE,
|
|
21
27
|
LOG_TYPE_DESTROY: () => LOG_TYPE_DESTROY,
|
|
22
28
|
LOG_TYPE_UPDATE: () => LOG_TYPE_UPDATE
|
|
@@ -25,8 +31,20 @@ module.exports = __toCommonJS(constants_exports);
|
|
|
25
31
|
const LOG_TYPE_CREATE = "create";
|
|
26
32
|
const LOG_TYPE_UPDATE = "update";
|
|
27
33
|
const LOG_TYPE_DESTROY = "destroy";
|
|
34
|
+
const AUDIT_TYPE_TENANT_ACCESS_DENIED = "tenant_access_denied";
|
|
35
|
+
const AUDIT_TYPE_TENANT_CROSS_TENANT = "tenant_cross_tenant_attempt";
|
|
36
|
+
const AUDIT_TYPE_TENANT_BULK_EXPORT = "tenant_bulk_export_alert";
|
|
37
|
+
const AUDIT_TYPE_TENANT_IMPERSONATION = "tenant_impersonation";
|
|
38
|
+
const EVENT_TENANT_SECURITY = "tenant.securityViolation";
|
|
39
|
+
const BULK_EXPORT_THRESHOLD = 1e3;
|
|
28
40
|
// Annotate the CommonJS export names for ESM import in node:
|
|
29
41
|
0 && (module.exports = {
|
|
42
|
+
AUDIT_TYPE_TENANT_ACCESS_DENIED,
|
|
43
|
+
AUDIT_TYPE_TENANT_BULK_EXPORT,
|
|
44
|
+
AUDIT_TYPE_TENANT_CROSS_TENANT,
|
|
45
|
+
AUDIT_TYPE_TENANT_IMPERSONATION,
|
|
46
|
+
BULK_EXPORT_THRESHOLD,
|
|
47
|
+
EVENT_TENANT_SECURITY,
|
|
30
48
|
LOG_TYPE_CREATE,
|
|
31
49
|
LOG_TYPE_DESTROY,
|
|
32
50
|
LOG_TYPE_UPDATE
|
|
@@ -21,8 +21,8 @@ __export(after_create_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(after_create_exports);
|
|
23
23
|
var import_constants = require("../constants");
|
|
24
|
+
var import_audit_context = require("./audit-context");
|
|
24
25
|
async function afterCreate(model, options, plugin) {
|
|
25
|
-
var _a, _b, _c;
|
|
26
26
|
if (options.logging === false) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
@@ -31,7 +31,7 @@ async function afterCreate(model, options, plugin) {
|
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
const transaction = options.transaction;
|
|
34
|
-
const
|
|
34
|
+
const auditContext = (0, import_audit_context.getAuditContext)(options);
|
|
35
35
|
try {
|
|
36
36
|
const changes = [];
|
|
37
37
|
const changed = model.changed();
|
|
@@ -53,7 +53,12 @@ async function afterCreate(model, options, plugin) {
|
|
|
53
53
|
collectionName: model.constructor.name,
|
|
54
54
|
recordId: model.get(model.constructor.primaryKeyAttribute),
|
|
55
55
|
createdAt: model.get("createdAt"),
|
|
56
|
-
userId:
|
|
56
|
+
userId: auditContext.userId,
|
|
57
|
+
tenantId: auditContext.tenantId,
|
|
58
|
+
actorUserId: auditContext.actorUserId,
|
|
59
|
+
impersonatedTenantId: auditContext.impersonatedTenantId,
|
|
60
|
+
tenantContextSource: auditContext.tenantContextSource,
|
|
61
|
+
isTenantImpersonation: auditContext.isTenantImpersonation,
|
|
57
62
|
changes
|
|
58
63
|
};
|
|
59
64
|
plugin.sendSyncMessage(
|
|
@@ -21,14 +21,14 @@ __export(after_destroy_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(after_destroy_exports);
|
|
23
23
|
var import_constants = require("../constants");
|
|
24
|
+
var import_audit_context = require("./audit-context");
|
|
24
25
|
async function afterDestroy(model, options, plugin) {
|
|
25
|
-
var _a, _b, _c;
|
|
26
26
|
const { collection } = model.constructor;
|
|
27
27
|
if (!collection || !collection.options.logging) {
|
|
28
28
|
return;
|
|
29
29
|
}
|
|
30
30
|
const transaction = options.transaction;
|
|
31
|
-
const
|
|
31
|
+
const auditContext = (0, import_audit_context.getAuditContext)(options);
|
|
32
32
|
try {
|
|
33
33
|
const changes = [];
|
|
34
34
|
Object.keys(model.get()).forEach((key) => {
|
|
@@ -46,7 +46,12 @@ async function afterDestroy(model, options, plugin) {
|
|
|
46
46
|
type: import_constants.LOG_TYPE_DESTROY,
|
|
47
47
|
collectionName: model.constructor.name,
|
|
48
48
|
recordId: model.get(model.constructor.primaryKeyAttribute),
|
|
49
|
-
userId:
|
|
49
|
+
userId: auditContext.userId,
|
|
50
|
+
tenantId: auditContext.tenantId,
|
|
51
|
+
actorUserId: auditContext.actorUserId,
|
|
52
|
+
impersonatedTenantId: auditContext.impersonatedTenantId,
|
|
53
|
+
tenantContextSource: auditContext.tenantContextSource,
|
|
54
|
+
isTenantImpersonation: auditContext.isTenantImpersonation,
|
|
50
55
|
changes
|
|
51
56
|
};
|
|
52
57
|
plugin.sendSyncMessage(
|
|
@@ -21,8 +21,8 @@ __export(after_update_exports, {
|
|
|
21
21
|
});
|
|
22
22
|
module.exports = __toCommonJS(after_update_exports);
|
|
23
23
|
var import_constants = require("../constants");
|
|
24
|
+
var import_audit_context = require("./audit-context");
|
|
24
25
|
async function afterUpdate(model, options, plugin) {
|
|
25
|
-
var _a, _b, _c;
|
|
26
26
|
const { collection } = model.constructor;
|
|
27
27
|
if (!collection || !collection.options.logging) {
|
|
28
28
|
return;
|
|
@@ -32,10 +32,10 @@ async function afterUpdate(model, options, plugin) {
|
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
const transaction = options.transaction;
|
|
35
|
-
const
|
|
35
|
+
const auditContext = (0, import_audit_context.getAuditContext)(options);
|
|
36
36
|
const changes = [];
|
|
37
37
|
changed.forEach((key) => {
|
|
38
|
-
var
|
|
38
|
+
var _a;
|
|
39
39
|
const field = collection.findField((field2) => {
|
|
40
40
|
return field2.name === key || field2.options.field === key;
|
|
41
41
|
});
|
|
@@ -48,7 +48,7 @@ async function afterUpdate(model, options, plugin) {
|
|
|
48
48
|
if ((before === null || before === void 0) && (after === null || after === void 0)) {
|
|
49
49
|
return;
|
|
50
50
|
}
|
|
51
|
-
if (field.type === "bigInt" && ((
|
|
51
|
+
if (field.type === "bigInt" && ((_a = field.options) == null ? void 0 : _a.isForeignKey) && +before === +after) {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
54
|
changes.push({
|
|
@@ -67,7 +67,12 @@ async function afterUpdate(model, options, plugin) {
|
|
|
67
67
|
collectionName: model.constructor.name,
|
|
68
68
|
recordId: model.get(model.constructor.primaryKeyAttribute),
|
|
69
69
|
createdAt: model.get("updatedAt"),
|
|
70
|
-
userId:
|
|
70
|
+
userId: auditContext.userId,
|
|
71
|
+
tenantId: auditContext.tenantId,
|
|
72
|
+
actorUserId: auditContext.actorUserId,
|
|
73
|
+
impersonatedTenantId: auditContext.impersonatedTenantId,
|
|
74
|
+
tenantContextSource: auditContext.tenantContextSource,
|
|
75
|
+
isTenantImpersonation: auditContext.isTenantImpersonation,
|
|
71
76
|
changes
|
|
72
77
|
};
|
|
73
78
|
plugin.sendSyncMessage(
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides the get audit context helper for this module.
|
|
3
|
+
*/
|
|
4
|
+
export declare function getAuditContext(options: any): {
|
|
5
|
+
userId: any;
|
|
6
|
+
tenantId: any;
|
|
7
|
+
actorUserId: any;
|
|
8
|
+
impersonatedTenantId: any;
|
|
9
|
+
tenantContextSource: any;
|
|
10
|
+
isTenantImpersonation: boolean;
|
|
11
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var audit_context_exports = {};
|
|
19
|
+
__export(audit_context_exports, {
|
|
20
|
+
getAuditContext: () => getAuditContext
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(audit_context_exports);
|
|
23
|
+
function getAuditContext(options) {
|
|
24
|
+
var _a, _b, _c;
|
|
25
|
+
const state = (_a = options == null ? void 0 : options.context) == null ? void 0 : _a.state;
|
|
26
|
+
const currentUserId = (_b = state == null ? void 0 : state.currentUser) == null ? void 0 : _b.id;
|
|
27
|
+
return {
|
|
28
|
+
userId: currentUserId,
|
|
29
|
+
tenantId: ((_c = state == null ? void 0 : state.currentTenant) == null ? void 0 : _c.id) ?? (state == null ? void 0 : state.currentTenantId),
|
|
30
|
+
actorUserId: (state == null ? void 0 : state.actorUserId) ?? currentUserId,
|
|
31
|
+
impersonatedTenantId: state == null ? void 0 : state.impersonatedTenantId,
|
|
32
|
+
tenantContextSource: state == null ? void 0 : state.tenantContextSource,
|
|
33
|
+
isTenantImpersonation: !!(state == null ? void 0 : state.isTenantImpersonation)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
getAuditContext
|
|
39
|
+
});
|
package/dist/server/index.js
CHANGED
|
@@ -34,6 +34,8 @@ var import_node_path = __toESM(require("node:path"));
|
|
|
34
34
|
var import_node_worker_threads = require("node:worker_threads");
|
|
35
35
|
var import_server = require("@tego/server");
|
|
36
36
|
var import_hooks = require("./hooks");
|
|
37
|
+
var import_normalize_audit_log_values = require("./normalize-audit-log-values");
|
|
38
|
+
var import_security_event_listener = require("./security-event-listener");
|
|
37
39
|
class PluginActionLogs extends import_server.Plugin {
|
|
38
40
|
constructor() {
|
|
39
41
|
super(...arguments);
|
|
@@ -46,11 +48,31 @@ class PluginActionLogs extends import_server.Plugin {
|
|
|
46
48
|
if (!import_node_worker_threads.isMainThread) {
|
|
47
49
|
this.addAuditListener();
|
|
48
50
|
}
|
|
51
|
+
(0, import_security_event_listener.registerSecurityEventListener)(this);
|
|
49
52
|
}
|
|
50
53
|
async beforeLoad() {
|
|
51
54
|
if (import_node_worker_threads.isMainThread) {
|
|
52
55
|
this.addAuditListener();
|
|
53
56
|
}
|
|
57
|
+
this.app.on("beforeDestroy", async () => {
|
|
58
|
+
var _a, _b, _c;
|
|
59
|
+
if (this.logsTimer) {
|
|
60
|
+
clearTimeout(this.logsTimer);
|
|
61
|
+
this.logsTimer = null;
|
|
62
|
+
}
|
|
63
|
+
if (this.logsBuffer.length > 0) {
|
|
64
|
+
const pending = [...this.logsBuffer];
|
|
65
|
+
this.logsBuffer = [];
|
|
66
|
+
try {
|
|
67
|
+
await this.workerCreateAuditLog(pending);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
(_c = (_b = (_a = this.app) == null ? void 0 : _a.logger) == null ? void 0 : _b.warn) == null ? void 0 : _c.call(_b, "Failed to flush pending audit logs before destroy", {
|
|
70
|
+
error,
|
|
71
|
+
pendingCount: pending.length
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
54
76
|
}
|
|
55
77
|
async addAuditListener() {
|
|
56
78
|
this.db.on("afterCreate", (model, options) => {
|
|
@@ -72,7 +94,16 @@ class PluginActionLogs extends import_server.Plugin {
|
|
|
72
94
|
}
|
|
73
95
|
});
|
|
74
96
|
this.app.acl.allow("auditLogs", ["list", "get"], "loggedIn");
|
|
75
|
-
this.app.
|
|
97
|
+
this.app.resourcer.use(
|
|
98
|
+
async (ctx, next) => {
|
|
99
|
+
var _a;
|
|
100
|
+
if (((_a = ctx.action) == null ? void 0 : _a.resourceName) === "auditChanges" && ctx.action.actionName === "get" && ctx.state.currentRole !== "root") {
|
|
101
|
+
ctx.throw(403, "Direct audit change access is not allowed");
|
|
102
|
+
}
|
|
103
|
+
await next();
|
|
104
|
+
},
|
|
105
|
+
{ tag: "auditChangesReadBoundary", after: "acl" }
|
|
106
|
+
);
|
|
76
107
|
}
|
|
77
108
|
async handleSyncMessage(message) {
|
|
78
109
|
if ((message == null ? void 0 : message.type) === "auditLog") {
|
|
@@ -109,8 +140,13 @@ class PluginActionLogs extends import_server.Plugin {
|
|
|
109
140
|
const auditLogRepo = this.db.getRepository("auditLogs");
|
|
110
141
|
const auditChangeRepo = this.db.getRepository("auditChanges");
|
|
111
142
|
const now = /* @__PURE__ */ new Date();
|
|
112
|
-
|
|
113
|
-
|
|
143
|
+
const auditLogValues = values.map(
|
|
144
|
+
(value) => (0, import_normalize_audit_log_values.normalizeAuditLogValues)({
|
|
145
|
+
...value,
|
|
146
|
+
createdAt: now
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
const insertedLogs = await auditLogRepo.model.bulkCreate(auditLogValues, {
|
|
114
150
|
individualHooks: false,
|
|
115
151
|
// 禁用逐条钩子调用
|
|
116
152
|
transaction,
|
|
@@ -120,7 +156,7 @@ class PluginActionLogs extends import_server.Plugin {
|
|
|
120
156
|
});
|
|
121
157
|
const changes = [];
|
|
122
158
|
insertedLogs.forEach((log, index) => {
|
|
123
|
-
const value =
|
|
159
|
+
const value = auditLogValues[index];
|
|
124
160
|
if (!value.changes) {
|
|
125
161
|
return;
|
|
126
162
|
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var add_tenant_fields_exports = {};
|
|
19
|
+
__export(add_tenant_fields_exports, {
|
|
20
|
+
default: () => AddTenantFieldsToAuditLogsMigration
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(add_tenant_fields_exports);
|
|
23
|
+
var import_server = require("@tego/server");
|
|
24
|
+
function normalizeTableName(table) {
|
|
25
|
+
return typeof table === "string" ? table : (table == null ? void 0 : table.tableName) || (table == null ? void 0 : table.name);
|
|
26
|
+
}
|
|
27
|
+
function getModel(db, collectionName) {
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
try {
|
|
30
|
+
return ((_b = (_a = db.getCollection) == null ? void 0 : _a.call(db, collectionName)) == null ? void 0 : _b.model) || ((_c = db.getModel) == null ? void 0 : _c.call(db, collectionName)) || null;
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function getPhysicalTableName(db, collectionName) {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const model = getModel(db, collectionName);
|
|
38
|
+
const modelTableName = normalizeTableName(((_a = model == null ? void 0 : model.getTableName) == null ? void 0 : _a.call(model)) || (model == null ? void 0 : model.tableName));
|
|
39
|
+
return modelTableName || (((_b = db.options) == null ? void 0 : _b.underscored) ? (0, import_server.snakeCase)(collectionName) : collectionName);
|
|
40
|
+
}
|
|
41
|
+
function getPhysicalColumnName(db, collectionName, attributeName) {
|
|
42
|
+
var _a, _b, _c, _d;
|
|
43
|
+
const model = getModel(db, collectionName);
|
|
44
|
+
const attribute = ((_b = (_a = model == null ? void 0 : model.getAttributes) == null ? void 0 : _a.call(model)) == null ? void 0 : _b[attributeName]) || ((_c = model == null ? void 0 : model.rawAttributes) == null ? void 0 : _c[attributeName]);
|
|
45
|
+
return (attribute == null ? void 0 : attribute.field) || (((_d = db.options) == null ? void 0 : _d.underscored) ? (0, import_server.snakeCase)(attributeName) : attributeName);
|
|
46
|
+
}
|
|
47
|
+
async function hasTable(queryInterface, tableName) {
|
|
48
|
+
const tables = await queryInterface.showAllTables();
|
|
49
|
+
return tables.map(normalizeTableName).includes(tableName);
|
|
50
|
+
}
|
|
51
|
+
async function addIndexIfMissing(queryInterface, tableName, columnName, indexName) {
|
|
52
|
+
const indexes = await queryInterface.showIndex(tableName);
|
|
53
|
+
const exists = indexes.some((index) => {
|
|
54
|
+
const fields = (index.fields || []).map((field) => field.attribute || field.name).filter(Boolean);
|
|
55
|
+
return index.name === indexName || fields.length === 1 && fields[0] === columnName;
|
|
56
|
+
});
|
|
57
|
+
if (!exists) {
|
|
58
|
+
await queryInterface.addIndex(tableName, [columnName], { name: indexName });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
class AddTenantFieldsToAuditLogsMigration extends import_server.Migration {
|
|
62
|
+
constructor() {
|
|
63
|
+
super(...arguments);
|
|
64
|
+
this.on = "afterLoad";
|
|
65
|
+
this.appVersion = "<1.6.23";
|
|
66
|
+
}
|
|
67
|
+
async up() {
|
|
68
|
+
var _a, _b, _c;
|
|
69
|
+
const queryInterface = this.db.sequelize.getQueryInterface();
|
|
70
|
+
const collectionName = "auditLogs";
|
|
71
|
+
const tableName = getPhysicalTableName(this.db, collectionName);
|
|
72
|
+
if (!await hasTable(queryInterface, tableName)) {
|
|
73
|
+
(_c = (_b = (_a = this.app) == null ? void 0 : _a.logger) == null ? void 0 : _b.info) == null ? void 0 : _c.call(_b, `[migration skipped] table ${tableName} does not exist`);
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
const table = await queryInterface.describeTable(tableName);
|
|
77
|
+
const columns = [
|
|
78
|
+
["tenantId", import_server.DataTypes.STRING],
|
|
79
|
+
["actorUserId", import_server.DataTypes.STRING],
|
|
80
|
+
["impersonatedTenantId", import_server.DataTypes.STRING],
|
|
81
|
+
["tenantContextSource", import_server.DataTypes.STRING],
|
|
82
|
+
["isTenantImpersonation", import_server.DataTypes.BOOLEAN]
|
|
83
|
+
];
|
|
84
|
+
for (const [attributeName, type] of columns) {
|
|
85
|
+
const columnName = getPhysicalColumnName(this.db, collectionName, attributeName);
|
|
86
|
+
if (!table[columnName]) {
|
|
87
|
+
await queryInterface.addColumn(tableName, columnName, {
|
|
88
|
+
type,
|
|
89
|
+
allowNull: true
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
await addIndexIfMissing(
|
|
94
|
+
queryInterface,
|
|
95
|
+
tableName,
|
|
96
|
+
getPhysicalColumnName(this.db, collectionName, "tenantId"),
|
|
97
|
+
"audit_logs_tenant_id"
|
|
98
|
+
);
|
|
99
|
+
await addIndexIfMissing(
|
|
100
|
+
queryInterface,
|
|
101
|
+
tableName,
|
|
102
|
+
getPhysicalColumnName(this.db, collectionName, "actorUserId"),
|
|
103
|
+
"audit_logs_actor_user_id"
|
|
104
|
+
);
|
|
105
|
+
await addIndexIfMissing(
|
|
106
|
+
queryInterface,
|
|
107
|
+
tableName,
|
|
108
|
+
getPhysicalColumnName(this.db, collectionName, "impersonatedTenantId"),
|
|
109
|
+
"audit_logs_impersonated_tenant_id"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var add_security_event_details_exports = {};
|
|
19
|
+
__export(add_security_event_details_exports, {
|
|
20
|
+
default: () => AddSecurityEventDetailsToAuditLogsMigration
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(add_security_event_details_exports);
|
|
23
|
+
var import_server = require("@tego/server");
|
|
24
|
+
function normalizeTableName(table) {
|
|
25
|
+
return typeof table === "string" ? table : (table == null ? void 0 : table.tableName) || (table == null ? void 0 : table.name);
|
|
26
|
+
}
|
|
27
|
+
async function hasTable(queryInterface, tableName) {
|
|
28
|
+
const tables = await queryInterface.showAllTables();
|
|
29
|
+
return tables.map(normalizeTableName).includes(tableName);
|
|
30
|
+
}
|
|
31
|
+
class AddSecurityEventDetailsToAuditLogsMigration extends import_server.Migration {
|
|
32
|
+
constructor() {
|
|
33
|
+
super(...arguments);
|
|
34
|
+
this.on = "afterLoad";
|
|
35
|
+
this.appVersion = "<1.6.24";
|
|
36
|
+
}
|
|
37
|
+
async up() {
|
|
38
|
+
var _a, _b, _c;
|
|
39
|
+
const queryInterface = this.db.sequelize.getQueryInterface();
|
|
40
|
+
const tableName = "auditLogs";
|
|
41
|
+
if (!await hasTable(queryInterface, tableName)) {
|
|
42
|
+
(_c = (_b = (_a = this.app) == null ? void 0 : _a.logger) == null ? void 0 : _b.info) == null ? void 0 : _c.call(_b, `[migration skipped] table ${tableName} does not exist`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const table = await queryInterface.describeTable(tableName);
|
|
46
|
+
if (!table.details) {
|
|
47
|
+
await queryInterface.addColumn(tableName, "details", {
|
|
48
|
+
type: import_server.DataTypes.JSON,
|
|
49
|
+
allowNull: true
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provides the normalize actor user id helper for this module.
|
|
3
|
+
*/
|
|
4
|
+
export declare function normalizeActorUserId(actorUserId: unknown): string;
|
|
5
|
+
/**
|
|
6
|
+
* Provides the normalize audit log values helper for this module.
|
|
7
|
+
*/
|
|
8
|
+
export declare function normalizeAuditLogValues<T extends Record<string, unknown>>(values: T): T;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var normalize_audit_log_values_exports = {};
|
|
19
|
+
__export(normalize_audit_log_values_exports, {
|
|
20
|
+
normalizeActorUserId: () => normalizeActorUserId,
|
|
21
|
+
normalizeAuditLogValues: () => normalizeAuditLogValues
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(normalize_audit_log_values_exports);
|
|
24
|
+
function normalizeActorUserId(actorUserId) {
|
|
25
|
+
return actorUserId == null ? null : String(actorUserId);
|
|
26
|
+
}
|
|
27
|
+
function normalizeAuditLogValues(values) {
|
|
28
|
+
return {
|
|
29
|
+
...values,
|
|
30
|
+
actorUserId: normalizeActorUserId(values.actorUserId)
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
normalizeActorUserId,
|
|
36
|
+
normalizeAuditLogValues
|
|
37
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface TenantSecurityEvent {
|
|
2
|
+
type: string;
|
|
3
|
+
userId?: number | string;
|
|
4
|
+
actorUserId?: number | string;
|
|
5
|
+
tenantId?: string;
|
|
6
|
+
collectionName?: string;
|
|
7
|
+
action?: string;
|
|
8
|
+
impersonatedTenantId?: string | null;
|
|
9
|
+
tenantContextSource?: string | null;
|
|
10
|
+
isTenantImpersonation?: boolean;
|
|
11
|
+
details?: Record<string, any>;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Listens for tenant security violation events emitted on the Application
|
|
15
|
+
* (EventEmitter) and writes them directly to the auditLogs table.
|
|
16
|
+
*
|
|
17
|
+
* Security events bypass the normal model-hook debounce pipeline because
|
|
18
|
+
* they fire on rejection paths (low volume, high importance).
|
|
19
|
+
*
|
|
20
|
+
* Idempotent: calling multiple times on the same app instance will not
|
|
21
|
+
* register duplicate listeners.
|
|
22
|
+
*
|
|
23
|
+
* The tenant module stores a back-reference (ctx.app.__application) so that
|
|
24
|
+
* setCurrentTenant / tenantResourceGuard can emit directly on the
|
|
25
|
+
* Application instead of the Koa instance.
|
|
26
|
+
*/
|
|
27
|
+
export declare function registerSecurityEventListener(plugin: {
|
|
28
|
+
app: any;
|
|
29
|
+
db: any;
|
|
30
|
+
}): void;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var security_event_listener_exports = {};
|
|
19
|
+
__export(security_event_listener_exports, {
|
|
20
|
+
registerSecurityEventListener: () => registerSecurityEventListener
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(security_event_listener_exports);
|
|
23
|
+
var import_constants = require("./constants");
|
|
24
|
+
var import_normalize_audit_log_values = require("./normalize-audit-log-values");
|
|
25
|
+
const REGISTERED_SYMBOL = Symbol.for("auditLogs:securityEventListenerRegistered");
|
|
26
|
+
const PENDING_SYMBOL = Symbol.for("auditLogs:securityEventListenerPending");
|
|
27
|
+
const SQLITE_BUSY_RETRY_DELAYS = [50, 100, 200];
|
|
28
|
+
function sleep(ms) {
|
|
29
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
30
|
+
}
|
|
31
|
+
function isSqliteBusyError(error) {
|
|
32
|
+
var _a, _b;
|
|
33
|
+
return (error == null ? void 0 : error.name) === "SequelizeTimeoutError" || ((_a = error == null ? void 0 : error.original) == null ? void 0 : _a.code) === "SQLITE_BUSY" || ((_b = error == null ? void 0 : error.parent) == null ? void 0 : _b.code) === "SQLITE_BUSY" || String((error == null ? void 0 : error.message) || "").includes("SQLITE_BUSY");
|
|
34
|
+
}
|
|
35
|
+
async function createSecurityAuditLog(plugin, values) {
|
|
36
|
+
const auditLogRepo = plugin.db.getRepository("auditLogs");
|
|
37
|
+
for (let attempt = 0; ; attempt++) {
|
|
38
|
+
try {
|
|
39
|
+
await auditLogRepo.model.create(values, { hooks: false });
|
|
40
|
+
return;
|
|
41
|
+
} catch (error) {
|
|
42
|
+
const retryDelay = SQLITE_BUSY_RETRY_DELAYS[attempt];
|
|
43
|
+
if (!isSqliteBusyError(error) || retryDelay == null) {
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
await sleep(retryDelay);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function registerSecurityEventListener(plugin) {
|
|
51
|
+
if (plugin.app[REGISTERED_SYMBOL]) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
plugin.app[REGISTERED_SYMBOL] = true;
|
|
55
|
+
plugin.app[PENDING_SYMBOL] = plugin.app[PENDING_SYMBOL] || Promise.resolve();
|
|
56
|
+
const persistEvent = async (event) => {
|
|
57
|
+
var _a, _b, _c, _d;
|
|
58
|
+
try {
|
|
59
|
+
const isImpersonation = event.type === import_constants.AUDIT_TYPE_TENANT_IMPERSONATION;
|
|
60
|
+
const details = event.action ? { ...event.details, action: event.action } : event.details || null;
|
|
61
|
+
await createSecurityAuditLog(plugin, {
|
|
62
|
+
type: event.type,
|
|
63
|
+
collectionName: event.collectionName || null,
|
|
64
|
+
recordId: null,
|
|
65
|
+
userId: event.userId ?? null,
|
|
66
|
+
tenantId: event.tenantId ?? null,
|
|
67
|
+
actorUserId: (0, import_normalize_audit_log_values.normalizeActorUserId)(event.actorUserId ?? event.userId),
|
|
68
|
+
impersonatedTenantId: isImpersonation ? event.impersonatedTenantId ?? ((_a = event.details) == null ? void 0 : _a.impersonatedTenantId) ?? event.tenantId ?? null : event.impersonatedTenantId ?? null,
|
|
69
|
+
tenantContextSource: isImpersonation ? event.tenantContextSource ?? "platformImpersonation" : event.tenantContextSource ?? null,
|
|
70
|
+
isTenantImpersonation: isImpersonation ? true : event.isTenantImpersonation ?? false,
|
|
71
|
+
details
|
|
72
|
+
});
|
|
73
|
+
} catch (error) {
|
|
74
|
+
(_d = (_c = (_b = plugin.app) == null ? void 0 : _b.logger) == null ? void 0 : _c.error) == null ? void 0 : _d.call(_c, "Failed to persist tenant security audit event", {
|
|
75
|
+
error,
|
|
76
|
+
event: {
|
|
77
|
+
type: event.type,
|
|
78
|
+
userId: event.userId,
|
|
79
|
+
actorUserId: event.actorUserId,
|
|
80
|
+
tenantId: event.tenantId,
|
|
81
|
+
collectionName: event.collectionName,
|
|
82
|
+
action: event.action,
|
|
83
|
+
impersonatedTenantId: event.impersonatedTenantId,
|
|
84
|
+
tenantContextSource: event.tenantContextSource,
|
|
85
|
+
isTenantImpersonation: event.isTenantImpersonation
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const handler = (event) => {
|
|
91
|
+
const pending = plugin.app[PENDING_SYMBOL].catch(() => void 0).then(() => persistEvent(event));
|
|
92
|
+
plugin.app[PENDING_SYMBOL] = pending.catch(() => void 0);
|
|
93
|
+
return pending;
|
|
94
|
+
};
|
|
95
|
+
plugin.app.on(import_constants.EVENT_TENANT_SECURITY, handler);
|
|
96
|
+
plugin.app.on("beforeDestroy", async () => {
|
|
97
|
+
await plugin.app[PENDING_SYMBOL];
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
101
|
+
0 && (module.exports = {
|
|
102
|
+
registerSecurityEventListener
|
|
103
|
+
});
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tachybase/plugin-audit-logs",
|
|
3
3
|
"displayName": "Audit logs",
|
|
4
|
-
"version": "1.6.
|
|
4
|
+
"version": "1.6.26",
|
|
5
5
|
"description": "Audit logs.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"System management"
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"antd": "5.22.5",
|
|
27
27
|
"react": "18.3.1",
|
|
28
28
|
"react-i18next": "16.2.1",
|
|
29
|
-
"@tachybase/client": "1.6.
|
|
29
|
+
"@tachybase/client": "1.6.26"
|
|
30
30
|
},
|
|
31
31
|
"description.zh-CN": "审计日志。",
|
|
32
32
|
"displayName.zh-CN": "审计日志",
|