@cocreate/users 1.34.1 → 1.35.0
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/CHANGELOG.md +17 -0
- package/docs/index.html +0 -5
- package/package.json +1 -1
- package/src/client.js +106 -3
- package/src/server.js +126 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,20 @@
|
|
|
1
|
+
# [1.35.0](https://github.com/CoCreate-app/CoCreate-users/compare/v1.34.2...v1.35.0) (2024-02-13)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* acceptInvite ([4b3db33](https://github.com/CoCreate-app/CoCreate-users/commit/4b3db33c2057968f8b37b9f618de7120a4b6f36d))
|
|
7
|
+
* acceptUser ([45c6869](https://github.com/CoCreate-app/CoCreate-users/commit/45c68699f5d978f02b6f9d550a04b853da2d64f5))
|
|
8
|
+
* inviteUser function ([593d9ad](https://github.com/CoCreate-app/CoCreate-users/commit/593d9add42568a0fa87060595daffdbee662212f))
|
|
9
|
+
|
|
10
|
+
## [1.34.2](https://github.com/CoCreate-app/CoCreate-users/compare/v1.34.1...v1.34.2) (2024-02-05)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Bug Fixes
|
|
14
|
+
|
|
15
|
+
* hostname selector ([3b6d38d](https://github.com/CoCreate-app/CoCreate-users/commit/3b6d38d74a09cf72ff5440e2dc1647c5bc078675))
|
|
16
|
+
* Removed https://cdn.cocreate.app/latest/CoCreate.min.css ([aaa7944](https://github.com/CoCreate-app/CoCreate-users/commit/aaa79444b46077144b81f84c524dd49d9744622f))
|
|
17
|
+
|
|
1
18
|
## [1.34.1](https://github.com/CoCreate-app/CoCreate-users/compare/v1.34.0...v1.34.1) (2024-01-30)
|
|
2
19
|
|
|
3
20
|
|
package/docs/index.html
CHANGED
|
@@ -21,11 +21,6 @@
|
|
|
21
21
|
property="og:image"
|
|
22
22
|
content="https://cdn.cocreate.app/docs/users.png" />
|
|
23
23
|
|
|
24
|
-
<!-- CoCreate CSS -->
|
|
25
|
-
<link
|
|
26
|
-
rel="stylesheet"
|
|
27
|
-
href="https://cdn.cocreate.app/latest/CoCreate.min.css"
|
|
28
|
-
type="text/css" />
|
|
29
24
|
<link
|
|
30
25
|
rel="stylesheet"
|
|
31
26
|
href="../index.css"
|
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -168,8 +168,12 @@ const CoCreateUser = {
|
|
|
168
168
|
|
|
169
169
|
updateUserStatus: function (data) {
|
|
170
170
|
this.redirect(data)
|
|
171
|
+
let statusEls
|
|
171
172
|
if (data.user_id) {
|
|
172
|
-
|
|
173
|
+
if (data.user_id === Crud.socket.user_id)
|
|
174
|
+
statusEls = document.querySelectorAll(`[user-status][object='${data['user_id']}'], [user-status][object='$user_id']`);
|
|
175
|
+
else
|
|
176
|
+
statusEls = document.querySelectorAll(`[user-status][object='${data['user_id']}']`);
|
|
173
177
|
|
|
174
178
|
statusEls.forEach((el) => {
|
|
175
179
|
el.setAttribute('user-status', data['userStatus']);
|
|
@@ -226,7 +230,92 @@ const CoCreateUser = {
|
|
|
226
230
|
|
|
227
231
|
},
|
|
228
232
|
|
|
229
|
-
|
|
233
|
+
inviteUser: async function (action) {
|
|
234
|
+
let email = action.form.querySelector('input[key="email"]');
|
|
235
|
+
if (!email)
|
|
236
|
+
return
|
|
237
|
+
else
|
|
238
|
+
email = await email.getValue()
|
|
239
|
+
|
|
240
|
+
let name = action.form.querySelector('input[key="name"]');
|
|
241
|
+
if (name)
|
|
242
|
+
name = await name.getValue()
|
|
243
|
+
|
|
244
|
+
let from = action.form.querySelector('input[key="from"]');
|
|
245
|
+
if (from)
|
|
246
|
+
from = await from.getValue()
|
|
247
|
+
|
|
248
|
+
let origin = action.form.querySelector('input[key="origin"]');
|
|
249
|
+
if (origin)
|
|
250
|
+
origin = await origin.getValue() || window.location.origin
|
|
251
|
+
|
|
252
|
+
let hostname = action.form.querySelector('input[key="hostname"]');
|
|
253
|
+
if (hostname)
|
|
254
|
+
hostname = await hostname.getValue() || window.location.hostname
|
|
255
|
+
|
|
256
|
+
let path = action.form.querySelector('input[key="path"]');
|
|
257
|
+
if (path)
|
|
258
|
+
path = await path.getValue()
|
|
259
|
+
|
|
260
|
+
let request = {
|
|
261
|
+
method: 'inviteUser',
|
|
262
|
+
name,
|
|
263
|
+
email,
|
|
264
|
+
from,
|
|
265
|
+
origin,
|
|
266
|
+
hostname,
|
|
267
|
+
path
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
Crud.socket.send(request).then((response) => {
|
|
271
|
+
render({
|
|
272
|
+
selector: "[template*='inviteUser']",
|
|
273
|
+
data: [{
|
|
274
|
+
type: 'inviteUser',
|
|
275
|
+
message: response.message,
|
|
276
|
+
success: response.success
|
|
277
|
+
}]
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
})
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
acceptInvite: async function (action) {
|
|
284
|
+
let data = {
|
|
285
|
+
method: 'acceptInvite',
|
|
286
|
+
success: false
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
let token = action.form.querySelector('input[key="token"]');
|
|
290
|
+
if (token)
|
|
291
|
+
data.token = await token.getValue()
|
|
292
|
+
let user_id = action.form.querySelector('input[key="_id"]');
|
|
293
|
+
if (user_id)
|
|
294
|
+
data.user_id = await user_id.getValue()
|
|
295
|
+
let email = action.form.querySelector('input[key="email"]');
|
|
296
|
+
if (email)
|
|
297
|
+
data.email = await email.getValue()
|
|
298
|
+
|
|
299
|
+
if (data.token && data.user_id) {
|
|
300
|
+
data = await Crud.socket.send(data)
|
|
301
|
+
} else {
|
|
302
|
+
data.message = 'Invitation failed'
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
if (data.success)
|
|
306
|
+
document.dispatchEvent(new CustomEvent('acceptInvite'));
|
|
307
|
+
else
|
|
308
|
+
render({
|
|
309
|
+
selector: "[template*='acceptInvite']",
|
|
310
|
+
data: [{
|
|
311
|
+
type: 'acceptInvite',
|
|
312
|
+
message: data.message,
|
|
313
|
+
success: data.success,
|
|
314
|
+
}]
|
|
315
|
+
});
|
|
316
|
+
},
|
|
317
|
+
|
|
318
|
+
|
|
230
319
|
forgotPassword: async function (action) {
|
|
231
320
|
let email = action.form.querySelector('input[key="email"]');
|
|
232
321
|
if (!email)
|
|
@@ -242,7 +331,7 @@ const CoCreateUser = {
|
|
|
242
331
|
if (origin)
|
|
243
332
|
origin = await origin.getValue() || window.location.origin
|
|
244
333
|
|
|
245
|
-
let hostname = action.form.querySelector('input[key="
|
|
334
|
+
let hostname = action.form.querySelector('input[key="hostname"]');
|
|
246
335
|
if (hostname)
|
|
247
336
|
hostname = await hostname.getValue() || window.location.hostname
|
|
248
337
|
|
|
@@ -330,6 +419,20 @@ Actions.init([
|
|
|
330
419
|
CoCreateUser.signOut(action);
|
|
331
420
|
}
|
|
332
421
|
},
|
|
422
|
+
{
|
|
423
|
+
name: "inviteUser",
|
|
424
|
+
endEvent: "inviteUser",
|
|
425
|
+
callback: (action) => {
|
|
426
|
+
CoCreateUser.inviteUser(action);
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
name: "acceptInvite",
|
|
431
|
+
endEvent: "acceptInvite",
|
|
432
|
+
callback: (action) => {
|
|
433
|
+
CoCreateUser.acceptInvite(action);
|
|
434
|
+
}
|
|
435
|
+
},
|
|
333
436
|
{
|
|
334
437
|
name: "forgotPassword",
|
|
335
438
|
endEvent: "forgotPassword",
|
package/src/server.js
CHANGED
|
@@ -11,6 +11,8 @@ class CoCreateUser {
|
|
|
11
11
|
this.wsManager.on('signIn', (data) => this.signIn(data))
|
|
12
12
|
this.wsManager.on('userStatus', (data) => this.userStatus(data))
|
|
13
13
|
this.wsManager.on('checkSession', (data) => this.checkSession(data))
|
|
14
|
+
this.wsManager.on('inviteUser', (data) => this.inviteUser(data))
|
|
15
|
+
this.wsManager.on('acceptInvite', (data) => this.acceptInvite(data))
|
|
14
16
|
this.wsManager.on('forgotPassword', (data) => this.forgotPassword(data))
|
|
15
17
|
this.wsManager.on('resetPassword', (data) => this.resetPassword(data))
|
|
16
18
|
}
|
|
@@ -153,6 +155,128 @@ class CoCreateUser {
|
|
|
153
155
|
}
|
|
154
156
|
}
|
|
155
157
|
|
|
158
|
+
async inviteUser(data) {
|
|
159
|
+
try {
|
|
160
|
+
const inviteId = this.crud.ObjectId().toString()
|
|
161
|
+
let socket = data.socket
|
|
162
|
+
delete data.socket
|
|
163
|
+
|
|
164
|
+
data.method = 'object.update'
|
|
165
|
+
data.array = "users"
|
|
166
|
+
data.object = { _id: data.user_id, '$addToSet.invitations': inviteId, '$addToSet.members': data.email }
|
|
167
|
+
|
|
168
|
+
data = await this.crud.send(data)
|
|
169
|
+
|
|
170
|
+
let htmlBody = `
|
|
171
|
+
<html>
|
|
172
|
+
<head>
|
|
173
|
+
<title>Welcome to Yellow Oracle!</title>
|
|
174
|
+
</head>
|
|
175
|
+
<body>
|
|
176
|
+
<p>Hello,</p>
|
|
177
|
+
|
|
178
|
+
<p>You have been invited to join ${data.name} on Yellow Oracle.</p>
|
|
179
|
+
|
|
180
|
+
<p><a href="${data.origin}${data.path}?email=${data.email}&token=${inviteId}&user_id=${data.user_id}&name=${data.name}" style="color: #ffffff; background-color: #FFD700; padding: 10px 20px; text-decoration: none; border-radius: 5px;">Accept Your Invitation</a></p>
|
|
181
|
+
|
|
182
|
+
<p>Please note, this invitation link will expire in 48 hours. We encourage you to accept it soon to begin your journey with ${data.name} on Yellow Oracle.</p>
|
|
183
|
+
|
|
184
|
+
<p>If the button above doesn't work, you can copy and paste the following URL into your web browser:</p>
|
|
185
|
+
<p><a href="${data.origin}${data.path}?email=${data.email}&token=${inviteId}&user_id=${data.user_id}&name=${data.name}">${data.origin}${data.path}?email=${data.email}&token=${inviteId}&user_id=${data.user_id}&name=${data.name}</a></p>
|
|
186
|
+
|
|
187
|
+
<p>If you received this invitation by mistake or have any questions, please don't hesitate to get in touch with our support team at <a href="mailto:support@${data.hostname}">support@${data.hostname}</a>.</p>
|
|
188
|
+
|
|
189
|
+
<p>We look forward to welcoming you to ${data.name}'s Yellow Oracle account!</p>
|
|
190
|
+
|
|
191
|
+
</body>
|
|
192
|
+
</html>
|
|
193
|
+
`;
|
|
194
|
+
|
|
195
|
+
let email = {
|
|
196
|
+
method: 'postmark.sendEmail',
|
|
197
|
+
host: data.host,
|
|
198
|
+
postmark: {
|
|
199
|
+
"From": data.from,
|
|
200
|
+
"To": data.email,
|
|
201
|
+
"Subject": `${data.name} has invited you to join them on Yellow Oracle`,
|
|
202
|
+
"HtmlBody": htmlBody,
|
|
203
|
+
"TextBody": "Hello, \n\nWe received a request to reset the password for your account.If you did not make this request, please ignore this email.Otherwise, you can reset your password by copying and pasting the following link into your browser: https://example.com/reset-password\n\nThis link will expire in 24 hours for your security.\n\nNeed more help? Our support team is here for you at support@example.com.\n\nThank you for using our services!\n\nBest regards,\nThe [Your Company] Team",
|
|
204
|
+
"MessageStream": "outbound"
|
|
205
|
+
},
|
|
206
|
+
organization_id: data.organization_id
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// TODO: wsManager.emit('postmark', email) needs to await response
|
|
210
|
+
this.wsManager.emit('postmark', email);
|
|
211
|
+
|
|
212
|
+
let response = {
|
|
213
|
+
socket,
|
|
214
|
+
host: data.host,
|
|
215
|
+
method: 'inviteUser',
|
|
216
|
+
success: true,
|
|
217
|
+
message: "Succesfully sent invite",
|
|
218
|
+
organization_id: data.organization_id,
|
|
219
|
+
uid: data.uid
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
this.wsManager.send(response)
|
|
223
|
+
|
|
224
|
+
} catch (error) {
|
|
225
|
+
data.error = error
|
|
226
|
+
this.wsManager.send(data)
|
|
227
|
+
|
|
228
|
+
console.log('Invite User failed', error);
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
async acceptInvite(data) {
|
|
233
|
+
const self = this;
|
|
234
|
+
try {
|
|
235
|
+
if (!data.token || !data.user_id) {
|
|
236
|
+
// TODO: handle error
|
|
237
|
+
return
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
data.method = 'object.update'
|
|
241
|
+
data.array = "users"
|
|
242
|
+
data.object = { '$pull.invitations': data.token, '$pull.members': data.email }
|
|
243
|
+
data.$filter = {
|
|
244
|
+
query: { invitations: { $in: [data.token] }, members: { $in: [data.email] } },
|
|
245
|
+
limit: 1
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
data = await this.crud.send(data)
|
|
249
|
+
|
|
250
|
+
let response = {
|
|
251
|
+
socket: data.socket,
|
|
252
|
+
host: data.host,
|
|
253
|
+
method: 'acceptInvite',
|
|
254
|
+
success: false,
|
|
255
|
+
message: "Token is invalid or has expired",
|
|
256
|
+
organization_id: data.organization_id,
|
|
257
|
+
uid: data.uid
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
for (let object of data.object) {
|
|
261
|
+
if (object._id) {
|
|
262
|
+
delete data.$filter
|
|
263
|
+
data.object = { _id: object._id, '$addToSet.members': data.user_id }
|
|
264
|
+
data = await this.crud.send(data)
|
|
265
|
+
|
|
266
|
+
response.success = true
|
|
267
|
+
response.message = "Invite Accepted"
|
|
268
|
+
break
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
self.wsManager.send(response)
|
|
273
|
+
|
|
274
|
+
} catch (error) {
|
|
275
|
+
console.log("Password reset failed", error);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
|
|
156
280
|
async forgotPassword(data) {
|
|
157
281
|
const self = this;
|
|
158
282
|
try {
|
|
@@ -222,6 +346,7 @@ class CoCreateUser {
|
|
|
222
346
|
organization_id: data.organization_id
|
|
223
347
|
}
|
|
224
348
|
|
|
349
|
+
// TODO: wsManager.emit('postmark', email) needs to await response
|
|
225
350
|
self.wsManager.emit('postmark', email);
|
|
226
351
|
|
|
227
352
|
break
|
|
@@ -232,7 +357,7 @@ class CoCreateUser {
|
|
|
232
357
|
})
|
|
233
358
|
|
|
234
359
|
} catch (error) {
|
|
235
|
-
console.log('
|
|
360
|
+
console.log('Forgot Password failed', error);
|
|
236
361
|
}
|
|
237
362
|
}
|
|
238
363
|
|