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.
Files changed (34) hide show
  1. package/.vscode/settings.json +3 -0
  2. package/bin/deploy.js +39 -0
  3. package/bin/index.js +1 -1
  4. package/docker-compose.yml +1 -1
  5. package/package.json +4 -3
  6. package/src/api/core/core.service.js +3 -5
  7. package/src/api/user/user.model.js +1 -1
  8. package/src/api/user/user.service.js +22 -21
  9. package/src/client/components/core/Account.js +142 -124
  10. package/src/client/components/core/Auth.js +94 -1
  11. package/src/client/components/core/Css.js +1 -1
  12. package/src/client/components/core/Docs.js +1 -1
  13. package/src/client/components/core/LogIn.js +8 -1
  14. package/src/client/components/core/LogOut.js +3 -2
  15. package/src/client/components/core/Modal.js +11 -7
  16. package/src/client/components/core/Panel.js +16 -3
  17. package/src/client/components/core/PanelForm.js +1 -0
  18. package/src/client/components/core/Scroll.js +35 -3
  19. package/src/client/components/core/SignUp.js +2 -5
  20. package/src/client/components/core/SocketIo.js +2 -0
  21. package/src/client/components/core/Translate.js +4 -0
  22. package/src/client/components/core/Validator.js +9 -2
  23. package/src/client/components/core/VanillaJs.js +4 -1
  24. package/src/client/components/default/LogInDefault.js +2 -23
  25. package/src/client/components/default/LogOutDefault.js +3 -5
  26. package/src/client/services/user/user.service.js +9 -1
  27. package/src/client/ssr/body/CacheControl.js +1 -1
  28. package/src/client/sw/default.sw.js +10 -4
  29. package/src/server/client-build.js +22 -21
  30. package/src/server/client-icons.js +12 -2
  31. package/src/server/conf.js +2 -1
  32. package/src/server/network.js +5 -1
  33. package/src/server/ssl.js +2 -2
  34. package/src/server/valkey.js +125 -0
@@ -43,6 +43,7 @@
43
43
  "lampp",
44
44
  "loadingio",
45
45
  "Longname",
46
+ "metanarrative",
46
47
  "Microdata",
47
48
  "minami",
48
49
  "MMORPG",
@@ -60,6 +61,8 @@
60
61
  "Tokenomics",
61
62
  "underpost",
62
63
  "Unequip",
64
+ "uuidv",
65
+ "Valkey",
63
66
  "webroot",
64
67
  "xampp",
65
68
  "xfwd",
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
@@ -19,7 +19,7 @@ const globalBinFolder = `${shellExec(`npm root -g`, {
19
19
 
20
20
  const program = new Command();
21
21
 
22
- const version = '2.7.93';
22
+ const version = '2.8.0';
23
23
 
24
24
  program.name('underpost').description(`underpost.net ci/cd cli ${version}`).version(version);
25
25
 
@@ -58,7 +58,7 @@ services:
58
58
  cpus: '0.25'
59
59
  memory: 20M
60
60
  labels: # labels in Compose file instead of Dockerfile
61
- engine.version: '2.7.93'
61
+ engine.version: '2.8.0'
62
62
  networks:
63
63
  - load-balancer
64
64
 
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.7.93",
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 --no-warnings",
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, async: true });
13
- return {
14
- status: 'success',
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
  },
@@ -58,7 +58,7 @@ const UserDto = {
58
58
  },
59
59
  },
60
60
  auth: {
61
- payload: (user) => ({ _id: user._id.toString(), role: user.role }),
61
+ payload: (user) => ({ _id: user._id.toString(), role: user.role, email: user.email }),
62
62
  },
63
63
  };
64
64
 
@@ -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 Jimp from 'jimp';
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 User.findOne({
331
- _id: req.auth.user._id,
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
- return await User.findOne({
347
- _id: req.auth.user._id,
348
- }).select(UserDto.select.get());
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
- if (LogIn.Scope.user.main.model.user.profileImage) {
25
- append(
26
- `.wave-animation-container-${waveAnimationId}`,
27
- html` <div class="abs center account-profile-image-container">
28
- <img
29
- class="abs center account-profile-image"
30
- style="opacity: 1"
31
- src="${LogIn.Scope.user.main.model.user.profileImage.imageSrc}"
32
- />
33
- </div>
34
- <div class="abs center account-profile-image-loading" style="color: white"></div>`,
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
- for (const inputData of formData) {
55
- s(`.${inputData.id}`).value =
56
- !user[inputData.model] && inputData.defaultValue ? inputData.defaultValue : user[inputData.model];
57
- }
58
- let lastUser;
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
- if (!s(`.${inputData.id}`).value || s(`.${inputData.id}`).value === 'undefined') continue;
66
- if ('model' in inputData) {
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
- const result = await UserService.put({ id: user._id, body });
72
- NotificationManager.Push({
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
- EventsUI.onClick(`.btn-account`, async (e) => {
89
- e.preventDefault();
90
- await submit();
91
- });
92
- EventsUI.onClick(`.btn-account-update-username`, async (e) => {
93
- e.preventDefault();
94
- await submit();
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: result.status === 'error' ? result.message : Translate.Render(`email send`),
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
- this.renderVerifyEmailStatus(user);
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
- s(`.account-profile-image`).style.opacity = 0;
121
- const formFile = fileFormDataFactory(e, profileFileAccept);
98
+ await submit();
99
+ });
122
100
 
123
- const { status, data } = await UserService.put({
124
- id: `profile-image/${user._id}`,
125
- body: formFile,
126
- headerId: 'file',
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
- if (status === 'success') {
130
- user.profileImageId = data.profileImageId;
131
- delete LogIn.Scope.user.main.model.user.profileImage;
132
- await LogIn.Trigger({ user });
133
- s(`.account-profile-image`).src = LogIn.Scope.user.main.model.user.profileImage.imageSrc;
134
- } else {
135
- NotificationManager.Push({
136
- html: Translate.Render('file-upload-failed'),
137
- status: 'error',
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
- s(`.account-profile-image`).style.opacity = 1;
142
- },
143
- { loadingContainer: `.account-profile-image-loading` },
144
- );
145
- s(`.btn-account-change-password`).onclick = (e) => {
146
- e.preventDefault();
147
- // s(`.btn-close-modal-account`).click();
148
- s(`.main-btn-recover`).click();
149
- };
150
- s(`.btn-account-delete-confirm`).onclick = async (e) => {
151
- e.preventDefault();
152
- const confirmResult = await Modal.RenderConfirm({
153
- html: async () => {
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
- id: 'delete-account-modal',
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
- EventsUI.onClick(`.btn-account-delete`, async (e) => {
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 : 'inl'} bubble-dialog bubble-dialog-${id}"
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}">