security(users): SafeUser — passwordHash/токены не уходят клиенту
Шаг 0.8 плана production-готовности: - shared/schema.ts: тип SafeUser + safeUserColumns - getUsersByOrganization, listUsers, searchUsers, getUsersByRole, getUsersByOrgRoleId, documents getUser — без чувствительных колонок - sync (initial/delta), автоматизации ctx.users.list, MCP list_users — sanitized
This commit is contained in:
@@ -2,7 +2,7 @@ import { Router } from "express";
|
||||
import { storage } from "../storage";
|
||||
import { authenticateToken, type AuthenticatedRequest } from "../middleware/auth.middleware";
|
||||
import { tenantIsolation } from "../middleware/tenant.middleware";
|
||||
import { type Task, type FormStatus, type User, roles, tasks } from "@shared/schema";
|
||||
import { type Task, type FormStatus, type SafeUser, roles, tasks } from "@shared/schema";
|
||||
import { db } from "../db";
|
||||
import { eq, inArray } from "drizzle-orm";
|
||||
import { tasksMinimalCache } from "../utils/cache";
|
||||
@@ -204,7 +204,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
db.select().from(roles).where(eq(roles.organizationId, req.organizationId!)),
|
||||
]);
|
||||
const statusMap = new Map(statuses.map((s: FormStatus) => [s.id, s]));
|
||||
const userMap = new Map(users.map((u: User) => [u.id, u]));
|
||||
const userMap = new Map(users.map((u: SafeUser) => [u.id, u]));
|
||||
const roleMap = new Map(orgRoles.map((r) => [r.id, r]));
|
||||
|
||||
const contractNumberFields = formFields.filter((f) => f.type === 'contract-number' && (f as any).options?.contractNumber?.legalEntityFormId);
|
||||
@@ -250,7 +250,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
db.select().from(roles).where(eq(roles.organizationId, req.organizationId!)),
|
||||
]);
|
||||
const statusMap = new Map(statuses.map((s: FormStatus) => [s.id, s]));
|
||||
const userMap = new Map(users.map((u: User) => [u.id, u]));
|
||||
const userMap = new Map(users.map((u: SafeUser) => [u.id, u]));
|
||||
const roleMap = new Map(orgRoles.map((r) => [r.id, r]));
|
||||
|
||||
const contractNumberFields = formFields.filter((f) => f.type === 'contract-number' && (f as any).options?.contractNumber?.legalEntityFormId);
|
||||
@@ -348,7 +348,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
// Отображаемое имя одного элемента user-поля (`user:<id>` / `role:<id>` / legacy-число)
|
||||
function resolveUserColumnEntry(
|
||||
entry: string,
|
||||
userMap: Map<number, User>,
|
||||
userMap: Map<number, SafeUser>,
|
||||
roleMap?: Map<number, { name?: string }>
|
||||
): string {
|
||||
if (entry.startsWith('user:')) {
|
||||
@@ -373,7 +373,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
task: Task & { fieldValues?: Record<number, unknown>; assignees?: Array<{ userId: number; user?: { firstName: string | null; middleName: string | null; lastName: string | null } }> },
|
||||
column: string,
|
||||
statusMap: Map<number, FormStatus>,
|
||||
userMap: Map<number, User>,
|
||||
userMap: Map<number, SafeUser>,
|
||||
fields?: Array<{ id: number; type: string; options?: unknown }>,
|
||||
roleMap?: Map<number, { name?: string }>,
|
||||
tableRowMap?: Map<number, Map<number, string>>,
|
||||
@@ -678,7 +678,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
const statuses = await storage.getFormStatuses(formId, req.organizationId!);
|
||||
const users = await storage.getUsersByOrganization(req.organizationId!);
|
||||
const statusMap = new Map(statuses.map((s: FormStatus) => [s.id, s]));
|
||||
const userMap = new Map(users.map((u: User) => [u.id, u]));
|
||||
const userMap = new Map(users.map((u: SafeUser) => [u.id, u]));
|
||||
|
||||
Object.entries(context).forEach(([col, val]) => {
|
||||
if (!val) return;
|
||||
@@ -703,7 +703,7 @@ export function registerTaskCrudListRoutes(router: ReturnType<typeof import("exp
|
||||
const statuses = await storage.getFormStatuses(formId, req.organizationId!);
|
||||
const users = await storage.getUsersByOrganization(req.organizationId!);
|
||||
const statusMap = new Map(statuses.map((s: FormStatus) => [s.id, s]));
|
||||
const userMap = new Map(users.map((u: User) => [u.id, u]));
|
||||
const userMap = new Map(users.map((u: SafeUser) => [u.id, u]));
|
||||
|
||||
// Отладка: логируем select/radio-group/table поля и их options
|
||||
if (column.startsWith('field_')) {
|
||||
|
||||
Reference in New Issue
Block a user