cap-user-info 0.1.1 → 0.1.4

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # cap-user-info
2
2
 
3
- CDS plugin that tracks created/modified user details on managed entities.
3
+ CDS plugin that adds user details on managed entities.
4
4
 
5
5
  ## Install
6
6
 
@@ -10,6 +10,25 @@ npm install cap-user-info
10
10
 
11
11
  ## Usage
12
12
 
13
+ The userinfo has the following properties by default that is added to the database
14
+ ``` cds
15
+ entity UserInfo {
16
+ @UI.Hidden
17
+ key ID : UUID;
18
+
19
+ @assert.unique: true @title: 'Email Address'
20
+ @Communication: {IsEmailAddress: true}
21
+ Email : String;
22
+
23
+ GivenName : String @title: 'Given Name';
24
+ FamilyName : String @title: 'Family Name';
25
+ FullName : String = concat(
26
+ GivenName, ' ', FamilyName
27
+ );
28
+ }
29
+ ```
30
+
31
+ Import it into your cds file.
13
32
  ```cds
14
33
  using { UserTracked, UserInfo } from 'cap-user-info';
15
34
 
@@ -24,6 +43,10 @@ handler UPSERTs the current user (`req.user`) into `UserInfo`. The
24
43
  associations `_toCreatedUserInfo` / `_toModifiedUserInfo` resolve via
25
44
  `createdBy` / `modifiedBy`.
26
45
 
46
+ The fields for createdBy and modifiedBy will automatically be shown as links with a quickview with the user details.
47
+ ![alt text](image-1.png)
48
+
49
+
27
50
  ## How it works
28
51
 
29
52
  `UserTracked` extends `managed`, so consuming entities automatically
@@ -37,3 +60,79 @@ aspect UserTracked : managed { ... }
37
60
 
38
61
  This means no extra `managed` declaration is required on the consuming
39
62
  entity — including `UserTracked` is enough.
63
+
64
+ ## Using the plugin for other purposes
65
+
66
+ Add a field to your entity and a association
67
+
68
+ ```cds
69
+
70
+ using { UserTracked, UserInfo } from 'cap-user-info';
71
+
72
+ entity MyEntity : cuid, UserTracked {
73
+ // The cds.on.insert is only to insert the userid automatically, otherwise handle it via code.
74
+ Responsible: User @cds.on.insert: $user.id;,
75
+ _toResponsibleUser: association to one UserInfo on _toResponsibleUser.ID = $self.Responsible
76
+ }
77
+
78
+ ```
79
+
80
+ Then the quickview will automatically be active
81
+ ![alt text](image-2.png)
82
+
83
+ ## Extending the quickview
84
+
85
+ You can extend the UserInfo to add more data into the quickview by adding to the fieldgroup in a cds file.
86
+
87
+ ``` cds
88
+ // Change the quickview
89
+ extend cap.userinfo.UserInfo with
90
+ @UI.FieldGroup: {Data: [
91
+ // Leave the original properties
92
+ {
93
+ $Type: 'UI.DataField',
94
+ Value: GivenName
95
+ },
96
+ {
97
+ $Type: 'UI.DataField',
98
+ Value: FamilyName
99
+ },
100
+ {
101
+ $Type: 'UI.DataField',
102
+ Value: Email
103
+ },
104
+ // your new field
105
+ {
106
+ $Type: 'UI.DataField',
107
+ Value: Department
108
+ },
109
+ ]}
110
+
111
+ //Change the
112
+ @UI.HeaderInfo : {
113
+ ImageUrl : '',
114
+ TypeImageUrl: 'sap-icon://employee',
115
+ Title : {
116
+ Value: FullName,
117
+ },
118
+ TypeName : '',
119
+ }
120
+ {
121
+ // your new field iin the entity
122
+ Department : String @title : 'Department';
123
+ }
124
+ ```
125
+
126
+ Then register your event handler to populate the data. It's important this piece of code isn't added within your srv.init method. It needs to be in the root context.
127
+ ``` javascript
128
+ cds.on("served", () => {
129
+ const { db } = cds.services;
130
+ const { UserInfo } = cds.entities("cap.userinfo");
131
+
132
+ //Register the handler for the Upsert
133
+ db.before("UPSERT", UserInfo, async (req) => {
134
+ //Change the data
135
+ req.data.Department = "Admin";
136
+ });
137
+ });
138
+ ```
package/db/user-info.cds CHANGED
@@ -1,7 +1,8 @@
1
- using { managed } from '@sap/cds/common';
1
+ using {managed} from '@sap/cds/common';
2
+
2
3
  namespace cap.userinfo;
3
4
 
4
- @UI.FieldGroup #contactDetails: {Data: [
5
+ @UI.FieldGroup : {Data: [
5
6
  {
6
7
  $Type: 'UI.DataField',
7
8
  Value: GivenName,
@@ -15,14 +16,14 @@ namespace cap.userinfo;
15
16
  Value: Email,
16
17
  }
17
18
  ]}
18
- @UI.QuickViewFacets : [{
19
+ @UI.QuickViewFacets: [{
19
20
  $Type : 'UI.ReferenceFacet',
20
- Target: '@UI.FieldGroup#contactDetails',
21
+ Target: '@UI.FieldGroup',
21
22
  Label : 'Contact Details',
22
23
  }]
23
- @UI.HeaderInfo : {
24
+ @UI.HeaderInfo : {
24
25
  ImageUrl : '',
25
- TypeImageUrl: 'sap-icon://customer',
26
+ TypeImageUrl: 'sap-icon://avatar',
26
27
  Title : {
27
28
  Label: 'Name',
28
29
  Value: FullName,
@@ -47,7 +48,7 @@ entity UserInfo {
47
48
 
48
49
  aspect UserTracked : managed {
49
50
  _toCreatedUserInfo : Association to one UserInfo
50
- on _toCreatedUserInfo.ID = $self.createdBy;
51
+ on _toCreatedUserInfo.ID = $self.createdBy;
51
52
  _toModifiedUserInfo : Association to one UserInfo
52
- on _toModifiedUserInfo.ID = $self.modifiedBy;
53
+ on _toModifiedUserInfo.ID = $self.modifiedBy;
53
54
  }
package/dist/handlers.js CHANGED
@@ -7,16 +7,19 @@ exports.hasUserTrackedAspect = hasUserTrackedAspect;
7
7
  exports.registerHandlers = registerHandlers;
8
8
  const cds_1 = __importDefault(require("@sap/cds"));
9
9
  const UPSERTED_FLAG = Symbol.for("cap-user-info.upserted-this-tx");
10
+ const userInfoLogger = cds_1.default.log("cap.userinfo");
10
11
  function hasUserTrackedAspect(entity) {
11
- const els = entity?.elements;
12
- if (!els)
12
+ const entieies = entity?.elements;
13
+ if (!entieies)
13
14
  return false;
14
- return Boolean(els._toCreatedUserInfo && els._toModifiedUserInfo);
15
+ return Boolean(entieies._toCreatedUserInfo && entieies._toModifiedUserInfo);
15
16
  }
16
17
  async function upsertUserInfo(req) {
17
18
  const user = req.user;
18
- if (!user?.id || user.is("system-user") || user._is_anonymous)
19
+ if (!user?.id || user.is("system-user") || user._is_anonymous) {
20
+ userInfoLogger.debug(`Skipping user info upsert for system or anonymous user: ${user?.id}`);
19
21
  return;
22
+ }
20
23
  const ctx = cds_1.default.context;
21
24
  if (ctx && ctx[UPSERTED_FLAG])
22
25
  return;
@@ -25,21 +28,29 @@ async function upsertUserInfo(req) {
25
28
  const { UserInfo } = cds_1.default.entities("cap.userinfo");
26
29
  let attr = user.attr ?? {};
27
30
  if (Object.keys(attr).length === 0) {
31
+ userInfoLogger.debug(`User ${user.id} has no attr property, using dummy values for user info upsert`);
28
32
  attr.email = "Dummy@example.com";
29
33
  attr.givenName = user.id || "FirstName";
30
34
  attr.familyName = "LastName";
31
35
  }
32
- await UPSERT.into(UserInfo).entries({
33
- ID: user.id,
34
- Email: attr.email,
35
- GivenName: attr.givenName,
36
- FamilyName: attr.familyName,
37
- });
36
+ userInfoLogger.debug(`Upserting user info for user ${user.id}: ${JSON.stringify(attr)}`);
37
+ try {
38
+ await UPSERT.into(UserInfo).entries({
39
+ ID: user.id,
40
+ Email: attr.email,
41
+ GivenName: attr.givenName,
42
+ FamilyName: attr.familyName,
43
+ });
44
+ }
45
+ catch (error) {
46
+ userInfoLogger.error(`Failed to upsert user info for user ${user.id}: ${error.message}`);
47
+ }
38
48
  }
39
49
  function registerHandlers(srv) {
40
50
  const tracked = [...srv.entities].filter(hasUserTrackedAspect);
41
51
  if (tracked.length === 0)
42
52
  return;
53
+ userInfoLogger.debug(`Registering user info handlers for entities: ${tracked.map((e) => e.name).join(", ")}`);
43
54
  srv.after(["CREATE", "UPDATE"], tracked, async (_data, req) => {
44
55
  await upsertUserInfo(req);
45
56
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cap-user-info",
3
- "version": "0.1.1",
3
+ "version": "0.1.4",
4
4
  "description": "CDS plugin: track created/modified user details on managed entities",
5
5
  "main": "cds-plugin.js",
6
6
  "repository": {