lupine.api 1.1.45 → 1.1.47

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.
@@ -10,13 +10,6 @@ import {
10
10
  downloadStream,
11
11
  } from 'lupine.components';
12
12
 
13
- interface DirProps {
14
- name: string;
15
- time: string;
16
- size: number;
17
- dir: boolean;
18
- items?: DirProps[];
19
- }
20
13
  interface ReleaseListProps {
21
14
  result: any;
22
15
  onUpdate: () => void;
@@ -101,7 +94,7 @@ const ReleaseList = (props: ReleaseListProps) => {
101
94
  </label>
102
95
  </div>
103
96
  ))}
104
- <label class='label mr-m release-label'>(Only update index.js file)</label>
97
+ <label class='label mr-m release-label'>(Skip *.js.map files)</label>
105
98
  </div>
106
99
  </div>
107
100
  <LogList logs={props.result.logs} onLogClick={props.onLogClick} />
@@ -123,12 +116,13 @@ const LogList = (props: {
123
116
  <div class='row-box mt-m'>
124
117
  <label class='label mr-m release-label'>Logs:</label>
125
118
  <div type='text'>
126
- {props.logs && props.logs.map((log: { name: string; size: number; time: string }) => (
127
- <div>
128
- <label class='release-log' onClick={() => props.onLogClick(log.name)}>{`${log.name}`}</label> ({log.time};{' '}
129
- {formatBytes(log.size)}){' '}
130
- </div>
131
- ))}
119
+ {props.logs &&
120
+ props.logs.map((log: { name: string; size: number; time: string }) => (
121
+ <div>
122
+ <label class='release-log' onClick={() => props.onLogClick(log.name)}>{`${log.name}`}</label> (
123
+ {log.time}; {formatBytes(log.size)}){' '}
124
+ </div>
125
+ ))}
132
126
  </div>
133
127
  </div>
134
128
  </div>
@@ -138,7 +132,7 @@ const LogList = (props: {
138
132
  export const AdminReleasePage = () => {
139
133
  const fetchData = async (options: { targetUrl: string; accessToken: string; log?: boolean }) => {
140
134
  const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/release/check', options);
141
- console.log('AdminRelease', data);
135
+ console.log('release/check', data);
142
136
  return data.json;
143
137
  };
144
138
  const css: CssProps = {
@@ -153,11 +147,18 @@ export const AdminReleasePage = () => {
153
147
  const domLog = new HtmlVar('');
154
148
  const domUpdate = new HtmlVar('');
155
149
  const getDomData = () => {
156
- const dataOld = JSON.parse(localStorage.getItem('admin-release') || '{}');
150
+ const domFromList = ref.$('.from-list');
151
+ let fromValue = '';
152
+ if (!domFromList) {
153
+ const dataOld = JSON.parse(localStorage.getItem('admin-release') || '{}');
154
+ fromValue = dataOld.fromList;
155
+ } else {
156
+ fromValue = domFromList.value;
157
+ }
157
158
  const data = {
158
- targetUrl: DomUtils.getValue('.target-url'),
159
- accessToken: DomUtils.getValue('.access-token'),
160
- fromList: DomUtils.getValue('.from-list') || dataOld.fromList,
159
+ targetUrl: ref.$('.target-url').value,
160
+ accessToken: ref.$('.access-token').value,
161
+ fromList: fromValue,
161
162
  };
162
163
  localStorage.setItem('admin-release', JSON.stringify(data));
163
164
  return data;
@@ -170,18 +171,23 @@ export const AdminReleasePage = () => {
170
171
  return;
171
172
  }
172
173
 
173
- const fromList = DomUtils.getValue('.from-list');
174
- const toList = DomUtils.getValue('.to-list');
175
- const chkServer = DomUtils.getChecked('.chk-server');
176
- const chkApi = DomUtils.getChecked('.chk-api');
177
- const chkWeb = DomUtils.getChecked('.chk-web');
178
- const webSub = DomUtils.getValue('.input-web-sub');
179
- const webSubs = document.querySelectorAll<HTMLInputElement>('.chk-web-sub');
174
+ const fromList = ref.$('.from-list').value;
175
+ const toList = ref.$('.to-list').value;
176
+ const chkServer = ref.$('.chk-server').checked;
177
+ const chkApi = ref.$('.chk-api').checked;
178
+ const chkWeb = ref.$('.chk-web').checked;
179
+ // const webSub = ref.$('.input-web-sub').value;
180
+ const webSubs = ref.$all('.chk-web-sub') as HTMLInputElement[];
180
181
  const webSubsChecked = Array.from(webSubs)
181
182
  .filter((input) => input.checked)
182
183
  .map((input) => input.value);
183
- const chkEnv = DomUtils.getChecked('.chk-env');
184
- const chkBackup = DomUtils.getChecked('.chk-backup');
184
+ const wrongWebSubs = webSubsChecked.filter((s) => !s.startsWith(fromList + '_web/'));
185
+ if (wrongWebSubs.length > 0) {
186
+ NotificationMessage.sendMessage(`Some web sub folder is not under ${fromList}`, NotificationColor.Error);
187
+ return;
188
+ }
189
+ const chkEnv = ref.$('.chk-env').checked;
190
+ const chkBackup = ref.$('.chk-backup').checked;
185
191
  if (!chkServer && !chkApi && !chkWeb && !chkEnv) {
186
192
  NotificationMessage.sendMessage('Please select the release options', NotificationColor.Error);
187
193
  return;
@@ -202,16 +208,19 @@ export const AdminReleasePage = () => {
202
208
  chkServer,
203
209
  chkApi,
204
210
  chkWeb,
205
- webSub, // will be deprecated
211
+ // webSub, // will be deprecated
206
212
  webSubs: webSubsChecked,
207
213
  chkEnv,
208
214
  chkBackup,
209
215
  });
210
216
  const dataResponse = await response.json;
211
- console.log('AdminRelease', dataResponse);
217
+ console.log('release/update', dataResponse);
212
218
  releaseUpdateBtn.disabled = false;
213
219
  if (!dataResponse || dataResponse.status !== 'ok') {
214
- NotificationMessage.sendMessage(dataResponse.message || 'Failed to update release', NotificationColor.Error);
220
+ NotificationMessage.sendMessage(
221
+ dataResponse.message || 'Failed to update release (timeout, possibly backend is runing, please wait!)',
222
+ NotificationColor.Error
223
+ );
215
224
  return;
216
225
  }
217
226
  NotificationMessage.sendMessage('Release updated successfully', NotificationColor.Success);
@@ -1,5 +1,4 @@
1
1
  import {
2
- DomUtils,
3
2
  NotificationColor,
4
3
  NotificationMessage,
5
4
  CssProps,
@@ -8,8 +7,8 @@ import {
8
7
  mountInnerComponent,
9
8
  downloadLink,
10
9
  } from 'lupine.components';
11
- import { adminFrameProps } from './admin-frame-props';
12
10
  import { TableDataPage } from './admin-table-data';
11
+ import { adminFrameHelper } from './admin-frame-helper';
13
12
 
14
13
  const fetchTableList = async () => {
15
14
  const data = await getRenderPageProps().renderPageFunctions.fetchData('/api/admin/db/tables/list');
@@ -29,10 +28,10 @@ const fetchTableTruncateAll = async () => {
29
28
  };
30
29
 
31
30
  export const TableListPage = () => {
32
- const refUpdate = adminFrameProps.tabsHook;
31
+ const refUpdate = adminFrameHelper.getTabsHook();
33
32
 
34
33
  const openTablePanel = async (tableName: string) => {
35
- if (refUpdate?.getCount && refUpdate.getCount() > adminFrameProps.maxTabsCount) {
34
+ if (refUpdate?.getCount && refUpdate.getCount() > adminFrameHelper.getMaxTabsCount()) {
36
35
  alert('You are opening too many pages');
37
36
  return;
38
37
  }
package/admin/index.ts CHANGED
@@ -1,6 +1,9 @@
1
1
  export * from './admin-css';
2
+ export * from './admin-db';
3
+ export * from './admin-frame';
4
+ export * from './admin-frame-helper';
2
5
  export * from './admin-index';
3
6
  export * from './admin-login';
4
- // export * from './admin-users';
5
- export * from './admin-frame';
6
- export * from './admin-db';
7
+ export * from './admin-release';
8
+ export * from './admin-tokens';
9
+ export * from './admin-performance';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lupine.api",
3
- "version": "1.1.45",
3
+ "version": "1.1.47",
4
4
  "license": "MIT",
5
5
  "author": "uuware.com",
6
6
  "homepage": "https://github.com/uuware/lupine.js",
@@ -0,0 +1,205 @@
1
+ import { ServerResponse } from 'http';
2
+ import { ApiHelper } from '../api';
3
+ import { CryptoUtils, Logger } from '../lib';
4
+ import { ServerRequest } from '../models';
5
+
6
+ /*
7
+ dev-admin uses different authentication method from frontend.
8
+ dev-admin only provides fixed username and password authentication, no user maintenance.
9
+ saved cookie name: _token_dev
10
+ */
11
+
12
+ // DEFAULT_ADMIN_PASS is DEFAULT_ADMIN_NAME + ':' + login password hash.
13
+ // Use below command to generate hash:
14
+ // node -e "console.log(require('crypto').createHash('md5').update('admin:F4AZ5O@2fPUjw%f$LmhZpJTQ^DoXnWPkH#hqE', 'utf8').digest('hex'))"
15
+ export type DevAdminSessionProps = {
16
+ u: string; // username
17
+ t: string; // type: admin, user
18
+ ip: string;
19
+ h: string; // md5 of name+pass
20
+ };
21
+
22
+ /*
23
+ dev admin has more permissions than app admin, and the dashboard also supports for app admin only users.
24
+ app admin is supposed to manage the application, not the site, and may have different fields in cookie.
25
+ This is a sample how to set login process for app admin.
26
+
27
+ export const appAdminHookSetCookie: AppAdminHookSetCookieProps = async (
28
+ req: ServerRequest,
29
+ res: ServerResponse,
30
+ username: string
31
+ ) => {
32
+ const cryptoKey = process.env['CRYPTO_KEY'];
33
+ const u = process.env['ADMIN_USER'];
34
+ const p = process.env['ADMIN_PASS'];
35
+ if (!cryptoKey || !u || !p) {
36
+ return {};
37
+ }
38
+
39
+ const specialToken = CryptoUtils.hash((u + ':' + p) as string);
40
+ const loginJson: LoginJsonProps = {
41
+ ip: '',
42
+ id: 0,
43
+ u: u,
44
+ t: 'admin',
45
+ h: specialToken,
46
+ };
47
+
48
+ const token = JSON.stringify(loginJson);
49
+ const tokenCookie = CryptoUtils.encrypt(token, cryptoKey);
50
+ const response = {
51
+ status: 'ok',
52
+ message: langHelper.getLang('shared:login_success'),
53
+ result: tokenCookie,
54
+ user: {
55
+ u: loginJson.u,
56
+ t: loginJson.t,
57
+ },
58
+ };
59
+
60
+ // sameSite: 'none' needs secure=true
61
+ req.locals.setCookie('_token', tokenCookie, {
62
+ expireDays: 360,
63
+ path: '/',
64
+ httpOnly: false,
65
+ secure: true,
66
+ sameSite: 'none',
67
+ });
68
+ return response;
69
+ };
70
+
71
+ export const appAdminHookCheckLogin: AppAdminHookCheckLoginProps = async (
72
+ req: ServerRequest,
73
+ res: ServerResponse,
74
+ username: string,
75
+ password: string
76
+ ) => {
77
+ if (process.env['ADMIN_PASS'] && username === process.env['ADMIN_USER'] && password === process.env['ADMIN_PASS']) {
78
+ const appAdminResponse = await appAdminHookSetCookie(req, res, username);
79
+ ApiHelper.sendJson(req, res, appAdminResponse);
80
+ return true;
81
+ }
82
+ return false;
83
+ };
84
+
85
+ adminHelper.setAppAdminHookSetCookie(appAdminHookSetCookie);
86
+ adminHelper.setAppAdminHookCheckLogin(appAdminHookCheckLogin);
87
+ */
88
+ export type AppAdminHookSetCookieProps = (req: ServerRequest, res: ServerResponse, username: string) => Promise<any>;
89
+ export type AppAdminHookCheckLoginProps = (req: ServerRequest, res: ServerResponse, username: string, password: string) => Promise<boolean>;
90
+ export type AppAdminHookLogoutProps = (req: ServerRequest, res: ServerResponse) => Promise<void>;
91
+
92
+ export const DEV_ADMIN_TYPE = 'dev-admin';
93
+ export const DEV_ADMIN_CRYPTO_KEY_NAME = 'DEV_CRYPTO_KEY';
94
+ export const DEV_ADMIN_SESSION_NAME = '_token_dev';
95
+ export class AdminApiHelper {
96
+ private static instance: AdminApiHelper;
97
+ private logger = new Logger('admin-api');
98
+
99
+ private constructor() {}
100
+
101
+ public static getInstance(): AdminApiHelper {
102
+ if (!AdminApiHelper.instance) {
103
+ AdminApiHelper.instance = new AdminApiHelper();
104
+ }
105
+ return AdminApiHelper.instance;
106
+ }
107
+
108
+ private AppAdminHookSetCookie?: AppAdminHookSetCookieProps;
109
+ setAppAdminHookSetCookie(hook: AppAdminHookSetCookieProps) {
110
+ this.AppAdminHookSetCookie = hook;
111
+ }
112
+ getAppAdminHookSetCookie() {
113
+ return this.AppAdminHookSetCookie;
114
+ }
115
+
116
+ private AppAdminHookCheckLogin?: AppAdminHookCheckLoginProps;
117
+ setAppAdminHookCheckLogin(hook: AppAdminHookCheckLoginProps) {
118
+ this.AppAdminHookCheckLogin = hook;
119
+ }
120
+ getAppAdminHookCheckLogin() {
121
+ return this.AppAdminHookCheckLogin;
122
+ }
123
+
124
+ private AppAdminHookLogout?: AppAdminHookLogoutProps;
125
+ setAppAdminHookLogout(hook: AppAdminHookLogoutProps) {
126
+ this.AppAdminHookLogout = hook;
127
+ }
128
+ getAppAdminHookLogout() {
129
+ return this.AppAdminHookLogout;
130
+ }
131
+
132
+ decryptJson(text: string) {
133
+ const cryptoKey = process.env[DEV_ADMIN_CRYPTO_KEY_NAME];
134
+ if (cryptoKey && text) {
135
+ try {
136
+ const deCrypto = CryptoUtils.decrypt(text, cryptoKey);
137
+ const json = JSON.parse(deCrypto);
138
+ return json;
139
+ } catch (error: any) {
140
+ this.logger.error(error.message);
141
+ }
142
+ }
143
+ return false;
144
+ }
145
+
146
+ encryptJson(jsonOrText: string | object) {
147
+ const cryptoKey = process.env[DEV_ADMIN_CRYPTO_KEY_NAME];
148
+ if (cryptoKey && jsonOrText) {
149
+ try {
150
+ const text = typeof jsonOrText === 'string' ? jsonOrText : JSON.stringify(jsonOrText);
151
+ const encryptText = CryptoUtils.encrypt(text, cryptoKey);
152
+ return encryptText;
153
+ } catch (error: any) {
154
+ this.logger.error(error.message);
155
+ }
156
+ }
157
+ return false;
158
+ }
159
+
160
+ async getDevAdminFromCookie(
161
+ req: ServerRequest,
162
+ res: ServerResponse,
163
+ sendResponseWhenError = true
164
+ ): Promise<DevAdminSessionProps | false> {
165
+ try {
166
+ const cookies = req.locals.cookies();
167
+ const token = cookies.get(DEV_ADMIN_SESSION_NAME, '');
168
+ if (token) {
169
+ const json = this.decryptJson(token) as DevAdminSessionProps;
170
+ if (!json || json.t !== DEV_ADMIN_TYPE) {
171
+ if (sendResponseWhenError) {
172
+ const response = {
173
+ status: 'error',
174
+ message: 'Wrong session data, contact site admin please.',
175
+ };
176
+ ApiHelper.sendJson(req, res, response);
177
+ }
178
+ return false;
179
+ }
180
+
181
+ // if it's special admin
182
+ if (json.h && json.u === process.env['DEV_ADMIN_USER']) {
183
+ const hash = CryptoUtils.hash(process.env['DEV_ADMIN_USER'] + ':' + process.env['DEV_ADMIN_PASS']);
184
+ if (json.h === hash) {
185
+ return json;
186
+ }
187
+ }
188
+ return false;
189
+ }
190
+ } catch (error: any) {
191
+ this.logger.error(error.message);
192
+ }
193
+ if (sendResponseWhenError) {
194
+ const response = {
195
+ status: 'error',
196
+ message: 'Please login to use this system.',
197
+ };
198
+ ApiHelper.sendJson(req, res, response);
199
+ }
200
+ return false;
201
+ }
202
+ }
203
+
204
+ // add comment for tree shaking
205
+ export const adminApiHelper = /* @__PURE__ */ AdminApiHelper.getInstance();
@@ -2,7 +2,7 @@ import { ServerResponse } from 'http';
2
2
  // import { AdminUser } from './admin-user';
3
3
  import { AdminDb } from './admin-db';
4
4
  import { AdminMenu } from './admin-menu';
5
- import { devAdminAuth, needDevAdminSession } from './admin-auth';
5
+ import { devAdminAuth, devAdminLogout, needDevAdminSession } from './admin-auth';
6
6
  import { AdminPerformance } from './admin-performance';
7
7
  import { AdminRelease } from './admin-release';
8
8
  import { AdminResources } from './admin-resources';
@@ -10,7 +10,7 @@ import { AdminTokens } from './admin-tokens';
10
10
  import { AdminConfig } from './admin-config';
11
11
  import { Logger } from '../lib';
12
12
  import { IApiBase, ServerRequest } from '../models';
13
- import {ApiRouter } from '../api';
13
+ import { ApiRouter } from '../api';
14
14
 
15
15
  const logger = new Logger('admin-api');
16
16
 
@@ -55,5 +55,8 @@ export class AdminApi implements IApiBase {
55
55
  this.router.use('/auth', async (req: ServerRequest, res: ServerResponse) => {
56
56
  return devAdminAuth(req, res);
57
57
  });
58
+ this.router.use('/logout', async (req: ServerRequest, res: ServerResponse) => {
59
+ return devAdminLogout(req, res);
60
+ });
58
61
  }
59
62
  }
@@ -1,12 +1,13 @@
1
1
  import { ServerResponse } from 'http';
2
2
  import { Logger, ServerRequest, ApiHelper } from 'lupine.api';
3
3
  import { CryptoUtils } from '../lib/utils/crypto';
4
- import { adminHelper, DEV_ADMIN_CRYPTO_KEY_NAME, DEV_ADMIN_TYPE, DevAdminSessionProps } from './admin-helper';
4
+ import { adminApiHelper, DEV_ADMIN_CRYPTO_KEY_NAME, DEV_ADMIN_TYPE, DevAdminSessionProps } from './admin-api-helper';
5
5
  import { langHelper } from '../lang';
6
6
 
7
7
  const logger = new Logger('admin-auth');
8
+
8
9
  export const needDevAdminSession = async (req: ServerRequest, res: ServerResponse) => {
9
- const devAdminSession = await adminHelper.getDevAdminFromCookie(req, res, true);
10
+ const devAdminSession = await adminApiHelper.getDevAdminFromCookie(req, res, true);
10
11
  if (!devAdminSession) {
11
12
  // return true to skip the rest of the middleware
12
13
  return true;
@@ -18,8 +19,8 @@ export const needDevAdminSession = async (req: ServerRequest, res: ServerRespons
18
19
  export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
19
20
  const cryptoKey = process.env[DEV_ADMIN_CRYPTO_KEY_NAME];
20
21
  if (!cryptoKey) {
21
- const msg = langHelper.getLang('shared:crypto_key_not_set', {
22
- cryptoKey: DEV_ADMIN_CRYPTO_KEY_NAME,
22
+ const msg = langHelper.getLang('shared:name_not_set', {
23
+ name: 'ENV ' + DEV_ADMIN_CRYPTO_KEY_NAME,
23
24
  });
24
25
  logger.error(msg);
25
26
  const response = {
@@ -31,7 +32,7 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
31
32
  }
32
33
  if (!process.env['DEV_ADMIN_PASS']) {
33
34
  const msg = langHelper.getLang('shared:name_not_set', {
34
- name: 'DEV_ADMIN_PASS',
35
+ name: 'ENV DEV_ADMIN_PASS',
35
36
  });
36
37
  logger.error(msg);
37
38
  const response = {
@@ -46,14 +47,34 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
46
47
  const data = req.locals.json();
47
48
  if (!data || Array.isArray(data) || !data.u || !data.p) {
48
49
  // if session already exists, use session data login
49
- const devAdminSession = await adminHelper.getDevAdminFromCookie(req, res, true);
50
+ const devAdminSession = await adminApiHelper.getDevAdminFromCookie(req, res, false);
50
51
  if (!devAdminSession) {
52
+ // check is app admin
53
+ const appAdminHookCheckLogin = adminApiHelper.getAppAdminHookCheckLogin();
54
+ if (appAdminHookCheckLogin) {
55
+ if (await appAdminHookCheckLogin(req, res, '', '')) {
56
+ return true;
57
+ }
58
+ }
59
+
60
+ const response = {
61
+ status: 'error',
62
+ message: 'Please login to use this system.',
63
+ };
64
+ ApiHelper.sendJson(req, res, response);
51
65
  return true;
52
66
  }
67
+ // if it's dev admin, then set app admin cookie as well
68
+ let addLoginResponse = {};
69
+ const appAdminHookSetCookie = adminApiHelper.getAppAdminHookSetCookie();
70
+ if (appAdminHookSetCookie) {
71
+ addLoginResponse = await appAdminHookSetCookie(req, res, devAdminSession.u);
72
+ }
53
73
  const response = {
74
+ ...addLoginResponse,
54
75
  status: 'ok',
55
76
  message: langHelper.getLang('shared:login_success'),
56
- result: CryptoUtils.encrypt(JSON.stringify(devAdminSession), cryptoKey),
77
+ devLogin: CryptoUtils.encrypt(JSON.stringify(devAdminSession), cryptoKey),
57
78
  };
58
79
  ApiHelper.sendJson(req, res, response);
59
80
  return true;
@@ -68,15 +89,40 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
68
89
  h: CryptoUtils.hash(data.u + ':' + data.p),
69
90
  };
70
91
  const token = JSON.stringify(devSession);
92
+ const tokenCookie = CryptoUtils.encrypt(token, cryptoKey);
93
+
94
+ // if it's dev admin, then set app admin cookie as well
95
+ let addLoginResponse = {};
96
+ const appAdminHookSetCookie = adminApiHelper.getAppAdminHookSetCookie();
97
+ if (appAdminHookSetCookie) {
98
+ addLoginResponse = await appAdminHookSetCookie(req, res, data.u);
99
+ }
100
+
71
101
  const response = {
102
+ ...addLoginResponse,
72
103
  status: 'ok',
73
104
  message: langHelper.getLang('shared:login_success'),
74
- result: CryptoUtils.encrypt(token, cryptoKey),
105
+ devLogin: tokenCookie,
75
106
  };
107
+ req.locals.setCookie('_token', tokenCookie, {
108
+ expireDays: 360,
109
+ path: '/',
110
+ httpOnly: false,
111
+ secure: true,
112
+ sameSite: 'none',
113
+ });
76
114
  ApiHelper.sendJson(req, res, response);
77
115
  return true;
78
116
  }
79
117
 
118
+ // check is app admin
119
+ const appAdminHookCheckLogin = adminApiHelper.getAppAdminHookCheckLogin();
120
+ if (appAdminHookCheckLogin) {
121
+ if (await appAdminHookCheckLogin(req, res, data.u as string, data.p as string)) {
122
+ return true;
123
+ }
124
+ }
125
+
80
126
  logger.info(`dev admin login failed: ${((data.u as string) || '').substring(0, 30)}`);
81
127
  const response = {
82
128
  status: 'error',
@@ -85,3 +131,10 @@ export const devAdminAuth = async (req: ServerRequest, res: ServerResponse) => {
85
131
  ApiHelper.sendJson(req, res, response);
86
132
  return true;
87
133
  };
134
+
135
+ export const devAdminLogout = async (req: ServerRequest, res: ServerResponse) => {
136
+ req.locals.setCookie('_token_dev', '', { expireDays: 360, path: '/', httpOnly: false, secure: true, sameSite: 'none' });
137
+ await adminApiHelper.getAppAdminHookLogout()?.(req, res);
138
+ ApiHelper.sendJson(req, res, { status: 'ok', message: langHelper.getLang('shared:process_completed') });
139
+ return true;
140
+ };
@@ -1,18 +1,7 @@
1
1
  import { ServerResponse } from 'http';
2
2
  import * as fs from 'fs/promises';
3
- import {
4
- IApiBase,
5
- Logger,
6
- apiCache,
7
- ServerRequest,
8
- ApiRouter,
9
- ApiHelper,
10
- langHelper,
11
- FsUtils,
12
- adminHelper,
13
- } from 'lupine.api';
3
+ import { IApiBase, Logger, apiCache, ServerRequest, ApiRouter, ApiHelper, langHelper, FsUtils } from 'lupine.api';
14
4
  import path from 'path';
15
- import { needDevAdminSession } from './admin-auth';
16
5
 
17
6
  export class AdminConfig implements IApiBase {
18
7
  private logger = new Logger('config-api');
@@ -16,7 +16,7 @@ import {
16
16
  AppCacheGlobal,
17
17
  getAppCache,
18
18
  } from 'lupine.api';
19
- import { adminHelper } from './admin-helper';
19
+ import { adminApiHelper } from './admin-api-helper';
20
20
  import { needDevAdminSession } from './admin-auth';
21
21
 
22
22
  // #https://github.com/sebhildebrandt/systeminformation
@@ -38,7 +38,7 @@ export class AdminPerformance implements IApiBase {
38
38
  }
39
39
 
40
40
  async performanceData(req: ServerRequest, res: ServerResponse) {
41
- const json = adminHelper.getDevAdminFromCookie(req, res, true);
41
+ const json = adminApiHelper.getDevAdminFromCookie(req, res, true);
42
42
  if (!json) {
43
43
  return false;
44
44
  }