@underpostnet/underpost 2.97.1 → 2.98.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/README.md +2 -2
- package/cli.md +3 -1
- package/conf.js +2 -0
- package/manifests/deployment/dd-default-development/deployment.yaml +2 -2
- package/manifests/deployment/dd-test-development/deployment.yaml +2 -2
- package/package.json +1 -1
- package/scripts/rocky-pwa.sh +200 -0
- package/src/api/core/core.service.js +0 -5
- package/src/api/default/default.service.js +7 -5
- package/src/api/document/document.model.js +1 -1
- package/src/api/document/document.router.js +5 -0
- package/src/api/document/document.service.js +176 -128
- package/src/api/file/file.model.js +112 -4
- package/src/api/file/file.ref.json +42 -0
- package/src/api/file/file.service.js +380 -32
- package/src/api/user/user.model.js +38 -1
- package/src/api/user/user.router.js +96 -63
- package/src/api/user/user.service.js +81 -48
- package/src/cli/db.js +424 -166
- package/src/cli/index.js +8 -0
- package/src/cli/repository.js +1 -1
- package/src/cli/run.js +1 -0
- package/src/cli/ssh.js +10 -10
- package/src/client/components/core/Account.js +327 -36
- package/src/client/components/core/AgGrid.js +3 -0
- package/src/client/components/core/Auth.js +11 -3
- package/src/client/components/core/Chat.js +2 -2
- package/src/client/components/core/Content.js +161 -80
- package/src/client/components/core/Css.js +30 -0
- package/src/client/components/core/CssCore.js +16 -12
- package/src/client/components/core/FileExplorer.js +813 -49
- package/src/client/components/core/Input.js +207 -12
- package/src/client/components/core/LogIn.js +42 -20
- package/src/client/components/core/Modal.js +138 -24
- package/src/client/components/core/Panel.js +71 -32
- package/src/client/components/core/PanelForm.js +262 -77
- package/src/client/components/core/PublicProfile.js +888 -0
- package/src/client/components/core/Responsive.js +15 -7
- package/src/client/components/core/Router.js +117 -15
- package/src/client/components/core/SearchBox.js +322 -116
- package/src/client/components/core/SignUp.js +26 -7
- package/src/client/components/core/SocketIo.js +6 -3
- package/src/client/components/core/Translate.js +148 -0
- package/src/client/components/core/Validator.js +15 -0
- package/src/client/components/core/windowGetDimensions.js +6 -6
- package/src/client/components/default/MenuDefault.js +59 -12
- package/src/client/components/default/RoutesDefault.js +1 -0
- package/src/client/services/core/core.service.js +163 -1
- package/src/client/services/default/default.management.js +454 -76
- package/src/client/services/default/default.service.js +13 -6
- package/src/client/services/file/file.service.js +43 -16
- package/src/client/services/user/user.service.js +13 -9
- package/src/client/sw/default.sw.js +107 -184
- package/src/db/DataBaseProvider.js +1 -1
- package/src/db/mongo/MongooseDB.js +1 -1
- package/src/index.js +1 -1
- package/src/mailer/MailerProvider.js +4 -4
- package/src/runtime/express/Express.js +2 -1
- package/src/runtime/lampp/Lampp.js +2 -2
- package/src/server/auth.js +3 -6
- package/src/server/data-query.js +449 -0
- package/src/server/object-layer.js +0 -3
- package/src/ws/IoInterface.js +2 -2
|
@@ -29,24 +29,51 @@ const FileService = {
|
|
|
29
29
|
}),
|
|
30
30
|
),
|
|
31
31
|
get: (options = { id: '' }) =>
|
|
32
|
-
new Promise((resolve, reject) =>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
32
|
+
new Promise((resolve, reject) => {
|
|
33
|
+
// Handle blob endpoint - fetch binary data directly
|
|
34
|
+
if (options.id && options.id.startsWith('blob/')) {
|
|
35
|
+
const blobId = options.id.substring(5); // Remove 'blob/' prefix
|
|
36
|
+
fetch(getApiBaseUrl({ id: blobId, endpoint: 'file/blob' }), {
|
|
37
|
+
method: 'GET',
|
|
38
|
+
headers: headersFactory(),
|
|
39
|
+
credentials: 'include',
|
|
40
40
|
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
.then(async (res) => {
|
|
42
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
43
|
+
return await res.blob();
|
|
44
|
+
})
|
|
45
|
+
.then((blob) => {
|
|
46
|
+
logger.info('Blob fetched successfully');
|
|
47
|
+
return resolve({
|
|
48
|
+
status: 'success',
|
|
49
|
+
data: [blob],
|
|
50
|
+
});
|
|
51
|
+
})
|
|
52
|
+
.catch((error) => {
|
|
53
|
+
logger.error(error);
|
|
54
|
+
return reject(error);
|
|
55
|
+
});
|
|
56
|
+
} else {
|
|
57
|
+
// Handle regular metadata endpoint - fetch JSON
|
|
58
|
+
fetch(getApiBaseUrl({ id: options.id, endpoint }), {
|
|
59
|
+
method: 'GET',
|
|
60
|
+
headers: headersFactory(),
|
|
61
|
+
credentials: 'include',
|
|
44
62
|
})
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
63
|
+
.then(async (res) => {
|
|
64
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`);
|
|
65
|
+
return await res.json();
|
|
66
|
+
})
|
|
67
|
+
.then((res) => {
|
|
68
|
+
logger.info(res);
|
|
69
|
+
return resolve(res);
|
|
70
|
+
})
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
logger.error(error);
|
|
73
|
+
return reject(error);
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}),
|
|
50
77
|
delete: (options = { id: '', body: {} }) =>
|
|
51
78
|
new Promise((resolve, reject) =>
|
|
52
79
|
fetch(getApiBaseUrl({ id: options.id, endpoint }), {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Auth } from '../../components/core/Auth.js';
|
|
2
2
|
import { loggerFactory } from '../../components/core/Logger.js';
|
|
3
|
-
import { getApiBaseUrl, headersFactory, payloadFactory } from '../core/core.service.js';
|
|
3
|
+
import { getApiBaseUrl, headersFactory, payloadFactory, buildQueryUrl } from '../core/core.service.js';
|
|
4
4
|
|
|
5
5
|
const logger = loggerFactory(import.meta);
|
|
6
6
|
|
|
@@ -37,15 +37,19 @@ const UserService = {
|
|
|
37
37
|
return reject(error);
|
|
38
38
|
}),
|
|
39
39
|
),
|
|
40
|
-
get: (options = {
|
|
41
|
-
const { id
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
get: (options = {}) => {
|
|
41
|
+
const { id, page, limit, filterModel, sortModel, sort, asc, order } = options;
|
|
42
|
+
const url = buildQueryUrl(getApiBaseUrl({ id, endpoint }), {
|
|
43
|
+
page,
|
|
44
|
+
limit,
|
|
45
|
+
filterModel,
|
|
46
|
+
sortModel,
|
|
47
|
+
sort,
|
|
48
|
+
asc,
|
|
49
|
+
order,
|
|
50
|
+
});
|
|
47
51
|
return new Promise((resolve, reject) =>
|
|
48
|
-
fetch(url, {
|
|
52
|
+
fetch(url.toString(), {
|
|
49
53
|
method: 'GET',
|
|
50
54
|
headers: headersFactory(),
|
|
51
55
|
credentials: 'include',
|
|
@@ -6,199 +6,122 @@
|
|
|
6
6
|
* @namespace PwaServiceWorker
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
* @property {string} PROXY_PATH - Base path for proxying requests.
|
|
22
|
-
*/
|
|
23
|
-
constructor() {
|
|
24
|
-
// Configuration properties equivalent to the original global constants
|
|
25
|
-
this.PRE_CACHED_RESOURCES = self.renderPayload?.PRE_CACHED_RESOURCES ?? [];
|
|
26
|
-
this.CACHE_NAME = self.renderPayload?.CACHE_NAME ?? 'app-cache';
|
|
27
|
-
this.PROXY_PATH = self.renderPayload?.PROXY_PATH ?? '/';
|
|
28
|
-
|
|
29
|
-
console.log(`Service Worker Initialized. Cache: ${this.CACHE_NAME}, Proxy: ${this.PROXY_PATH}`);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Registers event listeners for the service worker lifecycle and requests.
|
|
34
|
-
* @method
|
|
35
|
-
* @memberof PwaServiceWorker
|
|
36
|
-
*/
|
|
37
|
-
run() {
|
|
38
|
-
// Bind methods to 'this' (the instance) before attaching to self
|
|
39
|
-
self.addEventListener('install', this._onInstall.bind(this));
|
|
40
|
-
self.addEventListener('activate', this._onActivate.bind(this));
|
|
41
|
-
self.addEventListener('fetch', this._onFetch.bind(this));
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Handles the 'install' event. Skips waiting and precaches static assets.
|
|
46
|
-
* @param {ExtendableEvent} event
|
|
47
|
-
* @memberof PwaServiceWorker
|
|
48
|
-
*/
|
|
49
|
-
_onInstall(event) {
|
|
50
|
-
// Activate right away
|
|
51
|
-
self.skipWaiting();
|
|
52
|
-
|
|
53
|
-
event.waitUntil(
|
|
54
|
-
(async () => {
|
|
55
|
-
// Open the app's cache using the configured name.
|
|
56
|
-
const cache = await caches.open(this.CACHE_NAME);
|
|
57
|
-
// Cache all static resources.
|
|
58
|
-
try {
|
|
59
|
-
console.log(`Precaching ${this.PRE_CACHED_RESOURCES.length} resources...`);
|
|
60
|
-
await cache.addAll(this.PRE_CACHED_RESOURCES);
|
|
61
|
-
} catch (error) {
|
|
62
|
-
console.error('Error during precaching resources:', error);
|
|
63
|
-
}
|
|
64
|
-
})(),
|
|
65
|
-
);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Handles the 'activate' event. Enables navigation preload and takes control
|
|
70
|
-
* of uncontrolled clients immediately.
|
|
71
|
-
* @param {ExtendableEvent} event
|
|
72
|
-
* @memberof PwaServiceWorker
|
|
73
|
-
*/
|
|
74
|
-
_onActivate(event) {
|
|
75
|
-
event.waitUntil(
|
|
76
|
-
(async () => {
|
|
77
|
-
// Enable navigation preload if it's supported.
|
|
78
|
-
if ('navigationPreload' in self.registration) {
|
|
79
|
-
await self.registration.navigationPreload.enable();
|
|
80
|
-
console.log('Navigation Preload enabled.');
|
|
81
|
-
}
|
|
82
|
-
})(),
|
|
83
|
-
);
|
|
84
|
-
// Tell the active service worker to take control of the page immediately.
|
|
85
|
-
self.clients.claim();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Handles the 'fetch' event, implementing the Cache-First strategy with
|
|
90
|
-
* complex offline and maintenance fallbacks.
|
|
91
|
-
* @param {FetchEvent} event
|
|
92
|
-
* @memberof PwaServiceWorker
|
|
93
|
-
*/
|
|
94
|
-
_onFetch(event) {
|
|
95
|
-
// Only handle HTTP/HTTPS requests that are not cross-origin (optional, but robust)
|
|
96
|
-
if (event.request.url.startsWith('http')) {
|
|
97
|
-
event.respondWith(this._handleFetchRequest(event));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Core logic to handle fetching, caching, and fallbacks.
|
|
103
|
-
* @param {FetchEvent} event
|
|
104
|
-
* @returns {Promise<Response>}
|
|
105
|
-
* @memberof PwaServiceWorker
|
|
106
|
-
*/
|
|
107
|
-
async _handleFetchRequest(event) {
|
|
108
|
-
// 1. Try Navigation Preload (if available) or network first
|
|
109
|
-
try {
|
|
110
|
-
const preloadResponse = await event.preloadResponse;
|
|
111
|
-
if (preloadResponse) return preloadResponse;
|
|
112
|
-
|
|
113
|
-
// Fall through to network request if no preload response
|
|
114
|
-
const networkResponse = await fetch(event.request);
|
|
115
|
-
|
|
116
|
-
// OPTIONAL: If the network request is successful, cache it for future use (stale-while-revalidate logic)
|
|
117
|
-
// Omitted for strict equivalence, as original only had complex fallback, not runtime caching.
|
|
118
|
-
|
|
119
|
-
return networkResponse;
|
|
120
|
-
} catch (error) {
|
|
121
|
-
console.error('Network request failed. Attempting cache/fallback logic.', event.request.url, error);
|
|
122
|
-
|
|
123
|
-
// 2. Try to match the request in the cache
|
|
9
|
+
const PRE_CACHED_RESOURCES = self.renderPayload?.PRE_CACHED_RESOURCES ? self.renderPayload.PRE_CACHED_RESOURCES : [];
|
|
10
|
+
const CACHE_NAME = self.renderPayload?.CACHE_NAME ? self.renderPayload.CACHE_NAME : 'app-cache';
|
|
11
|
+
const PROXY_PATH = self.renderPayload?.PROXY_PATH ? self.renderPayload.PROXY_PATH : '/';
|
|
12
|
+
self.addEventListener('install', (event) => {
|
|
13
|
+
// Activate right away
|
|
14
|
+
self.skipWaiting();
|
|
15
|
+
|
|
16
|
+
event.waitUntil(
|
|
17
|
+
(async () => {
|
|
18
|
+
// Open the app's cache.
|
|
19
|
+
const cache = await caches.open(CACHE_NAME);
|
|
20
|
+
// Cache all static resources.
|
|
124
21
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
22
|
+
await cache.addAll(PRE_CACHED_RESOURCES);
|
|
23
|
+
} catch (error) {
|
|
24
|
+
console.error(error);
|
|
25
|
+
}
|
|
26
|
+
// for (const cacheKey of PRE_CACHED_RESOURCES) {
|
|
27
|
+
// try {
|
|
28
|
+
// await cache.add(cacheKey);
|
|
29
|
+
// } catch (error) {
|
|
30
|
+
// console.error(error, cacheKey);
|
|
31
|
+
// }
|
|
32
|
+
// }
|
|
33
|
+
})(),
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
self.addEventListener('activate', (event) => {
|
|
38
|
+
event.waitUntil(
|
|
39
|
+
(async () => {
|
|
40
|
+
// Enable navigation preload if it's supported.
|
|
41
|
+
// See https://developers.google.com/web/updates/2017/02/navigation-preload
|
|
42
|
+
if ('navigationPreload' in self.registration) {
|
|
43
|
+
await self.registration.navigationPreload.enable();
|
|
44
|
+
}
|
|
45
|
+
})(),
|
|
46
|
+
);
|
|
47
|
+
// Tell the active service worker to take control of the page immediately.
|
|
48
|
+
self.clients.claim();
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
self.addEventListener('fetch', (event) => {
|
|
52
|
+
// Cache-First Strategy
|
|
53
|
+
event.respondWith(
|
|
54
|
+
(async () => {
|
|
55
|
+
// First, try to use the navigation preload response if it's supported.
|
|
56
|
+
try {
|
|
57
|
+
(async () => {
|
|
58
|
+
// Get the client.
|
|
59
|
+
if (event.request.url.match(location.origin)) {
|
|
60
|
+
const client = await clients.get(event.clientId);
|
|
61
|
+
if (client)
|
|
62
|
+
client.postMessage({
|
|
63
|
+
status: 'loader',
|
|
64
|
+
path: event.request.url.slice(location.origin.length),
|
|
65
|
+
});
|
|
140
66
|
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
} catch (
|
|
146
|
-
console.error('
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
onLine: navigator.onLine,
|
|
150
|
-
});
|
|
67
|
+
})();
|
|
68
|
+
const preloadResponse = await event.preloadResponse;
|
|
69
|
+
if (preloadResponse) return preloadResponse;
|
|
70
|
+
return await fetch(event.request);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.error('Fetch failed; returning offline page instead.', event.request.url, error);
|
|
73
|
+
// Fallback to the offline page.
|
|
74
|
+
const path = PRE_CACHED_RESOURCES.find((path) => event.request.url.match(path.replaceAll('/index.html', '')));
|
|
151
75
|
|
|
152
|
-
// 4. Complex Fallback Logic (Offline or Maintenance)
|
|
153
76
|
try {
|
|
154
|
-
const
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
77
|
+
const cachedResponse = await caches.match(event.request);
|
|
78
|
+
if (cachedResponse) return cachedResponse;
|
|
79
|
+
const cache = await caches.open(CACHE_NAME);
|
|
80
|
+
const preCachedResponse = await cache.match(path);
|
|
81
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
82
|
+
return preCachedResponse;
|
|
83
|
+
} catch (error) {
|
|
84
|
+
console.error('Error opening cache for pre cached page', {
|
|
85
|
+
url: event.request.url,
|
|
86
|
+
error,
|
|
87
|
+
onLine: navigator.onLine,
|
|
88
|
+
});
|
|
89
|
+
try {
|
|
90
|
+
if (!navigator.onLine) {
|
|
91
|
+
if (event.request.method.toUpperCase() === 'GET') {
|
|
92
|
+
const cache = await caches.open(CACHE_NAME);
|
|
93
|
+
const preCachedResponse = await cache.match(
|
|
94
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/offline/index.html`,
|
|
95
|
+
);
|
|
96
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
97
|
+
return preCachedResponse;
|
|
98
|
+
}
|
|
99
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'offline test response' }));
|
|
100
|
+
// response.status = 200;
|
|
101
|
+
response.headers.set('Content-Type', 'application/json');
|
|
102
|
+
return response;
|
|
103
|
+
}
|
|
158
104
|
if (event.request.method.toUpperCase() === 'GET') {
|
|
159
|
-
const
|
|
160
|
-
const preCachedResponse = await cache.match(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
console.log('Serving offline HTML page.');
|
|
105
|
+
const cache = await caches.open(CACHE_NAME);
|
|
106
|
+
const preCachedResponse = await cache.match(
|
|
107
|
+
`${PROXY_PATH === '/' ? '' : PROXY_PATH}/maintenance/index.html`,
|
|
108
|
+
);
|
|
109
|
+
if (!preCachedResponse) throw new Error(error.message);
|
|
165
110
|
return preCachedResponse;
|
|
166
111
|
}
|
|
167
|
-
|
|
168
|
-
//
|
|
169
|
-
|
|
170
|
-
|
|
112
|
+
const response = new Response(JSON.stringify({ status: 'error', message: 'server in maintenance' }));
|
|
113
|
+
// response.status = 200;
|
|
114
|
+
response.headers.set('Content-Type', 'application/json');
|
|
115
|
+
return response;
|
|
116
|
+
} catch (error) {
|
|
117
|
+
console.error('Error opening cache for offline page', event.request.url, error);
|
|
118
|
+
const response = new Response(JSON.stringify({ status: 'error', message: error.message }));
|
|
119
|
+
// response.status = 200;
|
|
171
120
|
response.headers.set('Content-Type', 'application/json');
|
|
172
121
|
return response;
|
|
173
122
|
}
|
|
174
|
-
|
|
175
|
-
// C. MAINTENANCE FALLBACK (Online, but network failed - interpreted as maintenance)
|
|
176
|
-
if (event.request.method.toUpperCase() === 'GET') {
|
|
177
|
-
const maintenancePath = `${this.PROXY_PATH === '/' ? '' : this.PROXY_PATH}/maintenance/index.html`;
|
|
178
|
-
const preCachedResponse = await cache.match(maintenancePath);
|
|
179
|
-
|
|
180
|
-
if (!preCachedResponse) throw new Error(`Maintenance page not found in cache: ${maintenancePath}`);
|
|
181
|
-
|
|
182
|
-
console.log('Serving maintenance HTML page.');
|
|
183
|
-
return preCachedResponse;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// D. MAINTENANCE API FALLBACK (Non-GET requests)
|
|
187
|
-
console.log('Serving maintenance JSON response for non-GET request.');
|
|
188
|
-
const response = new Response(JSON.stringify({ status: 'error', message: 'server in maintenance' }));
|
|
189
|
-
response.headers.set('Content-Type', 'application/json');
|
|
190
|
-
return response;
|
|
191
|
-
} catch (finalError) {
|
|
192
|
-
// 5. Final fail-safe response
|
|
193
|
-
console.error('Final fail-safe execution failed.', event.request.url, finalError);
|
|
194
|
-
const response = new Response(JSON.stringify({ status: 'error', message: finalError.message }));
|
|
195
|
-
response.headers.set('Content-Type', 'application/json');
|
|
196
|
-
return response;
|
|
197
123
|
}
|
|
198
124
|
}
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Instantiate and run the service worker class
|
|
204
|
-
new PwaServiceWorker().run();
|
|
125
|
+
})(),
|
|
126
|
+
);
|
|
127
|
+
});
|
|
@@ -28,7 +28,7 @@ class MongooseDBService {
|
|
|
28
28
|
*/
|
|
29
29
|
async connect(host, name) {
|
|
30
30
|
const uri = `${host}/${name}`;
|
|
31
|
-
logger.info('MongooseDB connect', { host, name, uri });
|
|
31
|
+
// logger.info('MongooseDB connect', { host, name, uri });
|
|
32
32
|
return await mongoose
|
|
33
33
|
.createConnection(uri, {
|
|
34
34
|
serverSelectionTimeoutMS: 5000,
|
package/src/index.js
CHANGED
|
@@ -41,7 +41,7 @@ class MailerProviderService {
|
|
|
41
41
|
/**
|
|
42
42
|
* Internal storage for mailer instances (transporters, options, templates), keyed by ID.
|
|
43
43
|
* @type {object.<string, object>}
|
|
44
|
-
* @
|
|
44
|
+
* @method
|
|
45
45
|
*/
|
|
46
46
|
#instance = {};
|
|
47
47
|
|
|
@@ -108,14 +108,14 @@ class MailerProviderService {
|
|
|
108
108
|
P1: {
|
|
109
109
|
en: `Email confirmed! Thanks.
|
|
110
110
|
<br />
|
|
111
|
-
<span style="font-size: 12px; color: gray">
|
|
112
|
-
If it is not automatically verified,
|
|
111
|
+
<span style="font-size: 12px; color: gray">
|
|
112
|
+
If it is not automatically verified,
|
|
113
113
|
please allow the image to be seen, thank you.
|
|
114
114
|
</span>
|
|
115
115
|
`,
|
|
116
116
|
es: `Correo electrónico confirmado! Gracias.
|
|
117
117
|
<br />
|
|
118
|
-
<span style="font-size: 12px; color: gray">
|
|
118
|
+
<span style="font-size: 12px; color: gray">
|
|
119
119
|
Si no se verifica automáticamente, por favor permita que se vea la imagen, gracias.
|
|
120
120
|
</span>
|
|
121
121
|
`,
|
|
@@ -180,6 +180,7 @@ class ExpressService {
|
|
|
180
180
|
|
|
181
181
|
// Database and Valkey connections
|
|
182
182
|
if (db && apis) await DataBaseProvider.load({ apis, host, path, db });
|
|
183
|
+
|
|
183
184
|
if (valkey) await createValkeyConnection({ host, path }, valkey);
|
|
184
185
|
|
|
185
186
|
// Mailer setup
|
|
@@ -202,7 +203,7 @@ class ExpressService {
|
|
|
202
203
|
for (const api of apis) {
|
|
203
204
|
logger.info(`Build api server`, `${host}${apiPath}/${api}`);
|
|
204
205
|
const { ApiRouter } = await import(`../../api/${api}/${api}.router.js`);
|
|
205
|
-
const router = ApiRouter({ host, path, apiPath, mailer, db, authMiddleware, origins });
|
|
206
|
+
const router = ApiRouter({ app, host, path, apiPath, mailer, db, authMiddleware, origins });
|
|
206
207
|
app.use(`${apiPath}/${api}`, router);
|
|
207
208
|
}
|
|
208
209
|
}
|
|
@@ -20,7 +20,7 @@ const logger = loggerFactory(import.meta);
|
|
|
20
20
|
*/
|
|
21
21
|
class LamppService {
|
|
22
22
|
/**
|
|
23
|
-
* @
|
|
23
|
+
* @method
|
|
24
24
|
* @type {string | undefined}
|
|
25
25
|
* @description Stores the accumulated Apache virtual host configuration (router definition).
|
|
26
26
|
* @memberof LamppService
|
|
@@ -273,7 +273,7 @@ Listen ${port}
|
|
|
273
273
|
ErrorDocument 504 ${path === '/' ? '' : path}/500.html
|
|
274
274
|
|
|
275
275
|
</VirtualHost>
|
|
276
|
-
|
|
276
|
+
|
|
277
277
|
`);
|
|
278
278
|
|
|
279
279
|
return { disabled: false };
|
package/src/server/auth.js
CHANGED
|
@@ -221,7 +221,7 @@ const authMiddlewareFactory = (options = { host: '', path: '' }) => {
|
|
|
221
221
|
|
|
222
222
|
if (payload.userAgent && payload.userAgent !== req.headers['user-agent']) {
|
|
223
223
|
logger.warn(`UA mismatch for ${payload._id}`);
|
|
224
|
-
return res.status(401).json({ status: 'error', message: 'unauthorized
|
|
224
|
+
return res.status(401).json({ status: 'error', message: 'unauthorized device' });
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
// Non-guest verify session exists
|
|
@@ -247,7 +247,7 @@ const authMiddlewareFactory = (options = { host: '', path: '' }) => {
|
|
|
247
247
|
// check session userAgent
|
|
248
248
|
if (session.userAgent !== req.headers['user-agent']) {
|
|
249
249
|
logger.warn(`UA mismatch for ${payload._id}`);
|
|
250
|
-
return res.status(401).json({ status: 'error', message: 'unauthorized
|
|
250
|
+
return res.status(401).json({ status: 'error', message: 'unauthorized device' });
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
// compare payload host and path with session host and path
|
|
@@ -441,22 +441,19 @@ async function logoutSession(User, req, res) {
|
|
|
441
441
|
* @param {import('express').Request} req The Express request object.
|
|
442
442
|
* @param {import('express').Response} res The Express response object.
|
|
443
443
|
* @param {import('mongoose').Model} User The Mongoose User model.
|
|
444
|
-
* @param {import('mongoose').Model} File The Mongoose File model.
|
|
445
444
|
* @param {object} [options={}] Additional options.
|
|
446
|
-
* @param {Function} options.getDefaultProfileImageId Function to get the default profile image ID.
|
|
447
445
|
* @param {string} options.host The host name.
|
|
448
446
|
* @param {string} options.path The path name.
|
|
449
447
|
* @returns {Promise<{token: string, user: object}>} The access token and user object.
|
|
450
448
|
* @throws {Error} If password validation fails.
|
|
451
449
|
* @memberof Auth
|
|
452
450
|
*/
|
|
453
|
-
async function createUserAndSession(req, res, User,
|
|
451
|
+
async function createUserAndSession(req, res, User, options = { host: '', path: '' }) {
|
|
454
452
|
const pwdCheck = validatePasswordMiddleware(req);
|
|
455
453
|
if (pwdCheck.status === 'error') throw new Error(pwdCheck.message);
|
|
456
454
|
|
|
457
455
|
req.body.password = await hashPassword(req.body.password);
|
|
458
456
|
req.body.role = req.body.role === 'guest' ? 'guest' : 'user';
|
|
459
|
-
req.body.profileImageId = await options.getDefaultProfileImageId(File);
|
|
460
457
|
|
|
461
458
|
const saved = await new User(req.body).save();
|
|
462
459
|
const user = await User.findOne({ _id: saved._id }).select(UserDto.select.get());
|