username : 'system'; $result = ServiceToken::generate( name: $name, service: $service, createdBy: $createdBy, expiresInDays: $expiresInDays ); // Sync ke geonetagent.agent_tokens jika service adalah GeoNetAgent $synced = false; if ($this->agentTokenSync->isEnabled()) { $synced = $this->agentTokenSync->addToken($name, $result['model']->token_hash); } // Audit log $this->auditLogService->log( action: 'service_token_created', entityType: 'ServiceToken', entityId: $result['model']->id, details: [ 'name' => $name, 'service' => $service, 'token_prefix' => $result['model']->token_prefix, 'expires_at' => $result['model']->expires_at?->toIso8601String(), 'agent_token_synced' => $synced, ], userId: $createdBy ); return $result; } /** * List all service tokens (without plain tokens) * * @return array */ public function listAll(): array { return ServiceToken::orderByDesc('created_at')->get()->all(); } /** * Get a specific service token by ID */ public function getById(string $id): ?ServiceToken { return ServiceToken::find($id); } /** * Revoke (deactivate) a service token */ public function revoke(ServiceToken $token): void { $token->update(['is_active' => false]); // Sync revoke ke geonetagent.agent_tokens $synced = false; if ($this->agentTokenSync->isEnabled()) { $synced = $this->agentTokenSync->revokeToken($token->token_hash); } $createdBy = Auth::check() ? Auth::user()->username : 'system'; $this->auditLogService->log( action: 'service_token_revoked', entityType: 'ServiceToken', entityId: $token->id, details: [ 'name' => $token->name, 'service' => $token->service, 'token_prefix' => $token->token_prefix, 'agent_token_synced' => $synced, ], userId: $createdBy ); } /** * Permanently delete a service token */ public function delete(ServiceToken $token): void { $tokenId = $token->id; $tokenName = $token->name; $tokenService = $token->service; $tokenPrefix = $token->token_prefix; $tokenHash = $token->token_hash; $token->delete(); // Sync delete ke geonetagent.agent_tokens if ($this->agentTokenSync->isEnabled()) { $this->agentTokenSync->deleteToken($tokenHash); } $createdBy = Auth::check() ? Auth::user()->username : 'system'; $this->auditLogService->log( action: 'service_token_deleted', entityType: 'ServiceToken', entityId: $tokenId, details: [ 'name' => $tokenName, 'service' => $tokenService, 'token_prefix' => $tokenPrefix, ], userId: $createdBy ); } /** * Regenerate a service token (create new, revoke old) * * @return array{token: string, model: ServiceToken} */ public function regenerate(ServiceToken $oldToken, ?int $expiresInDays = null): array { // Revoke old token $this->revoke($oldToken); // Create new token with same name and service return $this->create( name: $oldToken->name, service: $oldToken->service, expiresInDays: $expiresInDays ); } /** * Verify a token (for external validation, not used in UI) * * @param string $plainToken Plain token to verify * @return ServiceToken|null */ public function verify(string $plainToken): ?ServiceToken { $token = ServiceToken::verify($plainToken); if ($token) { $token->touchLastUsed(); } return $token; } /** * Get tokens by service * * @param string $service Service name * @return array */ public function getByService(string $service): array { return ServiceToken::where('service', $service) ->orderByDesc('created_at') ->get() ->all(); } /** * Get active tokens only * * @return array */ public function getActive(): array { return ServiceToken::active() ->orderByDesc('created_at') ->get() ->all(); } /** * Get expired tokens * * @return array */ public function getExpired(): array { return ServiceToken::expired() ->orderByDesc('expires_at') ->get() ->all(); } /** * Clean up expired tokens (optional maintenance task) * * @param int $olderThanDays Delete tokens expired more than X days ago * @return int Number of deleted tokens */ public function cleanupExpired(int $olderThanDays = 30): int { $cutoffDate = now()->subDays($olderThanDays); $deleted = ServiceToken::expired() ->where('expires_at', '<', $cutoffDate) ->delete(); if ($deleted > 0) { $this->auditLogService->log( action: 'service_tokens_cleanup', entityType: 'ServiceToken', entityId: null, details: [ 'deleted_count' => $deleted, 'older_than_days' => $olderThanDays, ], userId: 'system' ); } return $deleted; } }