feat: add access control to channels with various modes
- Introduced AccessMode enum to define channel access levels: Public, PasswordProtected, AccountRequired, and OwnerOnly. - Updated Channel and ProgrammingBlock entities to include access_mode and access_password_hash fields. - Enhanced create and update channel functionality to handle access mode and password. - Implemented access checks in channel routes based on the defined access modes. - Modified frontend components to support channel creation and editing with access control options. - Added ChannelPasswordModal for handling password input when accessing restricted channels. - Updated API calls to include channel and block passwords as needed. - Created database migrations to add access_mode and access_password_hash columns to channels table.
This commit is contained in:
@@ -8,6 +8,8 @@ use axum::{Router, routing::{get, post}};
|
||||
use chrono::{DateTime, Utc};
|
||||
use uuid::Uuid;
|
||||
|
||||
use domain::{AccessMode, User};
|
||||
|
||||
use crate::{error::ApiError, state::AppState};
|
||||
|
||||
mod broadcast;
|
||||
@@ -42,6 +44,40 @@ pub(super) fn require_owner(channel: &domain::Channel, user_id: Uuid) -> Result<
|
||||
}
|
||||
}
|
||||
|
||||
/// Gate access to a channel or block based on its `AccessMode`.
|
||||
pub(super) fn check_access(
|
||||
mode: &AccessMode,
|
||||
password_hash: Option<&str>,
|
||||
user: Option<&User>,
|
||||
owner_id: Uuid,
|
||||
supplied_password: Option<&str>,
|
||||
) -> Result<(), ApiError> {
|
||||
match mode {
|
||||
AccessMode::Public => Ok(()),
|
||||
AccessMode::PasswordProtected => {
|
||||
let hash = password_hash.ok_or(ApiError::PasswordRequired)?;
|
||||
let supplied = supplied_password.unwrap_or("").trim();
|
||||
if supplied.is_empty() {
|
||||
return Err(ApiError::PasswordRequired);
|
||||
}
|
||||
if !infra::auth::verify_password(supplied, hash) {
|
||||
return Err(ApiError::PasswordRequired);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
AccessMode::AccountRequired => {
|
||||
if user.is_some() { Ok(()) } else { Err(ApiError::AuthRequired) }
|
||||
}
|
||||
AccessMode::OwnerOnly => {
|
||||
if user.map(|u| u.id) == Some(owner_id) {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(ApiError::Forbidden("owner only".into()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn parse_optional_dt(
|
||||
s: Option<String>,
|
||||
default: DateTime<Utc>,
|
||||
|
||||
Reference in New Issue
Block a user