Can register new clients
This commit is contained in:
@ -1,12 +1,14 @@
|
||||
use crate::app_config::AppConfig;
|
||||
use crate::constants::{STATE_KEY, USER_SESSION_KEY};
|
||||
use crate::server::{HttpFailure, HttpResult};
|
||||
use crate::user::{User, UserConfig, UserID};
|
||||
use crate::user::{APIClient, User, UserConfig, UserID};
|
||||
use crate::utils;
|
||||
use actix_session::Session;
|
||||
use actix_web::{web, HttpResponse};
|
||||
use askama::Template;
|
||||
use ipnet::IpNet;
|
||||
use light_openid::primitives::OpenIDConfig;
|
||||
use std::str::FromStr;
|
||||
|
||||
/// Static assets
|
||||
#[derive(rust_embed::Embed)]
|
||||
@ -36,17 +38,21 @@ struct HomeTemplate {
|
||||
error_message: Option<String>,
|
||||
}
|
||||
|
||||
/// Update matrix token request
|
||||
/// HTTP form request
|
||||
#[derive(serde::Deserialize)]
|
||||
pub struct UpdateMatrixToken {
|
||||
pub struct FormRequest {
|
||||
/// Update matrix token
|
||||
new_matrix_token: Option<String>,
|
||||
|
||||
/// Create a new client
|
||||
new_client_desc: Option<String>,
|
||||
|
||||
/// Restrict new client to a given network
|
||||
ip_network: Option<String>,
|
||||
}
|
||||
|
||||
/// Main route
|
||||
pub async fn home(
|
||||
session: Session,
|
||||
update_matrix_token: Option<web::Form<UpdateMatrixToken>>,
|
||||
) -> HttpResult {
|
||||
pub async fn home(session: Session, form_req: Option<web::Form<FormRequest>>) -> HttpResult {
|
||||
// Get user information, requesting authentication if information is missing
|
||||
let Some(user): Option<User> = session.get(USER_SESSION_KEY)? else {
|
||||
// Generate auth state
|
||||
@ -73,9 +79,9 @@ pub async fn home(
|
||||
.await
|
||||
.map_err(HttpFailure::FetchUserConfig)?;
|
||||
|
||||
// Update matrix token, if requested
|
||||
if let Some(update_matrix_token) = update_matrix_token {
|
||||
if let Some(t) = update_matrix_token.0.new_matrix_token {
|
||||
if let Some(form_req) = form_req {
|
||||
// Update matrix token, if requested
|
||||
if let Some(t) = form_req.0.new_matrix_token {
|
||||
if t.len() < 3 {
|
||||
error_message = Some("Specified Matrix token is too short!".to_string());
|
||||
} else {
|
||||
@ -85,6 +91,28 @@ pub async fn home(
|
||||
success_message = Some("Matrix token was successfully updated!".to_string());
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new client, if requested
|
||||
if let Some(new_token_desc) = form_req.0.new_client_desc {
|
||||
let ip_net = match form_req.0.ip_network.as_deref() {
|
||||
None | Some("") => None,
|
||||
Some(e) => match IpNet::from_str(e) {
|
||||
Ok(n) => Some(n),
|
||||
Err(e) => {
|
||||
log::error!("Failed to parse IP network provided by user: {e}");
|
||||
error_message = Some(format!("Failed to parse restricted IP network: {e}"));
|
||||
None
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
if error_message.is_none() {
|
||||
let token = APIClient::generate(new_token_desc, ip_net);
|
||||
success_message = Some(format!("The secret of your new token is '{}'. Be sure to write it somewhere as you will not be able to recover it later!", token.secret));
|
||||
config.clients.push(token);
|
||||
config.save().await?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Render page
|
||||
|
37
src/user.rs
37
src/user.rs
@ -1,10 +1,11 @@
|
||||
use crate::app_config::AppConfig;
|
||||
use crate::utils::curr_time;
|
||||
use s3::error::S3Error;
|
||||
use s3::request::ResponseData;
|
||||
use s3::{Bucket, BucketConfiguration};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::app_config::AppConfig;
|
||||
use crate::utils::{curr_time, rand_str};
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum UserError {
|
||||
#[error("failed to fetch user configuration: {0}")]
|
||||
@ -27,6 +28,34 @@ pub struct User {
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
/// Single API client information
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct APIClient {
|
||||
/// Client unique ID
|
||||
pub id: uuid::Uuid,
|
||||
|
||||
/// Client description
|
||||
pub description: String,
|
||||
|
||||
/// Restricted API network for token
|
||||
pub network: Option<ipnet::IpNet>,
|
||||
|
||||
/// Client secret
|
||||
pub secret: String,
|
||||
}
|
||||
|
||||
impl APIClient {
|
||||
/// Generate a new API client
|
||||
pub fn generate(description: String, network: Option<ipnet::IpNet>) -> Self {
|
||||
Self {
|
||||
id: Default::default(),
|
||||
description,
|
||||
network,
|
||||
secret: rand_str(20),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct UserConfig {
|
||||
/// Target user ID
|
||||
@ -40,6 +69,9 @@ pub struct UserConfig {
|
||||
|
||||
/// Current user matrix token
|
||||
pub matrix_token: String,
|
||||
|
||||
/// API clients
|
||||
pub clients: Vec<APIClient>,
|
||||
}
|
||||
|
||||
impl UserConfig {
|
||||
@ -97,6 +129,7 @@ impl UserConfig {
|
||||
created: curr_time()?,
|
||||
updated: curr_time()?,
|
||||
matrix_token: "".to_string(),
|
||||
clients: vec![],
|
||||
})
|
||||
}
|
||||
Err(e) => Err(UserError::FetchUserConfig(e).into()),
|
||||
|
Reference in New Issue
Block a user