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 +100 -1
- package/db/user-info.cds +9 -8
- package/dist/handlers.js +21 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# cap-user-info
|
|
2
2
|
|
|
3
|
-
CDS plugin that
|
|
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
|
+

|
|
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
|
+

|
|
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 {
|
|
1
|
+
using {managed} from '@sap/cds/common';
|
|
2
|
+
|
|
2
3
|
namespace cap.userinfo;
|
|
3
4
|
|
|
4
|
-
@UI.FieldGroup
|
|
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
|
|
21
|
+
Target: '@UI.FieldGroup',
|
|
21
22
|
Label : 'Contact Details',
|
|
22
23
|
}]
|
|
23
|
-
@UI.HeaderInfo
|
|
24
|
+
@UI.HeaderInfo : {
|
|
24
25
|
ImageUrl : '',
|
|
25
|
-
TypeImageUrl: 'sap-icon://
|
|
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
|
-
|
|
51
|
+
on _toCreatedUserInfo.ID = $self.createdBy;
|
|
51
52
|
_toModifiedUserInfo : Association to one UserInfo
|
|
52
|
-
|
|
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
|
|
12
|
-
if (!
|
|
12
|
+
const entieies = entity?.elements;
|
|
13
|
+
if (!entieies)
|
|
13
14
|
return false;
|
|
14
|
-
return Boolean(
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
});
|