docs: registrar fluxo do updater e atualizar chaves

This commit is contained in:
Esdras Renan 2025-10-12 04:06:29 -03:00
parent 206d00700e
commit b5fd920efd
50 changed files with 980 additions and 93 deletions

View file

@ -18,6 +18,7 @@ export type AppSession = {
role: string
tenantId: string | null
avatarUrl: string | null
machinePersona?: string | null
}
session: {
id: string
@ -25,6 +26,17 @@ export type AppSession = {
}
}
type MachineContext = {
machineId: string
tenantId: string
persona: string | null
assignedUserId: string | null
assignedUserEmail: string | null
assignedUserName: string | null
assignedUserRole: string | null
companyId: string | null
}
const authClient = createAuthClient({
plugins: [customSessionClient<AppAuth>()],
fetchOptions: {
@ -40,6 +52,7 @@ type AuthContextValue = {
isAdmin: boolean
isStaff: boolean
isCustomer: boolean
machineContext: MachineContext | null
}
const AuthContext = createContext<AuthContextValue>({
@ -50,6 +63,7 @@ const AuthContext = createContext<AuthContextValue>({
isAdmin: false,
isStaff: false,
isCustomer: false,
machineContext: null,
})
export function useAuth() {
@ -62,15 +76,68 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
const { data: session, isPending } = useSession()
const ensureUser = useMutation(api.users.ensureUser)
const [convexUserId, setConvexUserId] = useState<string | null>(null)
const [machineContext, setMachineContext] = useState<MachineContext | null>(null)
useEffect(() => {
if (!session?.user) {
if (!session?.user || session.user.role === "machine") {
setConvexUserId(null)
}
}, [session?.user])
useEffect(() => {
if (!session?.user || convexUserId) return
if (!session?.user || session.user.role !== "machine") {
setMachineContext(null)
return
}
let cancelled = false
;(async () => {
try {
const response = await fetch("/api/machines/session", { credentials: "include" })
if (!response.ok) {
if (!cancelled) {
setMachineContext(null)
}
return
}
const data = await response.json()
if (!cancelled) {
const machine = data.machine as {
id: string
tenantId: string
persona: string | null
assignedUserId: string | null
assignedUserEmail: string | null
assignedUserName: string | null
assignedUserRole: string | null
companyId: string | null
}
setMachineContext({
machineId: machine.id,
tenantId: machine.tenantId,
persona: machine.persona ?? null,
assignedUserId: machine.assignedUserId ?? null,
assignedUserEmail: machine.assignedUserEmail ?? null,
assignedUserName: machine.assignedUserName ?? null,
assignedUserRole: machine.assignedUserRole ?? null,
companyId: machine.companyId ?? null,
})
}
} catch (error) {
console.error("Failed to load machine context", error)
if (!cancelled) {
setMachineContext(null)
}
}
})()
return () => {
cancelled = true
}
}, [session?.user])
useEffect(() => {
if (!session?.user || session.user.role === "machine" || convexUserId) return
const controller = new AbortController()
@ -99,19 +166,26 @@ export function AuthProvider({ children }: { children: React.ReactNode }) {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ensureUser, session?.user?.email, session?.user?.tenantId, session?.user?.role, convexUserId])
const normalizedRole = session?.user?.role ? session.user.role.toLowerCase() : null
const baseRole = session?.user?.role ? session.user.role.toLowerCase() : null
const personaRole = session?.user?.machinePersona ? session.user.machinePersona.toLowerCase() : null
const normalizedRole =
baseRole === "machine" ? machineContext?.persona ?? personaRole ?? null : baseRole
const effectiveConvexUserId =
baseRole === "machine" ? machineContext?.assignedUserId ?? null : convexUserId
const value = useMemo<AuthContextValue>(
() => ({
session: session ?? null,
isLoading: isPending,
convexUserId,
convexUserId: effectiveConvexUserId,
role: normalizedRole,
isAdmin: isAdmin(normalizedRole),
isStaff: isStaff(normalizedRole),
isCustomer: false,
isCustomer: normalizedRole === "collaborator",
machineContext,
}),
[session, isPending, convexUserId, normalizedRole]
[session, isPending, effectiveConvexUserId, normalizedRole, machineContext]
)
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>

View file

@ -39,6 +39,11 @@ export const auth = betterAuth({
type: "string",
required: false,
},
machinePersona: {
type: "string",
required: false,
input: false,
},
},
},
session: {
@ -76,6 +81,7 @@ export const auth = betterAuth({
role: ((user as { role?: string }).role ?? "agent").toLowerCase(),
tenantId: (user as { tenantId?: string | null }).tenantId ?? null,
avatarUrl: (user as { avatarUrl?: string | null }).avatarUrl ?? null,
machinePersona: (user as { machinePersona?: string | null }).machinePersona ?? null,
},
}
}),

View file

@ -1,7 +1,8 @@
export const ROLE_OPTIONS = ["admin", "manager", "agent", "collaborator"] as const
const ADMIN_ROLE = "admin"
const STAFF_ROLES = new Set(["admin", "manager", "agent", "collaborator"])
const PORTAL_ROLE = "collaborator"
const STAFF_ROLES = new Set(["admin", "manager", "agent"])
export type RoleOption = (typeof ROLE_OPTIONS)[number]
@ -16,3 +17,7 @@ export function isAdmin(role?: string | null) {
export function isStaff(role?: string | null) {
return STAFF_ROLES.has(normalizeRole(role) ?? "")
}
export function isPortalUser(role?: string | null) {
return normalizeRole(role) === PORTAL_ROLE
}