work-license-server 1.0.18 → 1.0.19

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/assets/admin.js CHANGED
@@ -125,7 +125,7 @@
125
125
  ind.style.width = active.offsetWidth + 'px';
126
126
  }
127
127
 
128
- function showAdminApp(login = 'BOSS') {
128
+ function showAdminApp(login = 'Администратор') {
129
129
  $('#adminLoginScreen').style.display = 'none';
130
130
  $('#adminAppShell').style.display = '';
131
131
  if ($('#admUserLabel')) $('#admUserLabel').textContent = login;
@@ -191,7 +191,7 @@
191
191
  throw new Error(user.error || 'Неверный код подтверждения');
192
192
  }
193
193
  if (!user.isAdmin) {
194
- throw new Error(`Аккаунт ${user.email} не обладает правами администратора (BOSS) сервера лицензирования.`);
194
+ throw new Error(`Аккаунт ${user.email} не обладает правами администратора сервера лицензирования.`);
195
195
  }
196
196
  setStoredToken(user.sessionKey, user.email, user);
197
197
  resetAdmStep();
@@ -309,7 +309,7 @@
309
309
  if ($('#navAdmServers')) $('#navAdmServers').textContent = `Серверы и лицензии (${licenses.length})`;
310
310
  if ($('#navAdmFranchises')) $('#navAdmFranchises').textContent = `Франшизы (${activeFranchises.length})`;
311
311
  if ($('#navAdmOrders')) $('#navAdmOrders').textContent = `Заказы и счета (${orders.length})`;
312
- if ($('#navAdmUsers')) $('#navAdmUsers').textContent = `Клиенты и роли (${users.length})`;
312
+ if ($('#navAdmUsers')) $('#navAdmUsers').textContent = `Клиенты и администраторы (${users.length})`;
313
313
  if ($('#navAdmTickets')) $('#navAdmTickets').textContent = `Тикеты поддержки (${openTickets.length})`;
314
314
 
315
315
  renderServersTable(licenses);
@@ -351,7 +351,7 @@
351
351
  const baseHtml = l.baseActivated
352
352
  ? `<span class="tag ok">✓ Активна (${l.baseSeats || 10} вечн. + ИИ)</span>
353
353
  <div style="margin-top:4px"><button class="btn btn-ghost btn-sm" style="padding:3px 8px;font-size:11.5px;color:var(--danger)" data-adm-base="${esc(lid)}" data-activate="0">Отозвать базовую</button></div>`
354
- : `<span class="tag">Не активирована (1 сессия BOSS)</span>
354
+ : `<span class="tag">Не активирована (1 сессия)</span>
355
355
  <div style="margin-top:4px"><button class="btn btn-ok btn-sm" style="padding:3px 8px;font-size:11.5px" data-adm-base="${esc(lid)}" data-activate="1">Активировать базовую</button></div>`;
356
356
 
357
357
  const hwidHtml = hwidBound
@@ -543,7 +543,7 @@
543
543
  }).join('') || '<tr><td colspan="6" class="muted">Заказов по заданному фильтру не найдено</td></tr>';
544
544
  }
545
545
 
546
- /* 4. Таблица клиентов и ролей BOSS */
546
+ /* 4. Таблица клиентов и администраторов */
547
547
  function renderUsersTable(users = []) {
548
548
  const tbody = $('#admUsersBody');
549
549
  if (!tbody) return;
@@ -562,8 +562,8 @@
562
562
  <td><b>${esc(u.email)}</b><div class="small muted"><code>${esc(u.userId)}</code></div></td>
563
563
  <td>
564
564
  ${u.isAdmin
565
- ? `<span class="tag ok">BOSS · Администратор</span> <button class="btn btn-ghost btn-sm" style="margin-left:6px" data-toggle-admin="${esc(u.userId)}" data-make-admin="0">Снять права</button>`
566
- : `<span class="tag">Клиент</span> <button class="btn btn-ghost btn-sm" style="margin-left:6px" data-toggle-admin="${esc(u.userId)}" data-make-admin="1">Назначить BOSS</button>`}
565
+ ? `<span class="tag ok">Администратор</span> <button class="btn btn-ghost btn-sm" style="margin-left:6px" data-toggle-admin="${esc(u.userId)}" data-make-admin="0">Снять права</button>`
566
+ : `<span class="tag">Клиент</span> <button class="btn btn-ghost btn-sm" style="margin-left:6px" data-toggle-admin="${esc(u.userId)}" data-make-admin="1">Сделать администратором</button>`}
567
567
  </td>
568
568
  <td><b>${esc(u.companyName || '—')}</b><div class="small muted">ИНН ${esc(u.inn || '—')}</div></td>
569
569
  <td>Серверов: <b>${srvCount}</b> · Франшиз: <b>${frCount}</b></td>
package/assets/landing.js CHANGED
@@ -236,7 +236,7 @@
236
236
  if ($('#authLoggedEmail')) $('#authLoggedEmail').textContent = currentUser.email || '';
237
237
  if ($('#authLoggedRoleBadge')) {
238
238
  $('#authLoggedRoleBadge').innerHTML = currentUser.isAdmin
239
- ? '<span class="tag ok">BOSS · Главный администратор</span>'
239
+ ? '<span class="tag ok">Администратор портала</span>'
240
240
  : '<span class="tag">Клиент ODANT-WORK</span>';
241
241
  }
242
242
  if ($('#btnGoAdminModal')) $('#btnGoAdminModal').style.display = currentUser.isAdmin ? '' : 'none';
@@ -420,8 +420,8 @@
420
420
  if ($('#authOfertaCheck')) $('#authOfertaCheck').checked = Boolean(currentUser.ofertaAccepted);
421
421
  if ($('#userBadgeBox')) {
422
422
  const orgInfo = currentUser.companyName ? `${esc(currentUser.companyName)}${currentUser.inn ? ' (ИНН ' + esc(currentUser.inn) + ')' : ''} · ` : '';
423
- const bossBadge = currentUser.isAdmin ? `<span class="tag ok" style="margin-right:6px">BOSS · Администратор</span> <a href="/admin" style="font-weight:700;margin-right:8px">Открыть Админ-панель →</a> · ` : '';
424
- $('#userBadgeBox').innerHTML = `${bossBadge}${orgInfo}Аккаунт: <b>${esc(currentUser.email)}</b> · <a href="#" data-action="logout" style="color:var(--muted)">Выйти</a>`;
423
+ const adminBadge = currentUser.isAdmin ? `<span class="tag ok" style="margin-right:6px">Администратор</span> <a href="/admin" style="font-weight:700;margin-right:8px">Открыть Админ-панель →</a> · ` : '';
424
+ $('#userBadgeBox').innerHTML = `${adminBadge}${orgInfo}Аккаунт: <b>${esc(currentUser.email)}</b> · <a href="#" data-action="logout" style="color:var(--muted)">Выйти</a>`;
425
425
  }
426
426
  syncClientServerPicker();
427
427
  renderCabinetServers();
@@ -506,7 +506,7 @@
506
506
 
507
507
  const baseBadge = s.baseActivated
508
508
  ? `<span class="tag ok">✓ Базовая: ${s.baseSeats || 10} вечн. мест + ИИ</span>`
509
- : `<span class="tag">Базовая не активна (1 сессия BOSS)</span>`;
509
+ : `<span class="tag">Базовая не активирована (1 сессия)</span>`;
510
510
 
511
511
  const files = s.licenseFiles || [];
512
512
  const activeAddons = s.activeAddons || [];
package/bin/server.mjs CHANGED
@@ -14,4 +14,4 @@ const server = await app.listen(port);
14
14
  const addr = server.address();
15
15
  const actualPort = typeof addr === 'object' && addr ? addr.port : port;
16
16
  console.log(`[work.odant.org] Витрина ODANT-WORK: http://localhost:${actualPort}/`);
17
- console.log(`[work.odant.org] Панель администратора (BOSS): http://localhost:${actualPort}/admin (первый вошедший по Email становится BOSS)`);
17
+ console.log(`[work.odant.org] Панель администратора: http://localhost:${actualPort}/admin`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "work-license-server",
3
- "version": "1.0.18",
3
+ "version": "1.0.19",
4
4
  "description": "Лицензионный сервер, биллинг ЮKassa, боты поддержки (MAX, Telegram, VK) и лендинг ПАК WORK (work.odant.org)",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/admin.js CHANGED
@@ -58,14 +58,14 @@ export function renderAdminPage({ publicKey = '', assetVersion = '' } = {}) {
58
58
  <div class="modal-head" style="margin-bottom:18px">
59
59
  <img src="/assets/odant-logo.png" alt="ODANT">
60
60
  <div>
61
- <span class="kicker">Защищённый контур BOSS</span>
61
+ <span class="kicker">Защищённый контур</span>
62
62
  <h1 class="h3" style="margin:4px 0 2px;font-size:21px">Админ-панель ODANT-WORK</h1>
63
63
  <div class="small muted">Вход по вашему Email администратора с 6-значным кодом из письма</div>
64
64
  </div>
65
65
  </div>
66
66
  <div id="admStepEmail">
67
67
  <div class="field">
68
- <label for="admLoginEmail">Email администратора (BOSS)</label>
68
+ <label for="admLoginEmail">Email администратора</label>
69
69
  <input type="email" id="admLoginEmail" value="" placeholder="Введите ваш email…" autocomplete="email" required>
70
70
  </div>
71
71
  <button type="button" class="btn btn-primary btn-lg" style="width:100%" id="btnAdmSendCode" data-action="adm-send-code">
@@ -115,7 +115,7 @@ export function renderAdminPage({ publicKey = '', assetVersion = '' } = {}) {
115
115
 
116
116
  <div class="top-actions">
117
117
  <button class="icon-btn" id="btnTheme" title="Светлая / тёмная тема" aria-label="Переключить тему">${icon('sun')}</button>
118
- <button class="btn btn-primary btn-sm" data-action="open-adm-profile" title="Аккаунт администратора">${icon('user')}<span id="admUserLabel">BOSS</span></button>
118
+ <button class="btn btn-primary btn-sm" data-action="open-adm-profile" title="Аккаунт администратора">${icon('user')}<span id="admUserLabel">Администратор</span></button>
119
119
  </div>
120
120
  </header>
121
121
 
@@ -127,7 +127,7 @@ export function renderAdminPage({ publicKey = '', assetVersion = '' } = {}) {
127
127
  <button type="button" class="sec-nav-item" data-adm-tab="franchises" id="navAdmFranchises">Франшизы (0)</button>
128
128
  <div class="sec-nav-sep"></div>
129
129
  <button type="button" class="sec-nav-item" data-adm-tab="orders" id="navAdmOrders">Заказы и счета (0)</button>
130
- <button type="button" class="sec-nav-item" data-adm-tab="users" id="navAdmUsers">Клиенты и роли (0)</button>
130
+ <button type="button" class="sec-nav-item" data-adm-tab="users" id="navAdmUsers">Клиенты и администраторы (0)</button>
131
131
  <button type="button" class="sec-nav-item" data-adm-tab="tickets" id="navAdmTickets">Тикеты поддержки (0)</button>
132
132
  </aside>
133
133
 
@@ -223,10 +223,10 @@ export function renderAdminPage({ publicKey = '', assetVersion = '' } = {}) {
223
223
  </div>
224
224
  </div>
225
225
 
226
- <!-- 4. КЛИЕНТЫ И РОЛИ BOSS -->
226
+ <!-- 4. КЛИЕНТЫ И АДМИНИСТРАТОРЫ -->
227
227
  <div data-adm-sec="users" style="display:none">
228
228
  <div class="sec-bar" style="margin-bottom:12px">
229
- <h2 class="sec-title">Зарегистрированные клиенты и права администраторов (BOSS)</h2>
229
+ <h2 class="sec-title">Зарегистрированные клиенты и администраторы</h2>
230
230
  <div class="sec-controls">
231
231
  <input type="search" id="inpFilterUsers" placeholder="Поиск по Email, организации, ИНН…">
232
232
  </div>
@@ -416,7 +416,7 @@ export function renderAdminPage({ publicKey = '', assetVersion = '' } = {}) {
416
416
  <div style="padding:14px 16px;border-radius:12px;border:1px solid var(--line-strong);background:var(--field);margin-bottom:14px">
417
417
  <div class="small muted">Вы вошли как</div>
418
418
  <div style="font-size:16px;font-weight:700;margin-top:2px" id="admProfileEmail">—</div>
419
- <div style="margin-top:6px"><span class="tag ok">BOSS · Главный администратор</span></div>
419
+ <div style="margin-top:6px"><span class="tag ok">Администратор портала</span></div>
420
420
  </div>
421
421
  <div style="display:flex;flex-direction:column;gap:8px">
422
422
  <a class="btn btn-primary" href="/#addons" style="width:100%;text-decoration:none">Перейти в Личный кабинет</a>
package/src/server.js CHANGED
@@ -940,7 +940,7 @@ export function createLicenseServerApp(options = {}) {
940
940
  const body = await readJsonBody(req);
941
941
  const tok = extractBearerToken(req, body, url);
942
942
  if (!store.verifyAdminToken(tok))
943
- return sendJson(res, 401, { error: 'Требуется авторизация администратора (BOSS)' });
943
+ return sendJson(res, 401, { error: 'Требуется авторизация администратора' });
944
944
  const updated = store.setUserAdminRole(body.userId || body.email, body.isAdmin !== false);
945
945
  return sendJson(res, 200, { ok: true, user: updated });
946
946
  }
package/src/store.js CHANGED
@@ -149,14 +149,14 @@ export class LicenseStore {
149
149
  login: userFromTok.email,
150
150
  email: userFromTok.email,
151
151
  userId: userFromTok.userId,
152
- role: 'BOSS',
152
+ role: 'ADMIN',
153
153
  };
154
154
  }
155
155
  if (clean === this.adminPassword && this.adminPassword.length >= 6) {
156
156
  return {
157
157
  authenticated: true,
158
158
  login: this.adminLogin,
159
- role: 'BOSS',
159
+ role: 'ADMIN',
160
160
  };
161
161
  }
162
162
  const sess = this.adminSessions.get(clean);
@@ -169,12 +169,12 @@ export class LicenseStore {
169
169
  return {
170
170
  authenticated: true,
171
171
  login: sess.login || this.adminLogin,
172
- role: 'BOSS',
172
+ role: 'ADMIN',
173
173
  };
174
174
  }
175
175
 
176
176
  /**
177
- * Гарантировать, что первый зарегистрированный на сервере пользователь является главным Администратором (BOSS).
177
+ * Гарантировать, что первый зарегистрированный на сервере пользователь является администратором портала.
178
178
  */
179
179
  _ensureBootstrapAdmin() {
180
180
  const allUsers = Object.values(this.state.users || {});
@@ -182,19 +182,19 @@ export class LicenseStore {
182
182
  return null;
183
183
  const existingAdmin = allUsers.find(u => u.isAdmin);
184
184
  if (existingAdmin) {
185
- existingAdmin.role = 'BOSS';
185
+ existingAdmin.role = 'ADMIN';
186
186
  return existingAdmin;
187
187
  }
188
188
  const firstUser = [...allUsers].sort((a, b) => (a.createdAt || 0) - (b.createdAt || 0))[0];
189
189
  if (firstUser) {
190
190
  firstUser.isAdmin = true;
191
- firstUser.role = 'BOSS';
191
+ firstUser.role = 'ADMIN';
192
192
  }
193
193
  return firstUser || null;
194
194
  }
195
195
 
196
196
  /**
197
- * Назначить или снять права администратора (BOSS) у пользователя по Email или userId.
197
+ * Назначить или снять права администратора у пользователя по Email или userId.
198
198
  */
199
199
  setUserAdminRole(emailOrUserId = '', isAdmin = true) {
200
200
  const key = String(emailOrUserId || '').trim();
@@ -207,11 +207,11 @@ export class LicenseStore {
207
207
  if (!nextAdmin && user.isAdmin) {
208
208
  const otherAdmins = Object.values(this.state.users || {}).filter(u => u.isAdmin && u.userId !== user.userId);
209
209
  if (!otherAdmins.length) {
210
- throw new Error('Нельзя снять права BOSS у единственного администратора сервера');
210
+ throw new Error('Нельзя снять права у единственного администратора сервера');
211
211
  }
212
212
  }
213
213
  user.isAdmin = nextAdmin;
214
- user.role = nextAdmin ? 'BOSS' : 'USER';
214
+ user.role = nextAdmin ? 'ADMIN' : 'CLIENT';
215
215
  this._save();
216
216
  return this._formatUserResponse(user);
217
217
  }
@@ -1229,7 +1229,7 @@ export class LicenseStore {
1229
1229
  if (user) {
1230
1230
  if (verifiedPayload.isAdmin) {
1231
1231
  user.isAdmin = true;
1232
- user.role = 'BOSS';
1232
+ user.role = 'ADMIN';
1233
1233
  }
1234
1234
  user.sessionKey = key;
1235
1235
  try { this._save(); } catch { /* ignore */ }
@@ -1456,7 +1456,7 @@ export class LicenseStore {
1456
1456
  userId: user.userId,
1457
1457
  email: user.email,
1458
1458
  isAdmin: Boolean(user.isAdmin),
1459
- role: user.isAdmin ? 'BOSS' : 'USER',
1459
+ role: user.isAdmin ? 'ADMIN' : 'CLIENT',
1460
1460
  authProvider: user.authProvider || 'email',
1461
1461
  name: user.name,
1462
1462
  position: user.position || '',
@@ -1590,7 +1590,7 @@ export class LicenseStore {
1590
1590
  const isFirstAdmin = !Object.values(this.state.users || {}).some(u => u.isAdmin);
1591
1591
  if (isFirstAdmin) {
1592
1592
  user.isAdmin = true;
1593
- user.role = 'BOSS';
1593
+ user.role = 'ADMIN';
1594
1594
  }
1595
1595
 
1596
1596
  // Выпускаем криптографически подписанный бессрочный токен сессии (wks_1...), устойчивый к перезапускам сервера