feat: introduce CourseEditorLayout and AppHeader, add organization domain migration, and update Docker configurations and auth scripts
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
target
|
||||
**/*.rs.bk
|
||||
.env
|
||||
.env.*
|
||||
! .env.example
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Migration: Add domain to organizations
|
||||
ALTER TABLE organizations ADD COLUMN IF NOT EXISTS domain VARCHAR(255) UNIQUE;
|
||||
@@ -1474,3 +1474,50 @@ pub async fn update_user(
|
||||
|
||||
Ok(StatusCode::OK)
|
||||
}
|
||||
|
||||
// Organizations Management (Plural/Admin)
|
||||
pub async fn get_organizations(
|
||||
claims: common::auth::Claims,
|
||||
State(pool): State<PgPool>,
|
||||
) -> Result<Json<Vec<Organization>>, StatusCode> {
|
||||
if claims.role != "admin" {
|
||||
return Err(StatusCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
let orgs = sqlx::query_as::<_, Organization>("SELECT * FROM organizations ORDER BY created_at DESC")
|
||||
.fetch_all(&pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Failed to fetch organizations: {}", e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})?;
|
||||
|
||||
Ok(Json(orgs))
|
||||
}
|
||||
|
||||
pub async fn create_organization(
|
||||
claims: common::auth::Claims,
|
||||
State(pool): State<PgPool>,
|
||||
Json(payload): Json<serde_json::Value>,
|
||||
) -> Result<Json<Organization>, StatusCode> {
|
||||
if claims.role != "admin" {
|
||||
return Err(StatusCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
let name = payload.get("name").and_then(|v| v.as_str()).ok_or(StatusCode::BAD_REQUEST)?;
|
||||
let domain = payload.get("domain").and_then(|v| v.as_str());
|
||||
|
||||
let org = sqlx::query_as::<_, Organization>(
|
||||
"INSERT INTO organizations (name, domain) VALUES ($1, $2) RETURNING *"
|
||||
)
|
||||
.bind(name)
|
||||
.bind(domain)
|
||||
.fetch_one(&pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("Failed to create organization: {}", e);
|
||||
StatusCode::INTERNAL_SERVER_ERROR
|
||||
})?;
|
||||
|
||||
Ok(Json(org))
|
||||
}
|
||||
|
||||
@@ -86,6 +86,7 @@ async fn main() {
|
||||
.route("/users/{id}", axum::routing::put(handlers::update_user))
|
||||
.route("/audit-logs", get(handlers::get_audit_logs))
|
||||
.route("/assets/upload", post(handlers::upload_asset))
|
||||
.route("/organizations", get(handlers::get_organizations).post(handlers::create_organization))
|
||||
.route("/organization", get(handlers::get_organization))
|
||||
.route(
|
||||
"/organizations/{id}/logo",
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
target
|
||||
**/*.rs.bk
|
||||
.env
|
||||
.env.*
|
||||
! .env.example
|
||||
@@ -101,6 +101,7 @@ pub async fn register(
|
||||
email: user.email,
|
||||
full_name: user.full_name,
|
||||
role: user.role,
|
||||
organization_id: user.organization_id,
|
||||
},
|
||||
token,
|
||||
}))
|
||||
@@ -129,6 +130,7 @@ pub async fn login(
|
||||
email: user.email,
|
||||
full_name: user.full_name,
|
||||
role: user.role,
|
||||
organization_id: user.organization_id,
|
||||
},
|
||||
token,
|
||||
}))
|
||||
|
||||
Reference in New Issue
Block a user