Files
openccb/services/lms-service/src/live.rs
T
Nurfog 2c8bfaa20e chore: update dependencies and improve MermaidBlock security
- Updated mermaid from version 11.13.0 to 9.1.7 for compatibility.
- Upgraded next from version 14.2.21 to ^14.2.35 for the latest features and fixes.
- Added @types/dompurify and isomorphic-dompurify for improved sanitization.
- Replaced innerHTML assignment in MermaidBlock with sanitized SVG using DOMPurify.
- Updated eslint-config-next to ^16.2.4 for better linting support.
2026-04-28 15:15:16 -04:00

91 lines
2.7 KiB
Rust

use axum::{
extract::{Path, State},
http::StatusCode,
Json,
};
use chrono::Utc;
use common::auth::Claims;
use common::models::Meeting;
use sqlx::PgPool;
use uuid::Uuid;
use serde::Deserialize;
#[derive(Deserialize)]
pub struct CreateMeetingPayload {
pub title: String,
pub description: Option<String>,
pub start_at: chrono::DateTime<Utc>,
pub duration_minutes: i32,
}
pub async fn get_course_meetings(
Path(course_id): Path<Uuid>,
State(pool): State<PgPool>,
claims: Claims,
) -> Result<Json<Vec<Meeting>>, (StatusCode, String)> {
let meetings = sqlx::query_as::<sqlx::Postgres, Meeting>(
"SELECT * FROM meetings WHERE course_id = $1 AND organization_id = $2 ORDER BY start_at ASC"
)
.bind(course_id)
.bind(claims.org)
.fetch_all(&pool)
.await
.map_err(|e: sqlx::Error| (StatusCode::INTERNAL_SERVER_ERROR, "Error interno del servidor".to_string()))?;
Ok(Json(meetings))
}
pub async fn create_meeting(
Path(course_id): Path<Uuid>,
State(pool): State<PgPool>,
claims: Claims,
Json(payload): Json<CreateMeetingPayload>,
) -> Result<Json<Meeting>, (StatusCode, String)> {
if claims.role == "student" {
return Err((StatusCode::FORBIDDEN, "Solo los instructores pueden crear reuniones".to_string()));
}
let meeting_id = format!("openccb-{}", Uuid::new_v4());
let join_url = format!("https://meet.jit.si/{}", meeting_id);
let meeting = sqlx::query_as::<sqlx::Postgres, Meeting>(
r#"
INSERT INTO meetings (organization_id, course_id, title, description, provider, meeting_id, start_at, duration_minutes, join_url)
VALUES ($1, $2, $3, $4, 'jitsi', $5, $6, $7, $8)
RETURNING *
"#,
)
.bind(claims.org)
.bind(course_id)
.bind(payload.title)
.bind(payload.description)
.bind(meeting_id)
.bind(payload.start_at)
.bind(payload.duration_minutes)
.bind(join_url)
.fetch_one(&pool)
.await
.map_err(|e: sqlx::Error| (StatusCode::INTERNAL_SERVER_ERROR, "Error interno del servidor".to_string()))?;
Ok(Json(meeting))
}
pub async fn delete_meeting(
Path((_course_id, meeting_id)): Path<(Uuid, Uuid)>,
State(pool): State<PgPool>,
claims: Claims,
) -> Result<StatusCode, (StatusCode, String)> {
if claims.role == "student" {
return Err((StatusCode::FORBIDDEN, "Solo los instructores pueden eliminar reuniones".to_string()));
}
sqlx::query("DELETE FROM meetings WHERE id = $1 AND organization_id = $2")
.bind(meeting_id)
.bind(claims.org)
.execute(&pool)
.await
.map_err(|e: sqlx::Error| (StatusCode::INTERNAL_SERVER_ERROR, "Error interno del servidor".to_string()))?;
Ok(StatusCode::NO_CONTENT)
}