underpost 2.7.93 → 2.8.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/.vscode/settings.json +3 -0
- package/bin/deploy.js +39 -0
- package/bin/index.js +1 -1
- package/docker-compose.yml +1 -1
- package/package.json +4 -3
- package/src/api/core/core.service.js +3 -5
- package/src/api/user/user.model.js +1 -1
- package/src/api/user/user.service.js +22 -21
- package/src/client/components/core/Account.js +142 -124
- package/src/client/components/core/Auth.js +94 -1
- package/src/client/components/core/Css.js +1 -1
- package/src/client/components/core/Docs.js +1 -1
- package/src/client/components/core/LogIn.js +8 -1
- package/src/client/components/core/LogOut.js +3 -2
- package/src/client/components/core/Modal.js +11 -7
- package/src/client/components/core/Panel.js +16 -3
- package/src/client/components/core/PanelForm.js +1 -0
- package/src/client/components/core/Scroll.js +35 -3
- package/src/client/components/core/SignUp.js +2 -5
- package/src/client/components/core/SocketIo.js +2 -0
- package/src/client/components/core/Translate.js +4 -0
- package/src/client/components/core/Validator.js +9 -2
- package/src/client/components/core/VanillaJs.js +4 -1
- package/src/client/components/default/LogInDefault.js +2 -23
- package/src/client/components/default/LogOutDefault.js +3 -5
- package/src/client/services/user/user.service.js +9 -1
- package/src/client/ssr/body/CacheControl.js +1 -1
- package/src/client/sw/default.sw.js +10 -4
- package/src/server/client-build.js +22 -21
- package/src/server/client-icons.js +12 -2
- package/src/server/conf.js +2 -1
- package/src/server/network.js +5 -1
- package/src/server/ssl.js +2 -2
- package/src/server/valkey.js +125 -0
package/.vscode/settings.json
CHANGED
package/bin/deploy.js
CHANGED
|
@@ -35,6 +35,7 @@ import { Lampp } from '../src/runtime/lampp/Lampp.js';
|
|
|
35
35
|
import { DefaultConf } from '../conf.js';
|
|
36
36
|
import { JSONweb } from '../src/server/client-formatted.js';
|
|
37
37
|
import ejs from 'easy-json-schema';
|
|
38
|
+
import { Xampp } from '../src/runtime/xampp/Xampp.js';
|
|
38
39
|
|
|
39
40
|
const logger = loggerFactory(import.meta);
|
|
40
41
|
|
|
@@ -283,6 +284,28 @@ try {
|
|
|
283
284
|
}
|
|
284
285
|
break;
|
|
285
286
|
|
|
287
|
+
case 'xampp': {
|
|
288
|
+
const directory = 'c:/xampp/htdocs';
|
|
289
|
+
const host = 'localhost';
|
|
290
|
+
const port = 80;
|
|
291
|
+
Xampp.removeRouter();
|
|
292
|
+
Xampp.appendRouter(` Listen ${port}
|
|
293
|
+
<VirtualHost *:${port}>
|
|
294
|
+
DocumentRoot "${directory}"
|
|
295
|
+
ServerName ${host}:${port}
|
|
296
|
+
|
|
297
|
+
<Directory "${directory}">
|
|
298
|
+
Options Indexes FollowSymLinks MultiViews
|
|
299
|
+
AllowOverride All
|
|
300
|
+
Require all granted
|
|
301
|
+
</Directory>
|
|
302
|
+
|
|
303
|
+
</VirtualHost>
|
|
304
|
+
`);
|
|
305
|
+
if (Xampp.enabled() && Xampp.router) Xampp.initService({ daemon: true });
|
|
306
|
+
break;
|
|
307
|
+
}
|
|
308
|
+
|
|
286
309
|
case 'adminer': {
|
|
287
310
|
const directory = '/dd/engine/public/adminer';
|
|
288
311
|
// const host = '127.0.0.1';
|
|
@@ -998,6 +1021,22 @@ ${uniqueArray(logs.all.map((log) => `- ${log.author_name} ([${log.author_email}]
|
|
|
998
1021
|
break;
|
|
999
1022
|
}
|
|
1000
1023
|
|
|
1024
|
+
case 'valkey': {
|
|
1025
|
+
if (!process.argv.includes('server')) {
|
|
1026
|
+
shellExec(`cd /dd && git clone https://github.com/valkey-io/valkey.git`);
|
|
1027
|
+
shellExec(`cd /dd/valkey && make`);
|
|
1028
|
+
shellExec(`apt install valkey-tools`); // valkey-cli
|
|
1029
|
+
}
|
|
1030
|
+
shellExec(`cd /dd/valkey && ./src/valkey-server`);
|
|
1031
|
+
|
|
1032
|
+
break;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
case 'valkey-service': {
|
|
1036
|
+
shellExec(`pm2 start bin/deploy.js --node-args=\"--max-old-space-size=8192\" --name valkey -- valkey server`);
|
|
1037
|
+
break;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1001
1040
|
default:
|
|
1002
1041
|
break;
|
|
1003
1042
|
}
|
package/bin/index.js
CHANGED
package/docker-compose.yml
CHANGED
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"type": "module",
|
|
3
3
|
"main": "src/index.js",
|
|
4
4
|
"name": "underpost",
|
|
5
|
-
"version": "2.
|
|
5
|
+
"version": "2.8.0",
|
|
6
6
|
"description": "pwa api rest template",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"start": "env-cmd -f .env.production node --max-old-space-size=8192 src/server",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"pm2-delete": "pm2 delete engine",
|
|
12
12
|
"build": "node bin/deploy build-full-client",
|
|
13
13
|
"build-production": "env-cmd -f .env.production node bin/deploy build-full-client",
|
|
14
|
-
"dev": "env-cmd -f .env.development node src/client.dev
|
|
14
|
+
"dev": "env-cmd -f .env.development node src/client.dev",
|
|
15
15
|
"dev-api": "env-cmd -f .env.development nodemon --watch src --ignore src/client src/api",
|
|
16
16
|
"docs": "jsdoc -c jsdoc.json",
|
|
17
17
|
"backup": "node bin/db default.net/ export",
|
|
@@ -117,7 +117,8 @@
|
|
|
117
117
|
"systeminformation": "^5.21.17",
|
|
118
118
|
"uglify-js": "^3.17.4",
|
|
119
119
|
"validator": "^13.11.0",
|
|
120
|
-
"winston": "^3.11.0"
|
|
120
|
+
"winston": "^3.11.0",
|
|
121
|
+
"iovalkey": "^0.2.1"
|
|
121
122
|
},
|
|
122
123
|
"devDependencies": {
|
|
123
124
|
"clean-jsdoc-theme": "^4.3.0",
|
|
@@ -9,11 +9,9 @@ const CoreService = {
|
|
|
9
9
|
/** @type {import('./core.model.js').CoreModel} */
|
|
10
10
|
const Core = DataBaseProvider.instance[`${options.host}${options.path}`].mongoose.models.Core;
|
|
11
11
|
if (req.path.startsWith('/sh')) {
|
|
12
|
-
shellExec(req.body.sh, { stdout: true
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
message: 'Command "' + req.body.sh + '" running',
|
|
16
|
-
};
|
|
12
|
+
if (req.body.print) return shellExec(req.body.sh, { stdout: true });
|
|
13
|
+
shellExec(req.body.sh, { async: true });
|
|
14
|
+
return 'Command "' + req.body.sh + '" running';
|
|
17
15
|
}
|
|
18
16
|
return await new Core(req.body).save();
|
|
19
17
|
},
|
|
@@ -6,24 +6,13 @@ import { CoreWsEmit } from '../../ws/core/core.ws.emit.js';
|
|
|
6
6
|
import { CoreWsMailerChannel } from '../../ws/core/channels/core.ws.mailer.js';
|
|
7
7
|
import validator from 'validator';
|
|
8
8
|
import { DataBaseProvider } from '../../db/DataBaseProvider.js';
|
|
9
|
-
import { s4 } from '../../client/components/core/CommonJs.js';
|
|
10
9
|
import { FileFactory } from '../file/file.service.js';
|
|
11
|
-
import fs from 'fs-extra';
|
|
12
|
-
import { svg, png, png3x } from 'font-awesome-assets';
|
|
13
10
|
import { UserDto } from './user.model.js';
|
|
14
|
-
import
|
|
11
|
+
import { selectDtoFactory, ValkeyAPI } from '../../server/valkey.js';
|
|
12
|
+
import { getDefaultProfileImageId } from '../../server/client-icons.js';
|
|
15
13
|
|
|
16
14
|
const logger = loggerFactory(import.meta);
|
|
17
15
|
|
|
18
|
-
const getDefaultProfileImageId = async (File) => {
|
|
19
|
-
const faId = 'user';
|
|
20
|
-
const tmpFilePath = `./tmp/${faId}-${s4() + s4()}.svg`;
|
|
21
|
-
fs.writeFileSync(tmpFilePath, svg(faId, '#f5f5f5d1'), 'utf8');
|
|
22
|
-
const file = await new File(FileFactory.svg(fs.readFileSync(tmpFilePath), `${faId}.svg`)).save();
|
|
23
|
-
fs.removeSync(tmpFilePath);
|
|
24
|
-
return file._id;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
16
|
const UserService = {
|
|
28
17
|
post: async (req, res, options) => {
|
|
29
18
|
/** @type {import('./user.model.js').UserModel} */
|
|
@@ -235,6 +224,15 @@ const UserService = {
|
|
|
235
224
|
}
|
|
236
225
|
} else throw new Error('invalid email or password');
|
|
237
226
|
|
|
227
|
+
case 'guest': {
|
|
228
|
+
const user = await ValkeyAPI.valkeyObjectFactory('user', options);
|
|
229
|
+
await ValkeyAPI.setValkeyObject(user.email, user);
|
|
230
|
+
return {
|
|
231
|
+
token: hashJWT({ user: UserDto.auth.payload(user) }),
|
|
232
|
+
user: selectDtoFactory(user, UserDto.select.get()),
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
238
236
|
default: {
|
|
239
237
|
const validatePassword = validatePasswordMiddleware(req.body.password);
|
|
240
238
|
if (validatePassword.status === 'error') throw new Error(validatePassword.message);
|
|
@@ -327,13 +325,15 @@ const UserService = {
|
|
|
327
325
|
return await User.find().select(UserDto.select.getAll());
|
|
328
326
|
|
|
329
327
|
case 'auth': {
|
|
330
|
-
const user = await
|
|
331
|
-
|
|
332
|
-
|
|
328
|
+
const user = (await ValkeyAPI.getValkeyObject(req.auth.user.email))
|
|
329
|
+
? await ValkeyAPI.getValkeyObject(req.auth.user.email)
|
|
330
|
+
: await User.findOne({
|
|
331
|
+
_id: req.auth.user._id,
|
|
332
|
+
});
|
|
333
333
|
|
|
334
334
|
const file = await File.findOne({ _id: user.profileImageId });
|
|
335
335
|
|
|
336
|
-
if (!file) {
|
|
336
|
+
if (!file && !(await ValkeyAPI.getValkeyObject(req.auth.user.email))) {
|
|
337
337
|
await User.findByIdAndUpdate(
|
|
338
338
|
user._id,
|
|
339
339
|
{ profileImageId: await getDefaultProfileImageId(File) },
|
|
@@ -342,10 +342,11 @@ const UserService = {
|
|
|
342
342
|
},
|
|
343
343
|
);
|
|
344
344
|
}
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
345
|
+
return (await ValkeyAPI.getValkeyObject(req.auth.user.email))
|
|
346
|
+
? selectDtoFactory(await ValkeyAPI.getValkeyObject(req.auth.user.email), UserDto.select.get())
|
|
347
|
+
: await User.findOne({
|
|
348
|
+
_id: req.auth.user._id,
|
|
349
|
+
}).select(UserDto.select.get());
|
|
349
350
|
}
|
|
350
351
|
|
|
351
352
|
default: {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { UserService } from '../../services/user/user.service.js';
|
|
2
|
+
import { Auth } from './Auth.js';
|
|
2
3
|
import { BtnIcon } from './BtnIcon.js';
|
|
3
4
|
import { newInstance, s4 } from './CommonJs.js';
|
|
4
5
|
import { renderStatus, renderWave } from './Css.js';
|
|
5
6
|
import { EventsUI } from './EventsUI.js';
|
|
6
7
|
import { fileFormDataFactory, Input } from './Input.js';
|
|
7
8
|
import { LogIn } from './LogIn.js';
|
|
8
|
-
import { LogOut } from './LogOut.js';
|
|
9
9
|
import { Modal } from './Modal.js';
|
|
10
10
|
import { NotificationManager } from './NotificationManager.js';
|
|
11
11
|
import { Translate } from './Translate.js';
|
|
@@ -21,19 +21,19 @@ const Account = {
|
|
|
21
21
|
const waveAnimationId = 'account-wave';
|
|
22
22
|
const profileFileAccept = ['image/png', 'image/jpeg'];
|
|
23
23
|
setTimeout(async () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
src="${LogIn.Scope.user.main.model.user.profileImage.imageSrc}"
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
append(
|
|
25
|
+
`.wave-animation-container-${waveAnimationId}`,
|
|
26
|
+
html` <div class="abs center account-profile-image-container">
|
|
27
|
+
<img
|
|
28
|
+
class="abs center account-profile-image"
|
|
29
|
+
style="opacity: 1"
|
|
30
|
+
${LogIn.Scope.user.main.model.user.profileImage
|
|
31
|
+
? `src="${LogIn.Scope.user.main.model.user.profileImage.imageSrc}"`
|
|
32
|
+
: ''}
|
|
33
|
+
/>
|
|
34
|
+
</div>
|
|
35
|
+
<div class="abs center account-profile-image-loading" style="color: white"></div>`,
|
|
36
|
+
);
|
|
37
37
|
|
|
38
38
|
const formData = [
|
|
39
39
|
{
|
|
@@ -49,133 +49,141 @@ const Account = {
|
|
|
49
49
|
rules: [{ type: 'isStrongPassword' }],
|
|
50
50
|
},
|
|
51
51
|
];
|
|
52
|
-
const validators = await Validator.instance(formData);
|
|
53
52
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
const submit = async () => {
|
|
60
|
-
lastUser = newInstance(user);
|
|
61
|
-
const { errorMessage } = await validators();
|
|
62
|
-
if (errorMessage) return;
|
|
63
|
-
const body = {};
|
|
53
|
+
this.formData = formData;
|
|
54
|
+
|
|
55
|
+
this.instanceModalUiEvents = async ({ user }) => {
|
|
56
|
+
const validators = await Validator.instance(formData);
|
|
57
|
+
|
|
64
58
|
for (const inputData of formData) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
body[inputData.model] = s(`.${inputData.id}`).value;
|
|
68
|
-
user[inputData.model] = s(`.${inputData.id}`).value;
|
|
69
|
-
}
|
|
59
|
+
s(`.${inputData.id}`).value =
|
|
60
|
+
!user[inputData.model] && inputData.defaultValue ? inputData.defaultValue : user[inputData.model];
|
|
70
61
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
html:
|
|
74
|
-
result.status === 'error' && result.message
|
|
75
|
-
? result.message
|
|
76
|
-
: Translate.Render(`${result.status}-update-user`),
|
|
77
|
-
status: result.status,
|
|
78
|
-
});
|
|
79
|
-
if (result.status === 'success') {
|
|
80
|
-
user = result.data;
|
|
81
|
-
this.triggerUpdateEvent({ user });
|
|
82
|
-
if (lastUser.emailConfirmed !== user.emailConfirmed) {
|
|
83
|
-
this.renderVerifyEmailStatus(user);
|
|
84
|
-
}
|
|
62
|
+
let lastUser;
|
|
63
|
+
const submit = async () => {
|
|
85
64
|
lastUser = newInstance(user);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
if (s(`.btn-confirm-email`))
|
|
98
|
-
EventsUI.onClick(`.btn-confirm-email`, async (e) => {
|
|
99
|
-
e.preventDefault();
|
|
100
|
-
const result = await UserService.post({
|
|
101
|
-
id: 'mailer/verify-email',
|
|
102
|
-
body: { email: s(`.account-email`).value },
|
|
103
|
-
});
|
|
65
|
+
const { successKeys } = await validators();
|
|
66
|
+
if (successKeys.length === 0) return;
|
|
67
|
+
const body = {};
|
|
68
|
+
for (const inputData of formData) {
|
|
69
|
+
if (!s(`.${inputData.id}`).value || s(`.${inputData.id}`).value === 'undefined') continue;
|
|
70
|
+
if ('model' in inputData && successKeys.includes(inputData.id)) {
|
|
71
|
+
body[inputData.model] = s(`.${inputData.id}`).value;
|
|
72
|
+
user[inputData.model] = s(`.${inputData.id}`).value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const result = await UserService.put({ id: user._id, body });
|
|
104
76
|
NotificationManager.Push({
|
|
105
|
-
html:
|
|
77
|
+
html:
|
|
78
|
+
result.status === 'error' && result.message
|
|
79
|
+
? result.message
|
|
80
|
+
: Translate.Render(`${result.status}-update-user`),
|
|
106
81
|
status: result.status,
|
|
107
82
|
});
|
|
83
|
+
if (result.status === 'success') {
|
|
84
|
+
user = result.data;
|
|
85
|
+
this.triggerUpdateEvent({ user });
|
|
86
|
+
if (lastUser.emailConfirmed !== user.emailConfirmed) {
|
|
87
|
+
this.renderVerifyEmailStatus(user);
|
|
88
|
+
}
|
|
89
|
+
lastUser = newInstance(user);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
EventsUI.onClick(`.btn-account`, async (e) => {
|
|
93
|
+
e.preventDefault();
|
|
94
|
+
await submit();
|
|
108
95
|
});
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
s(`.${waveAnimationId}`).style.cursor = 'pointer';
|
|
112
|
-
s(`.${waveAnimationId}`).onclick = async (e) => {
|
|
113
|
-
e.preventDefault();
|
|
114
|
-
s(`.account-profile-image-input`).click();
|
|
115
|
-
};
|
|
116
|
-
EventsUI.onChange(
|
|
117
|
-
`.account-profile-image-input`,
|
|
118
|
-
async (e) => {
|
|
96
|
+
EventsUI.onClick(`.btn-account-update-username`, async (e) => {
|
|
119
97
|
e.preventDefault();
|
|
120
|
-
|
|
121
|
-
|
|
98
|
+
await submit();
|
|
99
|
+
});
|
|
122
100
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
101
|
+
if (s(`.btn-confirm-email`))
|
|
102
|
+
EventsUI.onClick(`.btn-confirm-email`, async (e) => {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
const result = await UserService.post({
|
|
105
|
+
id: 'mailer/verify-email',
|
|
106
|
+
body: { email: s(`.account-email`).value },
|
|
107
|
+
});
|
|
108
|
+
NotificationManager.Push({
|
|
109
|
+
html: result.status === 'error' ? result.message : Translate.Render(`email send`),
|
|
110
|
+
status: result.status,
|
|
111
|
+
});
|
|
127
112
|
});
|
|
113
|
+
this.renderVerifyEmailStatus(user);
|
|
128
114
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
115
|
+
s(`.${waveAnimationId}`).style.cursor = 'pointer';
|
|
116
|
+
s(`.${waveAnimationId}`).onclick = async (e) => {
|
|
117
|
+
e.preventDefault();
|
|
118
|
+
s(`.account-profile-image-input`).click();
|
|
119
|
+
};
|
|
120
|
+
EventsUI.onChange(
|
|
121
|
+
`.account-profile-image-input`,
|
|
122
|
+
async (e) => {
|
|
123
|
+
e.preventDefault();
|
|
124
|
+
s(`.account-profile-image`).style.opacity = 0;
|
|
125
|
+
const formFile = fileFormDataFactory(e, profileFileAccept);
|
|
126
|
+
|
|
127
|
+
const { status, data } = await UserService.put({
|
|
128
|
+
id: `profile-image/${user._id}`,
|
|
129
|
+
body: formFile,
|
|
130
|
+
headerId: 'file',
|
|
138
131
|
});
|
|
139
|
-
}
|
|
140
132
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return html`
|
|
155
|
-
<div class="in section-mp" style="text-align: center">${Translate.Render('confirm-delete-account')}</div>
|
|
156
|
-
`;
|
|
133
|
+
if (status === 'success') {
|
|
134
|
+
user.profileImageId = data.profileImageId;
|
|
135
|
+
delete LogIn.Scope.user.main.model.user.profileImage;
|
|
136
|
+
await LogIn.Trigger({ user });
|
|
137
|
+
s(`.account-profile-image`).src = LogIn.Scope.user.main.model.user.profileImage.imageSrc;
|
|
138
|
+
} else {
|
|
139
|
+
NotificationManager.Push({
|
|
140
|
+
html: Translate.Render('file-upload-failed'),
|
|
141
|
+
status: 'error',
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
s(`.account-profile-image`).style.opacity = 1;
|
|
157
146
|
},
|
|
158
|
-
|
|
147
|
+
{ loadingContainer: `.account-profile-image-loading` },
|
|
148
|
+
);
|
|
149
|
+
s(`.btn-account-change-password`).onclick = (e) => {
|
|
150
|
+
e.preventDefault();
|
|
151
|
+
// s(`.btn-close-modal-account`).click();
|
|
152
|
+
s(`.main-btn-recover`).click();
|
|
153
|
+
};
|
|
154
|
+
s(`.btn-account-delete-confirm`).onclick = async (e) => {
|
|
155
|
+
e.preventDefault();
|
|
156
|
+
const confirmResult = await Modal.RenderConfirm({
|
|
157
|
+
html: async () => {
|
|
158
|
+
return html`
|
|
159
|
+
<div class="in section-mp" style="text-align: center">
|
|
160
|
+
${Translate.Render('confirm-delete-account')}
|
|
161
|
+
</div>
|
|
162
|
+
`;
|
|
163
|
+
},
|
|
164
|
+
id: 'delete-account-modal',
|
|
165
|
+
});
|
|
166
|
+
if (confirmResult.status === 'cancelled') return;
|
|
167
|
+
s(`.btn-account-delete-confirm`).classList.add('hide');
|
|
168
|
+
s(`.btn-account-delete`).classList.remove('hide');
|
|
169
|
+
s(`.btn-account-delete`).click();
|
|
170
|
+
};
|
|
171
|
+
EventsUI.onClick(`.btn-account-delete`, async (e) => {
|
|
172
|
+
e.preventDefault();
|
|
173
|
+
const result = await UserService.delete({ id: user._id });
|
|
174
|
+
NotificationManager.Push({
|
|
175
|
+
html: result.status === 'error' ? result.message : Translate.Render(`success-delete-account`),
|
|
176
|
+
status: result.status,
|
|
177
|
+
});
|
|
178
|
+
s(`.btn-account-delete-confirm`).classList.remove('hide');
|
|
179
|
+
s(`.btn-account-delete`).classList.add('hide');
|
|
180
|
+
if (result.status === 'success') {
|
|
181
|
+
s(`.main-btn-home`).click();
|
|
182
|
+
await Auth.sessionOut();
|
|
183
|
+
}
|
|
159
184
|
});
|
|
160
|
-
if (confirmResult.status === 'cancelled') return;
|
|
161
|
-
s(`.btn-account-delete-confirm`).classList.add('hide');
|
|
162
|
-
s(`.btn-account-delete`).classList.remove('hide');
|
|
163
|
-
s(`.btn-account-delete`).click();
|
|
164
185
|
};
|
|
165
|
-
|
|
166
|
-
e.preventDefault();
|
|
167
|
-
const result = await UserService.delete({ id: user._id });
|
|
168
|
-
NotificationManager.Push({
|
|
169
|
-
html: result.status === 'error' ? result.message : Translate.Render(`success-delete-account`),
|
|
170
|
-
status: result.status,
|
|
171
|
-
});
|
|
172
|
-
s(`.btn-account-delete-confirm`).classList.remove('hide');
|
|
173
|
-
s(`.btn-account-delete`).classList.add('hide');
|
|
174
|
-
if (result.status === 'success') {
|
|
175
|
-
LogOut.Trigger();
|
|
176
|
-
s(`.main-btn-home`).click();
|
|
177
|
-
}
|
|
178
|
-
});
|
|
186
|
+
await this.instanceModalUiEvents({ user });
|
|
179
187
|
});
|
|
180
188
|
return html`
|
|
181
189
|
<input type="file" accept="${profileFileAccept.join(', ')}" class="account-profile-image-input hide" />
|
|
@@ -285,6 +293,16 @@ const Account = {
|
|
|
285
293
|
if (user.emailConfirmed === true) s(`.account-email`).setAttribute('disabled', '');
|
|
286
294
|
}
|
|
287
295
|
},
|
|
296
|
+
instanceModalUiEvents: async (user) => null,
|
|
297
|
+
updateForm: async function (user) {
|
|
298
|
+
if (!s(`.modal-account`)) return;
|
|
299
|
+
await this.instanceModalUiEvents({ user });
|
|
300
|
+
s(`.account-profile-image`).style.opacity = 0;
|
|
301
|
+
for (const inputData of this.formData)
|
|
302
|
+
if (s(`.${inputData.id}`)) s(`.${inputData.id}`).value = user[inputData.model];
|
|
303
|
+
s(`.account-profile-image`).src = LogIn.Scope.user.main.model.user.profileImage.imageSrc;
|
|
304
|
+
s(`.account-profile-image`).style.opacity = 1;
|
|
305
|
+
},
|
|
288
306
|
};
|
|
289
307
|
|
|
290
308
|
export { Account };
|
|
@@ -1,7 +1,19 @@
|
|
|
1
|
+
import { UserMock, UserService } from '../../services/user/user.service.js';
|
|
2
|
+
import { Account } from './Account.js';
|
|
3
|
+
import { loggerFactory } from './Logger.js';
|
|
4
|
+
import { LogIn } from './LogIn.js';
|
|
5
|
+
import { LogOut } from './LogOut.js';
|
|
6
|
+
import { SignUp } from './SignUp.js';
|
|
7
|
+
|
|
8
|
+
const logger = loggerFactory(import.meta);
|
|
9
|
+
|
|
1
10
|
const token = Symbol('token');
|
|
2
11
|
|
|
12
|
+
const guestToken = Symbol('guestToken');
|
|
13
|
+
|
|
3
14
|
const Auth = {
|
|
4
15
|
[token]: '',
|
|
16
|
+
[guestToken]: '',
|
|
5
17
|
setToken: function (value = '') {
|
|
6
18
|
return (this[token] = value);
|
|
7
19
|
},
|
|
@@ -11,8 +23,89 @@ const Auth = {
|
|
|
11
23
|
getToken: function () {
|
|
12
24
|
return this[token];
|
|
13
25
|
},
|
|
26
|
+
setGuestToken: function (value = '') {
|
|
27
|
+
return (this[guestToken] = value);
|
|
28
|
+
},
|
|
29
|
+
deleteGuestToken: function () {
|
|
30
|
+
return (this[guestToken] = '');
|
|
31
|
+
},
|
|
32
|
+
getGuestToken: function () {
|
|
33
|
+
return this[guestToken];
|
|
34
|
+
},
|
|
35
|
+
// jwt
|
|
14
36
|
getJWT: function () {
|
|
15
|
-
return `Bearer ${this.getToken()}`;
|
|
37
|
+
return `Bearer ${this.getToken() ? this.getToken() : this.getGuestToken()}`;
|
|
38
|
+
},
|
|
39
|
+
signUpToken: async function (
|
|
40
|
+
result = {
|
|
41
|
+
data: {
|
|
42
|
+
token: '',
|
|
43
|
+
user: null,
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
) {
|
|
47
|
+
try {
|
|
48
|
+
localStorage.setItem('jwt', result.data.token);
|
|
49
|
+
await Auth.sessionIn();
|
|
50
|
+
await SignUp.Trigger(result.data);
|
|
51
|
+
} catch (error) {
|
|
52
|
+
logger.error(error);
|
|
53
|
+
localStorage.removeItem('jwt');
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
sessionIn: async function (userServicePayload) {
|
|
57
|
+
try {
|
|
58
|
+
const token = userServicePayload?.data?.token ? userServicePayload.data.token : localStorage.getItem('jwt');
|
|
59
|
+
|
|
60
|
+
if (token) {
|
|
61
|
+
this.setToken(token);
|
|
62
|
+
const result = userServicePayload
|
|
63
|
+
? userServicePayload
|
|
64
|
+
: await (async () => {
|
|
65
|
+
const _result = await UserService.get({ id: 'auth' });
|
|
66
|
+
return {
|
|
67
|
+
status: _result.status,
|
|
68
|
+
data: {
|
|
69
|
+
user: _result.data,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
})();
|
|
73
|
+
const { status, data, message } = result;
|
|
74
|
+
if (status === 'success') {
|
|
75
|
+
localStorage.setItem('jwt', token);
|
|
76
|
+
await LogIn.Trigger({ user: data.user });
|
|
77
|
+
await Account.updateForm(data.user);
|
|
78
|
+
return { user: data.user };
|
|
79
|
+
} else throw new Error(message);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// anon guest session
|
|
83
|
+
this.deleteToken();
|
|
84
|
+
localStorage.removeItem('jwt');
|
|
85
|
+
let guestToken = localStorage.getItem('jwt.g');
|
|
86
|
+
|
|
87
|
+
if (!guestToken) {
|
|
88
|
+
const result = await UserService.post({ id: 'guest' });
|
|
89
|
+
localStorage.setItem('jwt.g', result.data.token);
|
|
90
|
+
guestToken = result.data.token;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
this.setGuestToken(guestToken);
|
|
94
|
+
let { data, status, message } = await UserService.get({ id: 'auth' });
|
|
95
|
+
if (status === 'error') throw new Error(message);
|
|
96
|
+
await Account.updateForm(data);
|
|
97
|
+
return { user: data };
|
|
98
|
+
} catch (error) {
|
|
99
|
+
logger.error(error);
|
|
100
|
+
localStorage.removeItem('jwt');
|
|
101
|
+
localStorage.removeItem('jwt.g');
|
|
102
|
+
return { user: UserMock.default };
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
sessionOut: async function () {
|
|
106
|
+
this.deleteToken();
|
|
107
|
+
localStorage.removeItem('jwt');
|
|
108
|
+
await LogOut.Trigger(await this.sessionIn());
|
|
16
109
|
},
|
|
17
110
|
};
|
|
18
111
|
|
|
@@ -344,7 +344,7 @@ const renderBubbleDialog = async function (
|
|
|
344
344
|
}
|
|
345
345
|
if (options.trianglePositionCss) cssTrianglePosition = options.trianglePositionCss;
|
|
346
346
|
return html` <div
|
|
347
|
-
class="${options?.classSelectors ? options.classSelectors : '
|
|
347
|
+
class="${options?.classSelectors ? options.classSelectors : 'in'} bubble-dialog bubble-dialog-${id}"
|
|
348
348
|
${options.bubbleCss ? `style='${options.bubbleCss}'` : ''}
|
|
349
349
|
>
|
|
350
350
|
<style class="style-bubble-dialog-triangle-${id}">
|