@naisys/erp 3.0.0-beta.45 → 3.0.0-beta.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.
- package/client-dist/assets/{index-BWVp_WEm.js → index-Bu_bS_Vd.js} +723 -698
- package/client-dist/index.html +1 -1
- package/dist/{erpDb.js → database/erpDb.js} +1 -1
- package/dist/erpRoutes.js +28 -28
- package/dist/erpServer.js +7 -7
- package/dist/{auth-middleware.js → middleware/auth-middleware.js} +1 -1
- package/dist/route-helpers.js +2 -2
- package/dist/routes/admin.js +3 -3
- package/dist/routes/audit.js +1 -1
- package/dist/routes/{item-fields.js → items/item-fields.js} +7 -7
- package/dist/routes/{item-instances.js → items/item-instances.js} +7 -7
- package/dist/routes/{items.js → items/items.js} +5 -5
- package/dist/routes/{operation-dependencies.js → operations/operation-dependencies.js} +6 -6
- package/dist/routes/{operation-field-refs.js → operations/operation-field-refs.js} +6 -6
- package/dist/routes/{operation-run-comments.js → operations/operation-run-comments.js} +5 -5
- package/dist/routes/{operation-run-transitions.js → operations/operation-run-transitions.js} +6 -6
- package/dist/routes/{operation-runs.js → operations/operation-runs.js} +5 -5
- package/dist/routes/{operations.js → operations/operations.js} +6 -6
- package/dist/routes/{order-revision-transitions.js → orders/order-revision-transitions.js} +4 -4
- package/dist/routes/{order-revisions.js → orders/order-revisions.js} +6 -6
- package/dist/routes/{order-run-transitions.js → orders/order-run-transitions.js} +4 -4
- package/dist/routes/{order-runs.js → orders/order-runs.js} +5 -5
- package/dist/routes/{orders.js → orders/orders.js} +5 -5
- package/dist/routes/{dispatch.js → production/dispatch.js} +3 -3
- package/dist/routes/{inventory.js → production/inventory.js} +3 -3
- package/dist/routes/{labor-tickets.js → production/labor-tickets.js} +5 -5
- package/dist/routes/{work-centers.js → production/work-centers.js} +5 -5
- package/dist/routes/root.js +1 -1
- package/dist/routes/{step-field-attachments.js → steps/step-field-attachments.js} +8 -8
- package/dist/routes/{step-fields.js → steps/step-fields.js} +6 -6
- package/dist/routes/{step-run-fields.js → steps/step-run-fields.js} +9 -9
- package/dist/routes/{step-run-transitions.js → steps/step-run-transitions.js} +6 -6
- package/dist/routes/{step-runs.js → steps/step-runs.js} +7 -7
- package/dist/routes/{steps.js → steps/steps.js} +5 -5
- package/dist/routes/{auth.js → users/auth.js} +4 -4
- package/dist/routes/{user-permissions.js → users/user-permissions.js} +4 -4
- package/dist/routes/{users.js → users/users.js} +5 -5
- package/dist/services/attachment-service.js +1 -1
- package/dist/services/{item-instance-service.js → inventory/item-instance-service.js} +2 -2
- package/dist/services/{item-service.js → inventory/item-service.js} +2 -2
- package/dist/services/{operation-dependency-service.js → operations/operation-dependency-service.js} +1 -1
- package/dist/services/{operation-run-comment-service.js → operations/operation-run-comment-service.js} +1 -1
- package/dist/services/{operation-run-service.js → operations/operation-run-service.js} +3 -3
- package/dist/services/{operation-service.js → operations/operation-service.js} +2 -2
- package/dist/services/{step-run-service.js → operations/step-run-service.js} +1 -1
- package/dist/services/{step-service.js → operations/step-service.js} +2 -2
- package/dist/services/{order-revision-service.js → orders/order-revision-service.js} +2 -2
- package/dist/services/{order-run-service.js → orders/order-run-service.js} +2 -2
- package/dist/services/{order-service.js → orders/order-service.js} +2 -2
- package/dist/services/{revision-diff-service.js → orders/revision-diff-service.js} +1 -1
- package/dist/services/{field-ref-service.js → production/field-ref-service.js} +1 -1
- package/dist/services/{field-service.js → production/field-service.js} +2 -2
- package/dist/services/{field-value-service.js → production/field-value-service.js} +1 -1
- package/dist/services/{labor-ticket-service.js → production/labor-ticket-service.js} +1 -1
- package/dist/services/{work-center-service.js → production/work-center-service.js} +2 -2
- package/dist/services/user-service.js +84 -1
- package/npm-shrinkwrap.json +28 -28
- package/package.json +6 -6
- package/dist/userService.js +0 -87
- /package/dist/{dbConfig.js → database/dbConfig.js} +0 -0
- /package/dist/{supervisorAuth.js → middleware/supervisorAuth.js} +0 -0
- /package/dist/{audit.js → services/audit.js} +0 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ErrorResponseSchema, StepRunTransitionSlimSchema, TransitionNoteSchema, } from "@naisys/erp-shared";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { checkOpRunInProgress, checkOrderRunStarted, checkWorkCenterAccess, mutationResult, resolveStepRun, } from "
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
3
|
+
import { conflict, notFound, unprocessable } from "../../error-handler.js";
|
|
4
|
+
import { requirePermission } from "../../middleware/auth-middleware.js";
|
|
5
|
+
import { checkOpRunInProgress, checkOrderRunStarted, checkWorkCenterAccess, mutationResult, resolveStepRun, } from "../../route-helpers.js";
|
|
6
|
+
import { getStepRunWithFields, updateStepRun, } from "../../services/operations/step-run-service.js";
|
|
7
|
+
import { validateCompletionFields } from "../../services/production/field-value-service.js";
|
|
8
|
+
import { isUserClockedIn } from "../../services/production/labor-ticket-service.js";
|
|
9
9
|
import { formatStepRunTransition } from "./step-runs.js";
|
|
10
10
|
const StepSeqNoParamsSchema = z.object({
|
|
11
11
|
orderKey: z.string(),
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { ErrorResponseSchema, fieldTypeString, getValueFormatHint, OperationRunStatus, StepRunListQuerySchema, StepRunListResponseSchema, StepRunSchema, } from "@naisys/erp-shared";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { checkWorkCenterAccess, childItemLinks, formatAuditFields, resolveActions, resolveOpRun, resolveStepRun, } from "
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
3
|
+
import { notFound } from "../../error-handler.js";
|
|
4
|
+
import { API_PREFIX, selfLink } from "../../hateoas.js";
|
|
5
|
+
import { hasPermission } from "../../middleware/auth-middleware.js";
|
|
6
|
+
import { checkWorkCenterAccess, childItemLinks, formatAuditFields, resolveActions, resolveOpRun, resolveStepRun, } from "../../route-helpers.js";
|
|
7
|
+
import { getStepRunWithFields, listStepRuns, listStepRunsWithFields, } from "../../services/operations/step-run-service.js";
|
|
8
|
+
import { deserializeFieldValue, validateCompletionFields, validateFieldValue, } from "../../services/production/field-value-service.js";
|
|
9
|
+
import { isUserClockedIn } from "../../services/production/labor-ticket-service.js";
|
|
10
10
|
export function stepRunResource(orderKey, runNo, seqNo) {
|
|
11
11
|
return `orders/${orderKey}/runs/${runNo}/ops/${seqNo}/steps`;
|
|
12
12
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { BatchCreateStepSchema, BatchSeqNoCreateResponseSchema, CreateStepSchema, ErrorResponseSchema, MutateResponseSchema, RevisionStatus, SeqNoCreateResponseSchema, StepListResponseSchema, StepSchema, UpdateStepSchema, } from "@naisys/erp-shared";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { calcNextSeqNo, childItemLinks, draftCrudActions, formatAuditFields, mutationResult, resolveActions, resolveOperation, } from "
|
|
7
|
-
import { createStep, createSteps, deleteStep, findExisting, getStep, listSteps, updateStep, } from "
|
|
3
|
+
import { conflict, notFound } from "../../error-handler.js";
|
|
4
|
+
import { API_PREFIX, selfLink } from "../../hateoas.js";
|
|
5
|
+
import { requirePermission } from "../../middleware/auth-middleware.js";
|
|
6
|
+
import { calcNextSeqNo, childItemLinks, draftCrudActions, formatAuditFields, mutationResult, resolveActions, resolveOperation, } from "../../route-helpers.js";
|
|
7
|
+
import { createStep, createSteps, deleteStep, findExisting, getStep, listSteps, updateStep, } from "../../services/operations/step-service.js";
|
|
8
8
|
import { formatFieldListResponse } from "./step-fields.js";
|
|
9
9
|
const ParamsSchema = z.object({
|
|
10
10
|
orderKey: z.string(),
|
|
@@ -3,10 +3,10 @@ import { AuthUserSchema, ErrorResponseSchema, LoginRequestSchema, LoginResponseS
|
|
|
3
3
|
import { deleteSession } from "@naisys/supervisor-database";
|
|
4
4
|
import bcrypt from "bcryptjs";
|
|
5
5
|
import { randomUUID } from "crypto";
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import {
|
|
9
|
-
import { isSupervisorAuth } from "
|
|
6
|
+
import erpDb from "../../database/erpDb.js";
|
|
7
|
+
import { unauthorized } from "../../error-handler.js";
|
|
8
|
+
import { authCache } from "../../middleware/auth-middleware.js";
|
|
9
|
+
import { isSupervisorAuth } from "../../middleware/supervisorAuth.js";
|
|
10
10
|
const SESSION_DURATION_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
11
11
|
export default function authRoutes(fastify) {
|
|
12
12
|
const app = fastify.withTypeProvider();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { ErpPermissionEnum, GrantPermissionSchema } from "@naisys/erp-shared";
|
|
2
2
|
import { z } from "zod/v4";
|
|
3
|
-
import { authCache, requirePermission } from "
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { authCache, requirePermission, } from "../../middleware/auth-middleware.js";
|
|
4
|
+
import { isSupervisorAuth } from "../../middleware/supervisorAuth.js";
|
|
5
|
+
import { mutationResult } from "../../route-helpers.js";
|
|
6
|
+
import { getUserById, getUserByUsername, grantPermission, hasUserApiKey, revokePermission, rotateUserApiKey, } from "../../services/user-service.js";
|
|
7
7
|
import { formatUser } from "./users.js";
|
|
8
8
|
export default function userPermissionRoutes(fastify) {
|
|
9
9
|
const app = fastify.withTypeProvider();
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { ChangePasswordSchema, CreateAgentUserSchema, CreateUserSchema, UpdateUserSchema, } from "@naisys/erp-shared";
|
|
2
2
|
import { getHubAgentById } from "@naisys/hub-database";
|
|
3
3
|
import { z } from "zod/v4";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
4
|
+
import { API_PREFIX, collectionLink, paginationLinks, schemaLink, selfLink, } from "../../hateoas.js";
|
|
5
|
+
import { authCache, hasPermission, requirePermission, } from "../../middleware/auth-middleware.js";
|
|
6
|
+
import { isSupervisorAuth } from "../../middleware/supervisorAuth.js";
|
|
7
|
+
import { mutationResult } from "../../route-helpers.js";
|
|
8
|
+
import { createUserForAgent, createUserWithPassword, deleteUser, getUserByUsername, getUserByUuid, hasUserApiKey, listUsers, updateUser, } from "../../services/user-service.js";
|
|
9
9
|
function userItemLinks(username) {
|
|
10
10
|
return [
|
|
11
11
|
selfLink(`/users/${username}`),
|
|
@@ -2,7 +2,7 @@ import { MAX_ATTACHMENT_SIZE } from "@naisys/common";
|
|
|
2
2
|
import { createHash, randomBytes } from "crypto";
|
|
3
3
|
import { createWriteStream, existsSync, mkdirSync, renameSync, unlinkSync, } from "fs";
|
|
4
4
|
import { join } from "path";
|
|
5
|
-
import erpDb from "../erpDb.js";
|
|
5
|
+
import erpDb from "../database/erpDb.js";
|
|
6
6
|
function attachmentsDir() {
|
|
7
7
|
return join(process.env.NAISYS_FOLDER || "", "attachments");
|
|
8
8
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import erpDb from "
|
|
2
|
-
import { includeUsers } from "
|
|
1
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
|
+
import { includeUsers } from "../../route-helpers.js";
|
|
3
3
|
// --- Prisma include & result type ---
|
|
4
4
|
export const includeItemInstanceRelations = {
|
|
5
5
|
...includeUsers,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import erpDb from "
|
|
2
|
-
import { includeUsers } from "
|
|
1
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
|
+
import { includeUsers } from "../../route-helpers.js";
|
|
3
3
|
// --- Prisma include & result type ---
|
|
4
4
|
export const includeUsersAndFieldSet = {
|
|
5
5
|
...includeUsers,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { OperationRunStatus as OperationRunStatusValues, } from "@naisys/erp-shared";
|
|
2
2
|
import { fieldTypeString, getValueFormatHint, } from "@naisys/erp-shared";
|
|
3
|
+
import erpDb from "../../database/erpDb.js";
|
|
4
|
+
import { API_PREFIX } from "../../hateoas.js";
|
|
3
5
|
import { writeAuditEntry } from "../audit.js";
|
|
4
|
-
import
|
|
5
|
-
import { API_PREFIX } from "../hateoas.js";
|
|
6
|
-
import { deserializeFieldValue, validateFieldValue, } from "./field-value-service.js";
|
|
6
|
+
import { deserializeFieldValue, validateFieldValue, } from "../production/field-value-service.js";
|
|
7
7
|
// --- Prisma include & result type ---
|
|
8
8
|
export const includeOp = {
|
|
9
9
|
operation: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import erpDb from "
|
|
2
|
-
import { calcNextSeqNo, includeUsers, } from "
|
|
1
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
|
+
import { calcNextSeqNo, includeUsers, } from "../../route-helpers.js";
|
|
3
3
|
// --- Prisma include & result type ---
|
|
4
4
|
const includeWorkCenter = {
|
|
5
5
|
workCenter: { select: { key: true } },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import erpDb from "
|
|
2
|
-
import { calcNextSeqNo, includeUsers, } from "
|
|
1
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
|
+
import { calcNextSeqNo, includeUsers, } from "../../route-helpers.js";
|
|
3
3
|
// --- Prisma include & result type ---
|
|
4
4
|
export const includeUsersAndFields = {
|
|
5
5
|
...includeUsers,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RevisionStatus as RevisionStatusValues, } from "@naisys/erp-shared";
|
|
2
|
+
import erpDb from "../../database/erpDb.js";
|
|
3
|
+
import { includeUsers } from "../../route-helpers.js";
|
|
2
4
|
import { writeAuditEntry } from "../audit.js";
|
|
3
|
-
import erpDb from "../erpDb.js";
|
|
4
|
-
import { includeUsers } from "../route-helpers.js";
|
|
5
5
|
// --- Prisma include & result type ---
|
|
6
6
|
const includeRevisionRelations = {
|
|
7
7
|
...includeUsers,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OperationRunStatus as OperationRunStatusValues, OrderRunStatus as OrderRunStatusValues, } from "@naisys/erp-shared";
|
|
2
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
3
|
import { writeAuditEntry } from "../audit.js";
|
|
3
|
-
import
|
|
4
|
-
import { deserializeFieldValue, upsertFieldValue, validateFieldSet, } from "./field-value-service.js";
|
|
4
|
+
import { deserializeFieldValue, upsertFieldValue, validateFieldSet, } from "../production/field-value-service.js";
|
|
5
5
|
// --- Prisma include & result type ---
|
|
6
6
|
export const includeRev = {
|
|
7
7
|
orderRev: { select: { revNo: true, description: true } },
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { RevisionStatus } from "@naisys/erp-shared";
|
|
2
|
-
import erpDb from "
|
|
3
|
-
import { includeUsers } from "
|
|
2
|
+
import erpDb from "../../database/erpDb.js";
|
|
3
|
+
import { includeUsers } from "../../route-helpers.js";
|
|
4
4
|
// --- Prisma include & result type ---
|
|
5
5
|
const includeOrderRelations = {
|
|
6
6
|
...includeUsers,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FieldType } from "@naisys/erp-shared";
|
|
2
|
-
import erpDb from "
|
|
3
|
-
import { calcNextSeqNo, includeUsers, } from "
|
|
2
|
+
import erpDb from "../../database/erpDb.js";
|
|
3
|
+
import { calcNextSeqNo, includeUsers, } from "../../route-helpers.js";
|
|
4
4
|
// --- Lookups ---
|
|
5
5
|
export async function listFields(fieldSetId) {
|
|
6
6
|
return erpDb.field.findMany({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { formatFileSize } from "@naisys/common";
|
|
2
2
|
import { FieldType, } from "@naisys/erp-shared";
|
|
3
|
-
import erpDb from "
|
|
3
|
+
import erpDb from "../../database/erpDb.js";
|
|
4
4
|
// --- Lookups ---
|
|
5
5
|
export async function findStepRunWithField(id, opRunId, fieldSeqNo) {
|
|
6
6
|
const stepRun = await erpDb.stepRun.findUnique({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getLatestRunInfoByUuid, sumCostsByUuid } from "@naisys/hub-database";
|
|
2
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
3
|
import { writeAuditEntry } from "../audit.js";
|
|
3
|
-
import erpDb from "../erpDb.js";
|
|
4
4
|
// --- Prisma include & result type ---
|
|
5
5
|
export const includeLaborTicket = {
|
|
6
6
|
user: { select: { username: true } },
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import erpDb from "
|
|
2
|
-
import { includeUsers } from "
|
|
1
|
+
import erpDb from "../../database/erpDb.js";
|
|
2
|
+
import { includeUsers } from "../../route-helpers.js";
|
|
3
3
|
// --- Prisma include & result type ---
|
|
4
4
|
const includeDetail = {
|
|
5
5
|
...includeUsers,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { SUPER_ADMIN_USERNAME } from "@naisys/common";
|
|
1
2
|
import { generatePersistentUserApiKey } from "@naisys/common-node";
|
|
3
|
+
import { ensureSuperAdmin } from "@naisys/supervisor-database";
|
|
2
4
|
import bcrypt from "bcryptjs";
|
|
3
5
|
import { randomUUID } from "crypto";
|
|
4
|
-
import erpDb from "../erpDb.js";
|
|
6
|
+
import erpDb from "../database/erpDb.js";
|
|
5
7
|
// --- Prisma include & result type ---
|
|
6
8
|
export const includePermissions = {
|
|
7
9
|
permissions: true,
|
|
@@ -112,4 +114,85 @@ export async function rotateUserApiKey(id) {
|
|
|
112
114
|
}),
|
|
113
115
|
});
|
|
114
116
|
}
|
|
117
|
+
// --- Superadmin bootstrap ---
|
|
118
|
+
/**
|
|
119
|
+
* Ensure a superadmin user exists in the local ERP database.
|
|
120
|
+
* If a password is supplied, it is used on create and updates the existing one if present.
|
|
121
|
+
* For standalone mode (no supervisor auth).
|
|
122
|
+
*/
|
|
123
|
+
export async function ensureLocalSuperAdmin(password) {
|
|
124
|
+
const existing = await erpDb.user.findUnique({
|
|
125
|
+
where: { username: SUPER_ADMIN_USERNAME },
|
|
126
|
+
});
|
|
127
|
+
if (existing) {
|
|
128
|
+
await ensureErpAdminPermission(existing.id);
|
|
129
|
+
if (password) {
|
|
130
|
+
const hash = await bcrypt.hash(password, SALT_ROUNDS);
|
|
131
|
+
await erpDb.user.update({
|
|
132
|
+
where: { id: existing.id },
|
|
133
|
+
data: { passwordHash: hash },
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const finalPassword = password || randomUUID().slice(0, 8);
|
|
139
|
+
const hash = await bcrypt.hash(finalPassword, SALT_ROUNDS);
|
|
140
|
+
const user = await erpDb.user.create({
|
|
141
|
+
data: {
|
|
142
|
+
uuid: randomUUID(),
|
|
143
|
+
username: SUPER_ADMIN_USERNAME,
|
|
144
|
+
passwordHash: hash,
|
|
145
|
+
},
|
|
146
|
+
});
|
|
147
|
+
await ensureErpAdminPermission(user.id);
|
|
148
|
+
if (!password) {
|
|
149
|
+
console.log(`\n ${SUPER_ADMIN_USERNAME} user created. Password: ${finalPassword}`);
|
|
150
|
+
console.log(` Change it via the admin UI or with --setup\n`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Warn if agent users exist without supervisor auth
|
|
154
|
+
const agentCount = await erpDb.user.count({ where: { isAgent: true } });
|
|
155
|
+
if (agentCount > 0) {
|
|
156
|
+
console.warn(`[ERP] Warning: ${agentCount} agent user(s) found but supervisor auth is disabled. ` +
|
|
157
|
+
`Agent API key lookups and authentication will not work. ` +
|
|
158
|
+
`Set SUPERVISOR_AUTH=true to enable.`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Sync superadmin from supervisor into ERP DB and ensure permissions.
|
|
163
|
+
* For supervisor auth mode. Supervisor uses passkey-only auth — the
|
|
164
|
+
* mirrored ERP row has no passwordHash.
|
|
165
|
+
*/
|
|
166
|
+
export async function ensureSupervisorSuperAdmin() {
|
|
167
|
+
const result = await ensureSuperAdmin();
|
|
168
|
+
await erpDb.user.upsert({
|
|
169
|
+
where: { uuid: result.user.uuid },
|
|
170
|
+
create: {
|
|
171
|
+
uuid: result.user.uuid,
|
|
172
|
+
username: result.user.username,
|
|
173
|
+
},
|
|
174
|
+
update: {
|
|
175
|
+
username: result.user.username,
|
|
176
|
+
},
|
|
177
|
+
});
|
|
178
|
+
const localSuperAdmin = await erpDb.user.findUnique({
|
|
179
|
+
where: { uuid: result.user.uuid },
|
|
180
|
+
});
|
|
181
|
+
if (localSuperAdmin) {
|
|
182
|
+
await ensureErpAdminPermission(localSuperAdmin.id);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Ensure a user has the erp_admin permission.
|
|
187
|
+
*/
|
|
188
|
+
export async function ensureErpAdminPermission(userId) {
|
|
189
|
+
const existing = await erpDb.userPermission.findUnique({
|
|
190
|
+
where: { userId_permission: { userId, permission: "erp_admin" } },
|
|
191
|
+
});
|
|
192
|
+
if (!existing) {
|
|
193
|
+
await erpDb.userPermission.create({
|
|
194
|
+
data: { userId, permission: "erp_admin" },
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
}
|
|
115
198
|
//# sourceMappingURL=user-service.js.map
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/erp",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.47",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@naisys/erp",
|
|
9
|
-
"version": "3.0.0-beta.
|
|
9
|
+
"version": "3.0.0-beta.47",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@fastify/cookie": "^11.0.2",
|
|
12
12
|
"@fastify/cors": "^11.2.0",
|
|
@@ -14,11 +14,11 @@
|
|
|
14
14
|
"@fastify/rate-limit": "^10.3.0",
|
|
15
15
|
"@fastify/static": "^9.0.0",
|
|
16
16
|
"@fastify/swagger": "^9.7.0",
|
|
17
|
-
"@naisys/common": "3.0.0-beta.
|
|
18
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
19
|
-
"@naisys/erp-shared": "3.0.0-beta.
|
|
20
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
21
|
-
"@naisys/supervisor-database": "3.0.0-beta.
|
|
17
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
18
|
+
"@naisys/common-node": "3.0.0-beta.47",
|
|
19
|
+
"@naisys/erp-shared": "3.0.0-beta.47",
|
|
20
|
+
"@naisys/hub-database": "3.0.0-beta.47",
|
|
21
|
+
"@naisys/supervisor-database": "3.0.0-beta.47",
|
|
22
22
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
23
23
|
"@prisma/client": "^7.5.0",
|
|
24
24
|
"@scalar/fastify-api-reference": "^1.48.7",
|
|
@@ -394,41 +394,41 @@
|
|
|
394
394
|
}
|
|
395
395
|
},
|
|
396
396
|
"node_modules/@naisys/common": {
|
|
397
|
-
"version": "3.0.0-beta.
|
|
398
|
-
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.
|
|
399
|
-
"integrity": "sha512-
|
|
397
|
+
"version": "3.0.0-beta.47",
|
|
398
|
+
"resolved": "https://registry.npmjs.org/@naisys/common/-/common-3.0.0-beta.47.tgz",
|
|
399
|
+
"integrity": "sha512-jRtyDq2GMcCEiuiG6yQAMuMERPzrfQUmTVjUmwXfPakwjNVQyn8Tbz05m2WjB1YRqVXjRCY/SNGjTtrb55TJ5A==",
|
|
400
400
|
"dependencies": {
|
|
401
401
|
"semver": "^7.7.4",
|
|
402
402
|
"zod": "^4.3.6"
|
|
403
403
|
}
|
|
404
404
|
},
|
|
405
405
|
"node_modules/@naisys/common-node": {
|
|
406
|
-
"version": "3.0.0-beta.
|
|
407
|
-
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.
|
|
408
|
-
"integrity": "sha512-
|
|
406
|
+
"version": "3.0.0-beta.47",
|
|
407
|
+
"resolved": "https://registry.npmjs.org/@naisys/common-node/-/common-node-3.0.0-beta.47.tgz",
|
|
408
|
+
"integrity": "sha512-FCwX+ESUI/U9vk1amldCahfMiosxXIWXqvfihCeN1P7B97WZ3bFgJgn7JogXCNRD4axuUMAXPOWSTSjHJSDeWw==",
|
|
409
409
|
"dependencies": {
|
|
410
|
-
"@naisys/common": "3.0.0-beta.
|
|
410
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
411
411
|
"better-sqlite3": "^12.6.2",
|
|
412
412
|
"js-yaml": "^4.1.1",
|
|
413
413
|
"pino": "^10.3.1"
|
|
414
414
|
}
|
|
415
415
|
},
|
|
416
416
|
"node_modules/@naisys/erp-shared": {
|
|
417
|
-
"version": "3.0.0-beta.
|
|
418
|
-
"resolved": "https://registry.npmjs.org/@naisys/erp-shared/-/erp-shared-3.0.0-beta.
|
|
419
|
-
"integrity": "sha512-
|
|
417
|
+
"version": "3.0.0-beta.47",
|
|
418
|
+
"resolved": "https://registry.npmjs.org/@naisys/erp-shared/-/erp-shared-3.0.0-beta.47.tgz",
|
|
419
|
+
"integrity": "sha512-MlTnJ9gA8m366yqEmRFhMXXBO39i3PqqTfW/TNXdyVnWls8vHLU/GjhbPlhjas13J+yXc2Hpukj2eezQ5LIgBA==",
|
|
420
420
|
"dependencies": {
|
|
421
|
-
"@naisys/common": "3.0.0-beta.
|
|
421
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
422
422
|
"zod": "^4.3.6"
|
|
423
423
|
}
|
|
424
424
|
},
|
|
425
425
|
"node_modules/@naisys/hub-database": {
|
|
426
|
-
"version": "3.0.0-beta.
|
|
427
|
-
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.
|
|
428
|
-
"integrity": "sha512-
|
|
426
|
+
"version": "3.0.0-beta.47",
|
|
427
|
+
"resolved": "https://registry.npmjs.org/@naisys/hub-database/-/hub-database-3.0.0-beta.47.tgz",
|
|
428
|
+
"integrity": "sha512-eagwn0cYNsuu2rqLuWRr/D0Se8QvqYa+R8khDtMahb5RjN6q/L4YkLTxEf4RBqw2dfee3kTQbACxwlN27CsL2A==",
|
|
429
429
|
"dependencies": {
|
|
430
|
-
"@naisys/common": "3.0.0-beta.
|
|
431
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
430
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
431
|
+
"@naisys/common-node": "3.0.0-beta.47",
|
|
432
432
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
433
433
|
"@prisma/client": "^7.5.0",
|
|
434
434
|
"better-sqlite3": "^12.6.2",
|
|
@@ -436,12 +436,12 @@
|
|
|
436
436
|
}
|
|
437
437
|
},
|
|
438
438
|
"node_modules/@naisys/supervisor-database": {
|
|
439
|
-
"version": "3.0.0-beta.
|
|
440
|
-
"resolved": "https://registry.npmjs.org/@naisys/supervisor-database/-/supervisor-database-3.0.0-beta.
|
|
441
|
-
"integrity": "sha512-
|
|
439
|
+
"version": "3.0.0-beta.47",
|
|
440
|
+
"resolved": "https://registry.npmjs.org/@naisys/supervisor-database/-/supervisor-database-3.0.0-beta.47.tgz",
|
|
441
|
+
"integrity": "sha512-64tzBp/Xj2IN6bqc5NPfszqhjungaADHG1hyxBuu/TDSD8dquUQczV6eLEGWOXRImU8u2LnfkAPkyv2jfta88A==",
|
|
442
442
|
"dependencies": {
|
|
443
|
-
"@naisys/common": "3.0.0-beta.
|
|
444
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
443
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
444
|
+
"@naisys/common-node": "3.0.0-beta.47",
|
|
445
445
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
446
446
|
"@prisma/client": "^7.5.0",
|
|
447
447
|
"bcryptjs": "^3.0.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@naisys/erp",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.47",
|
|
4
4
|
"description": "NAISYS ERP - Web UI for AI-driven order and work management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/erpServer.js",
|
|
@@ -46,11 +46,11 @@
|
|
|
46
46
|
"@fastify/rate-limit": "^10.3.0",
|
|
47
47
|
"@fastify/static": "^9.0.0",
|
|
48
48
|
"@fastify/swagger": "^9.7.0",
|
|
49
|
-
"@naisys/common": "3.0.0-beta.
|
|
50
|
-
"@naisys/common-node": "3.0.0-beta.
|
|
51
|
-
"@naisys/erp-shared": "3.0.0-beta.
|
|
52
|
-
"@naisys/hub-database": "3.0.0-beta.
|
|
53
|
-
"@naisys/supervisor-database": "3.0.0-beta.
|
|
49
|
+
"@naisys/common": "3.0.0-beta.47",
|
|
50
|
+
"@naisys/common-node": "3.0.0-beta.47",
|
|
51
|
+
"@naisys/erp-shared": "3.0.0-beta.47",
|
|
52
|
+
"@naisys/hub-database": "3.0.0-beta.47",
|
|
53
|
+
"@naisys/supervisor-database": "3.0.0-beta.47",
|
|
54
54
|
"@prisma/adapter-better-sqlite3": "^7.5.0",
|
|
55
55
|
"@prisma/client": "^7.5.0",
|
|
56
56
|
"@scalar/fastify-api-reference": "^1.48.7",
|
package/dist/userService.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import { SUPER_ADMIN_USERNAME } from "@naisys/common";
|
|
2
|
-
import { ensureSuperAdmin } from "@naisys/supervisor-database";
|
|
3
|
-
import bcrypt from "bcryptjs";
|
|
4
|
-
import { randomUUID } from "crypto";
|
|
5
|
-
import erpDb from "./erpDb.js";
|
|
6
|
-
const SALT_ROUNDS = 10;
|
|
7
|
-
/**
|
|
8
|
-
* Ensure a superadmin user exists in the local ERP database.
|
|
9
|
-
* If a password is supplied, it is used on create and updates the existing one if present.
|
|
10
|
-
* For standalone mode (no supervisor auth).
|
|
11
|
-
*/
|
|
12
|
-
export async function ensureLocalSuperAdmin(password) {
|
|
13
|
-
const existing = await erpDb.user.findUnique({
|
|
14
|
-
where: { username: SUPER_ADMIN_USERNAME },
|
|
15
|
-
});
|
|
16
|
-
if (existing) {
|
|
17
|
-
await ensureErpAdminPermission(existing.id);
|
|
18
|
-
if (password) {
|
|
19
|
-
const hash = await bcrypt.hash(password, SALT_ROUNDS);
|
|
20
|
-
await erpDb.user.update({
|
|
21
|
-
where: { id: existing.id },
|
|
22
|
-
data: { passwordHash: hash },
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
else {
|
|
27
|
-
const finalPassword = password || randomUUID().slice(0, 8);
|
|
28
|
-
const hash = await bcrypt.hash(finalPassword, SALT_ROUNDS);
|
|
29
|
-
const user = await erpDb.user.create({
|
|
30
|
-
data: {
|
|
31
|
-
uuid: randomUUID(),
|
|
32
|
-
username: SUPER_ADMIN_USERNAME,
|
|
33
|
-
passwordHash: hash,
|
|
34
|
-
},
|
|
35
|
-
});
|
|
36
|
-
await ensureErpAdminPermission(user.id);
|
|
37
|
-
if (!password) {
|
|
38
|
-
console.log(`\n ${SUPER_ADMIN_USERNAME} user created. Password: ${finalPassword}`);
|
|
39
|
-
console.log(` Change it via the admin UI or with --setup\n`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
// Warn if agent users exist without supervisor auth
|
|
43
|
-
const agentCount = await erpDb.user.count({ where: { isAgent: true } });
|
|
44
|
-
if (agentCount > 0) {
|
|
45
|
-
console.warn(`[ERP] Warning: ${agentCount} agent user(s) found but supervisor auth is disabled. ` +
|
|
46
|
-
`Agent API key lookups and authentication will not work. ` +
|
|
47
|
-
`Set SUPERVISOR_AUTH=true to enable.`);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Sync superadmin from supervisor into ERP DB and ensure permissions.
|
|
52
|
-
* For supervisor auth mode. Supervisor uses passkey-only auth — the
|
|
53
|
-
* mirrored ERP row has no passwordHash.
|
|
54
|
-
*/
|
|
55
|
-
export async function ensureSupervisorSuperAdmin() {
|
|
56
|
-
const result = await ensureSuperAdmin();
|
|
57
|
-
await erpDb.user.upsert({
|
|
58
|
-
where: { uuid: result.user.uuid },
|
|
59
|
-
create: {
|
|
60
|
-
uuid: result.user.uuid,
|
|
61
|
-
username: result.user.username,
|
|
62
|
-
},
|
|
63
|
-
update: {
|
|
64
|
-
username: result.user.username,
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
const localSuperAdmin = await erpDb.user.findUnique({
|
|
68
|
-
where: { uuid: result.user.uuid },
|
|
69
|
-
});
|
|
70
|
-
if (localSuperAdmin) {
|
|
71
|
-
await ensureErpAdminPermission(localSuperAdmin.id);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Ensure a user has the erp_admin permission.
|
|
76
|
-
*/
|
|
77
|
-
export async function ensureErpAdminPermission(userId) {
|
|
78
|
-
const existing = await erpDb.userPermission.findUnique({
|
|
79
|
-
where: { userId_permission: { userId, permission: "erp_admin" } },
|
|
80
|
-
});
|
|
81
|
-
if (!existing) {
|
|
82
|
-
await erpDb.userPermission.create({
|
|
83
|
-
data: { userId, permission: "erp_admin" },
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
//# sourceMappingURL=userService.js.map
|
|
File without changes
|
|
File without changes
|
|
File without changes
|