admin: add service seam builder
This commit is contained in:
@@ -18,7 +18,7 @@ use tracing::info;
|
||||
use crate::{
|
||||
app::build_app,
|
||||
auth::{AuthSettings, BootstrapAdminConfig},
|
||||
service::AdminService,
|
||||
service::AdminServiceBuilder,
|
||||
state::AppState,
|
||||
};
|
||||
use crank_runtime::{
|
||||
@@ -70,13 +70,14 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.with_limits(runtime_limits)
|
||||
.with_response_cache(cache_stores.response.clone())
|
||||
.build();
|
||||
let service = AdminService::new_with_runtime(
|
||||
let service = AdminServiceBuilder::new(
|
||||
registry,
|
||||
storage_root,
|
||||
auth_settings,
|
||||
secret_crypto,
|
||||
runtime,
|
||||
);
|
||||
)
|
||||
.build();
|
||||
service.bootstrap_admin_user().await?;
|
||||
if env_flag("CRANK_DEMO_SEED") {
|
||||
service.seed_demo_assets().await?;
|
||||
|
||||
+130
-15
@@ -1,19 +1,21 @@
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
|
||||
use crank_core::{
|
||||
Agent, AgentId, AgentOperationBinding, AgentStatus, AgentVersion, AggregationMode,
|
||||
AsyncJobHandle, AuthConfig, AuthKind, AuthProfile, AuthProfileId, CapabilityProfile,
|
||||
ConfigExport, EditionCapabilities, ExecutionMode, ExportMode, GeneratedDraft,
|
||||
GeneratedDraftStatus, InvitationId, InvitationStatus, InvitationToken, InvocationLevel,
|
||||
InvocationLog, InvocationLogId, InvocationSource, InvocationStatus, IssueAgentTokenRequest,
|
||||
IssueOneTimeAgentTokenRequest, IssuedAgentTokenResponse, JobStatus, MachineAccessMode,
|
||||
MembershipRole, OperationId, OperationSecurityLevel, OperationStatus, PlatformApiKey,
|
||||
PlatformApiKeyId, PlatformApiKeyScope, PlatformApiKeyStatus, ProductEdition, Protocol,
|
||||
ResponseCachePolicy, SampleId, Samples, Secret, SecretId, SecretKind, SecretStatus,
|
||||
StreamSession, StreamStatus, Target, TransportBehavior, UsagePeriod, UserId, UserSessionId,
|
||||
Workspace, WorkspaceId, WorkspaceStatus,
|
||||
AsyncJobHandle, AuditSink, AuthConfig, AuthKind, AuthProfile, AuthProfileId, CapabilityProfile,
|
||||
CommunityCapabilityProfile, ConfigExport, EditionCapabilities, ExecutionMode, ExportMode,
|
||||
GeneratedDraft, GeneratedDraftStatus, IdentityProvider, InvitationId, InvitationStatus,
|
||||
InvitationToken, InvocationLevel, InvocationLog, InvocationLogId, InvocationSource,
|
||||
InvocationStatus, IssueAgentTokenRequest, IssueOneTimeAgentTokenRequest,
|
||||
IssuedAgentTokenResponse, JobStatus, MachineAccessMode, MachineTokenIssuer, MembershipRole,
|
||||
NoMachineTokenIssuer, NoopAuditSink, OperationId, OperationSecurityLevel, OperationStatus,
|
||||
OwnerOnlyPolicyEngine, PlatformApiKey, PlatformApiKeyId, PlatformApiKeyScope,
|
||||
PlatformApiKeyStatus, PolicyEngine, ProductEdition, Protocol, ResponseCachePolicy, SampleId,
|
||||
Samples, Secret, SecretId, SecretKind, SecretStatus, StreamSession, StreamStatus, Target,
|
||||
TransportBehavior, UsagePeriod, UserId, UserSessionId, Workspace, WorkspaceId, WorkspaceStatus,
|
||||
};
|
||||
use crank_mapping::{JsonPathRoot, MappingSet, infer_mapping_from_samples};
|
||||
use crank_registry::{
|
||||
@@ -57,6 +59,24 @@ pub struct AdminService {
|
||||
storage: LocalArtifactStorage,
|
||||
auth_settings: AuthSettings,
|
||||
secret_crypto: SecretCrypto,
|
||||
identity_provider: Option<Arc<dyn IdentityProvider>>,
|
||||
policy_engine: Arc<dyn PolicyEngine>,
|
||||
audit_sink: Arc<dyn AuditSink>,
|
||||
token_issuer: Arc<dyn MachineTokenIssuer>,
|
||||
capability_profile: Arc<dyn CapabilityProfile>,
|
||||
}
|
||||
|
||||
pub struct AdminServiceBuilder {
|
||||
registry: PostgresRegistry,
|
||||
storage_root: PathBuf,
|
||||
auth_settings: AuthSettings,
|
||||
secret_crypto: SecretCrypto,
|
||||
runtime: RuntimeExecutor,
|
||||
identity_provider: Option<Arc<dyn IdentityProvider>>,
|
||||
policy_engine: Option<Arc<dyn PolicyEngine>>,
|
||||
audit_sink: Option<Arc<dyn AuditSink>>,
|
||||
token_issuer: Option<Arc<dyn MachineTokenIssuer>>,
|
||||
capability_profile: Option<Arc<dyn CapabilityProfile>>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
@@ -654,19 +674,114 @@ impl AdminService {
|
||||
secret_crypto: SecretCrypto,
|
||||
runtime: RuntimeExecutor,
|
||||
) -> Self {
|
||||
Self {
|
||||
AdminServiceBuilder::new(
|
||||
registry,
|
||||
runtime,
|
||||
storage: LocalArtifactStorage::new(storage_root),
|
||||
storage_root,
|
||||
auth_settings,
|
||||
secret_crypto,
|
||||
}
|
||||
runtime,
|
||||
)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub fn auth_settings(&self) -> &AuthSettings {
|
||||
&self.auth_settings
|
||||
}
|
||||
|
||||
pub fn identity_provider(&self) -> Option<&Arc<dyn IdentityProvider>> {
|
||||
self.identity_provider.as_ref()
|
||||
}
|
||||
|
||||
pub fn policy_engine(&self) -> &Arc<dyn PolicyEngine> {
|
||||
&self.policy_engine
|
||||
}
|
||||
|
||||
pub fn audit_sink(&self) -> &Arc<dyn AuditSink> {
|
||||
&self.audit_sink
|
||||
}
|
||||
|
||||
pub fn token_issuer(&self) -> &Arc<dyn MachineTokenIssuer> {
|
||||
&self.token_issuer
|
||||
}
|
||||
|
||||
pub fn capability_profile(&self) -> &Arc<dyn CapabilityProfile> {
|
||||
&self.capability_profile
|
||||
}
|
||||
}
|
||||
|
||||
impl AdminServiceBuilder {
|
||||
pub fn new(
|
||||
registry: PostgresRegistry,
|
||||
storage_root: PathBuf,
|
||||
auth_settings: AuthSettings,
|
||||
secret_crypto: SecretCrypto,
|
||||
runtime: RuntimeExecutor,
|
||||
) -> Self {
|
||||
Self {
|
||||
registry,
|
||||
storage_root,
|
||||
auth_settings,
|
||||
secret_crypto,
|
||||
runtime,
|
||||
identity_provider: None,
|
||||
policy_engine: None,
|
||||
audit_sink: None,
|
||||
token_issuer: None,
|
||||
capability_profile: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_identity_provider(mut self, provider: Arc<dyn IdentityProvider>) -> Self {
|
||||
self.identity_provider = Some(provider);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_policy_engine(mut self, policy_engine: Arc<dyn PolicyEngine>) -> Self {
|
||||
self.policy_engine = Some(policy_engine);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_audit_sink(mut self, audit_sink: Arc<dyn AuditSink>) -> Self {
|
||||
self.audit_sink = Some(audit_sink);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_token_issuer(mut self, token_issuer: Arc<dyn MachineTokenIssuer>) -> Self {
|
||||
self.token_issuer = Some(token_issuer);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_capability_profile(
|
||||
mut self,
|
||||
capability_profile: Arc<dyn CapabilityProfile>,
|
||||
) -> Self {
|
||||
self.capability_profile = Some(capability_profile);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build(self) -> AdminService {
|
||||
AdminService {
|
||||
registry: self.registry,
|
||||
runtime: self.runtime,
|
||||
storage: LocalArtifactStorage::new(self.storage_root),
|
||||
auth_settings: self.auth_settings,
|
||||
secret_crypto: self.secret_crypto,
|
||||
identity_provider: self.identity_provider,
|
||||
policy_engine: self
|
||||
.policy_engine
|
||||
.unwrap_or_else(|| Arc::new(OwnerOnlyPolicyEngine)),
|
||||
audit_sink: self.audit_sink.unwrap_or_else(|| Arc::new(NoopAuditSink)),
|
||||
token_issuer: self
|
||||
.token_issuer
|
||||
.unwrap_or_else(|| Arc::new(NoMachineTokenIssuer)),
|
||||
capability_profile: self
|
||||
.capability_profile
|
||||
.unwrap_or_else(|| Arc::new(CommunityCapabilityProfile)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AdminService {
|
||||
pub async fn bootstrap_admin_user(&self) -> Result<(), ApiError> {
|
||||
let password_hash = hash_password(
|
||||
&self.auth_settings.bootstrap_admin.password,
|
||||
@@ -1496,7 +1611,7 @@ impl AdminService {
|
||||
}
|
||||
|
||||
pub async fn get_capabilities(&self) -> EditionCapabilities {
|
||||
crank_core::CommunityCapabilityProfile.capabilities()
|
||||
self.capability_profile().capabilities()
|
||||
}
|
||||
|
||||
pub async fn issue_agent_token(
|
||||
|
||||
Reference in New Issue
Block a user