mirror of
https://github.com/CloudNebulaProject/barycenter.git
synced 2026-04-11 05:30:41 +00:00
Major Features: - Admin GraphQL API with dual endpoints (Seaography + custom) - Background job scheduler with execution tracking - Idempotent user sync CLI for Kubernetes deployments - Secure PUT /properties endpoint with Bearer token auth Admin GraphQL API: - Entity CRUD via Seaography at /admin/graphql - Custom job management API at /admin/jobs - Mutations: triggerJob - Queries: jobLogs, availableJobs - GraphiQL playgrounds for both endpoints Background Jobs: - tokio-cron-scheduler integration - Automated cleanup of expired sessions (hourly) - Automated cleanup of expired refresh tokens (hourly) - Job execution tracking in database - Manual job triggering via GraphQL User Sync CLI: - Command: barycenter sync-users --file users.json - Idempotent user synchronization from JSON - Creates new users with hashed passwords - Updates existing users (enabled, email_verified, email) - Syncs custom properties per user - Perfect for Kubernetes init containers Security Enhancements: - PUT /properties endpoint requires Bearer token - Users can only modify their own properties - Public registration disabled by default - Admin API on separate port for network isolation Database: - New job_executions table for job tracking - User update functions (update_user, update_user_email) - PostgreSQL + SQLite support maintained Configuration: - allow_public_registration setting (default: false) - admin_port setting (default: main port + 1) Documentation: - Comprehensive Kubernetes deployment guide - User sync JSON schema and examples - Init container and CronJob examples - Production deployment patterns Files Added: - src/admin_graphql.rs - GraphQL schema builders - src/admin_mutations.rs - Custom mutations and queries - src/jobs.rs - Job scheduler and tracking - src/user_sync.rs - User sync logic - src/entities/ - SeaORM entities (8 entities) - docs/kubernetes-deployment.md - K8s deployment guide - users.json.example - User sync example Dependencies: - tokio-cron-scheduler 0.13 - seaography 1.1.4 - async-graphql 7.0 - async-graphql-axum 7.0 🤖 Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
113 lines
3.6 KiB
Rust
113 lines
3.6 KiB
Rust
use async_graphql::dynamic::Schema as DynamicSchema;
|
|
use async_graphql::EmptySubscription;
|
|
use async_graphql_axum::{GraphQLRequest, GraphQLResponse};
|
|
use axum::{
|
|
extract::State,
|
|
response::IntoResponse,
|
|
routing::{get, post},
|
|
Router,
|
|
};
|
|
use sea_orm::DatabaseConnection;
|
|
use std::sync::Arc;
|
|
|
|
use crate::admin_mutations::{AdminMutation, AdminQuery};
|
|
use crate::entities;
|
|
|
|
/// Initialize the Seaography admin GraphQL schema with all entities
|
|
pub fn build_seaography_schema(db: DatabaseConnection) -> DynamicSchema {
|
|
use seaography::{Builder, BuilderContext};
|
|
|
|
// Create a static BuilderContext for Seaography
|
|
let context: &'static BuilderContext = Box::leak(Box::new(BuilderContext::default()));
|
|
|
|
let mut builder = Builder::new(context, db.clone());
|
|
|
|
// Register all entities
|
|
builder.register_entity::<entities::user::Entity>(vec![]);
|
|
builder.register_entity::<entities::client::Entity>(vec![]);
|
|
builder.register_entity::<entities::session::Entity>(vec![]);
|
|
builder.register_entity::<entities::access_token::Entity>(vec![]);
|
|
builder.register_entity::<entities::auth_code::Entity>(vec![]);
|
|
builder.register_entity::<entities::refresh_token::Entity>(vec![]);
|
|
builder.register_entity::<entities::property::Entity>(vec![]);
|
|
builder.register_entity::<entities::job_execution::Entity>(vec![]);
|
|
|
|
// Build and return the schema
|
|
builder.schema_builder().finish().unwrap()
|
|
}
|
|
|
|
/// Build custom job management GraphQL schema
|
|
pub fn build_jobs_schema(
|
|
db: DatabaseConnection,
|
|
) -> async_graphql::Schema<AdminQuery, AdminMutation, EmptySubscription> {
|
|
async_graphql::Schema::build(AdminQuery, AdminMutation, EmptySubscription)
|
|
.data(Arc::new(db))
|
|
.finish()
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct SeaographyState {
|
|
pub schema: DynamicSchema,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct JobsState {
|
|
pub schema: async_graphql::Schema<AdminQuery, AdminMutation, EmptySubscription>,
|
|
}
|
|
|
|
/// Seaography GraphQL POST handler for entity CRUD
|
|
async fn seaography_handler(
|
|
State(state): State<Arc<SeaographyState>>,
|
|
req: GraphQLRequest,
|
|
) -> GraphQLResponse {
|
|
state.schema.execute(req.into_inner()).await.into()
|
|
}
|
|
|
|
/// Jobs GraphQL POST handler for job management
|
|
async fn jobs_handler(
|
|
State(state): State<Arc<JobsState>>,
|
|
req: GraphQLRequest,
|
|
) -> GraphQLResponse {
|
|
state.schema.execute(req.into_inner()).await.into()
|
|
}
|
|
|
|
/// Seaography GraphQL playground (GraphiQL) handler
|
|
async fn seaography_playground() -> impl IntoResponse {
|
|
axum::response::Html(
|
|
async_graphql::http::GraphiQLSource::build()
|
|
.endpoint("/admin/graphql")
|
|
.finish(),
|
|
)
|
|
}
|
|
|
|
/// Jobs GraphQL playground (GraphiQL) handler
|
|
async fn jobs_playground() -> impl IntoResponse {
|
|
axum::response::Html(
|
|
async_graphql::http::GraphiQLSource::build()
|
|
.endpoint("/admin/jobs")
|
|
.finish(),
|
|
)
|
|
}
|
|
|
|
/// Create the admin API router with both Seaography and custom job endpoints
|
|
pub fn router(
|
|
seaography_schema: DynamicSchema,
|
|
jobs_schema: async_graphql::Schema<AdminQuery, AdminMutation, EmptySubscription>,
|
|
) -> Router {
|
|
let seaography_state = Arc::new(SeaographyState {
|
|
schema: seaography_schema,
|
|
});
|
|
let jobs_state = Arc::new(JobsState {
|
|
schema: jobs_schema,
|
|
});
|
|
|
|
Router::new()
|
|
// Seaography entity CRUD
|
|
.route("/admin/graphql", post(seaography_handler))
|
|
.route("/admin/playground", get(seaography_playground))
|
|
.with_state(seaography_state)
|
|
// Custom job management
|
|
.route("/admin/jobs", post(jobs_handler))
|
|
.route("/admin/jobs/playground", get(jobs_playground))
|
|
.with_state(jobs_state)
|
|
}
|