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:
@@ -1,5 +1,5 @@
|
||||
import { db } from "../db";
|
||||
import { tasks, taskFieldValues, users, organizations, forms, formFields, formTabs, regularTableRows, taskRelations } from "@shared/schema";
|
||||
import { tasks, taskFieldValues, users, organizations, forms, formFields, formTabs, regularTableRows, taskRelations, safeUserColumns, type SafeUser } from "@shared/schema";
|
||||
import { eq, and, asc, sql } from "drizzle-orm";
|
||||
import type { TemplateVariable } from "@shared/schema";
|
||||
import { TransformService, type TransformConfig, type TransformType } from "./transform.service";
|
||||
@@ -14,10 +14,10 @@ export interface ResolutionContext {
|
||||
type: string;
|
||||
name: string;
|
||||
}>;
|
||||
assignee: typeof users.$inferSelect | null;
|
||||
creator: typeof users.$inferSelect | null;
|
||||
assignee: SafeUser | null;
|
||||
creator: SafeUser | null;
|
||||
organization: typeof organizations.$inferSelect | null;
|
||||
currentUser: typeof users.$inferSelect | null;
|
||||
currentUser: SafeUser | null;
|
||||
}
|
||||
|
||||
export interface ResolutionResult {
|
||||
@@ -89,8 +89,9 @@ export class DataResolutionService {
|
||||
.where(eq(taskFieldValues.taskId, taskId));
|
||||
}
|
||||
|
||||
private async getUser(userId: number) {
|
||||
const [user] = await db.select().from(users).where(eq(users.id, userId)).limit(1);
|
||||
private async getUser(userId: number): Promise<SafeUser | null> {
|
||||
// Для подстановки в шаблоны документов достаточно безопасных колонок (без хэша пароля и токенов)
|
||||
const [user] = await db.select(safeUserColumns).from(users).where(eq(users.id, userId)).limit(1);
|
||||
return user || null;
|
||||
}
|
||||
|
||||
@@ -243,7 +244,7 @@ export class DataResolutionService {
|
||||
}
|
||||
}
|
||||
|
||||
private getUserField(user: typeof users.$inferSelect, key: string): string | null {
|
||||
private getUserField(user: SafeUser, key: string): string | null {
|
||||
switch (key) {
|
||||
case 'fullName':
|
||||
return `${user.lastName || ''} ${user.firstName || ''} ${user.middleName || ''}`.trim() || user.email || '';
|
||||
|
||||
Reference in New Issue
Block a user