feat(api, web): enhance agent installation process with invited status and policy support
Build and Push EvoFirewall Docker Image / build-and-push (push) Successful in 1m48s
Build and Push EvoFirewall Docker Image / create-release (push) Skipped

- Updated the agent enrollment process to include an 'invited' status, allowing for better tracking of agent states.
- Implemented support for install links that can now include an `install_link_id`, facilitating the transition from invited to pending status upon enrollment.
- Enhanced the MikroTik installation script to include the `EvofwInstallLinkId` for better tracking and management.
- Added new API endpoints for fetching agent policies and serving MikroTik-specific installation scripts.
- Improved the web UI to reflect the new agent statuses and provide copyable installation commands for agents.

Co-authored-by: Cursor <[email protected]>
This commit is contained in:
Denozordec
2026-07-21 01:45:38 +07:00
co-authored by Cursor
parent ef56da4d91
commit d5784b9f35
20 changed files with 793 additions and 104 deletions
+15
View File
@@ -459,6 +459,20 @@ export function getInstallLinkBySlug(db: Db, slug: string) {
.get()
}
export function getInstallLinkByAgentId(db: Db, agentId: string) {
return db
.select()
.from(agentInstallLinks)
.where(
and(
eq(agentInstallLinks.agentId, agentId),
sql`${agentInstallLinks.revokedAt} IS NULL`,
),
)
.orderBy(desc(agentInstallLinks.createdAt))
.get()
}
export function insertInstallLink(
db: Db,
row: typeof agentInstallLinks.$inferInsert,
@@ -538,6 +552,7 @@ export const repos = {
listInstallLinks,
getInstallLink,
getInstallLinkBySlug,
getInstallLinkByAgentId,
insertInstallLink,
revokeInstallLink,
touchInstallLink,
+3 -1
View File
@@ -18,7 +18,7 @@ export const agents = sqliteTable(
platform: text('platform').notNull().default('linux'), // linux | mikrotik
tokenPrefix: text('token_prefix').notNull(),
tokenHash: text('token_hash').notNull(),
status: text('status').notNull().default('pending'), // pending | approved | revoked
status: text('status').notNull().default('pending'), // invited | pending | approved | revoked
policyMode: text('policy_mode').notNull().default('blacklist'), // blacklist | whitelist
policyGeneration: integer('policy_generation').notNull().default(1),
lastSeenAt: text('last_seen_at'),
@@ -202,6 +202,7 @@ export const agentInstallLinks = sqliteTable(
slug: text('slug').notNull(),
clientName: text('client_name').notNull(),
platform: text('platform').notNull().default('linux'), // linux | mikrotik
agentId: text('agent_id').references(() => agents.id, { onDelete: 'cascade' }),
createdAt: text('created_at')
.notNull()
.default(sql`(strftime('%Y-%m-%dT%H:%M:%fZ', 'now'))`),
@@ -211,6 +212,7 @@ export const agentInstallLinks = sqliteTable(
},
(t) => ({
slugIdx: uniqueIndex('idx_agent_install_links_slug').on(t.slug),
agentIdx: index('idx_agent_install_links_agent').on(t.agentId),
}),
)