Add registration.type configuration option
This commit is contained in:
parent
b82c2f3fc6
commit
771f45baab
11 changed files with 92 additions and 17 deletions
|
@ -9,6 +9,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Added `approval_required` and `invites_enabled` flags to `/api/v1/instance` endpoint response.
|
- Added `approval_required` and `invites_enabled` flags to `/api/v1/instance` endpoint response.
|
||||||
|
- Added `registration.type` configuration option (replaces `registrations_open`).
|
||||||
|
|
||||||
|
### Deprecated
|
||||||
|
|
||||||
|
- `registrations_open` configuration option.
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,9 @@ instance_uri: 127.0.0.1:8380
|
||||||
instance_title: Mitra
|
instance_title: Mitra
|
||||||
instance_short_description: My instance
|
instance_short_description: My instance
|
||||||
instance_description: My instance
|
instance_description: My instance
|
||||||
registrations_open: true
|
|
||||||
|
registration:
|
||||||
|
type: open
|
||||||
|
|
||||||
blockchains:
|
blockchains:
|
||||||
# Parameters for hardhat local node
|
# Parameters for hardhat local node
|
||||||
|
|
|
@ -18,7 +18,9 @@ instance_short_description: my instance
|
||||||
# Long description can contain markdown syntax
|
# Long description can contain markdown syntax
|
||||||
instance_description: my instance
|
instance_description: my instance
|
||||||
|
|
||||||
registrations_open: false
|
registration:
|
||||||
|
# Possible values: open, invite
|
||||||
|
type: invite
|
||||||
|
|
||||||
# EIP-4361 login message
|
# EIP-4361 login message
|
||||||
#login_message: 'Do not sign this message on other sites!'
|
#login_message: 'Do not sign this message on other sites!'
|
||||||
|
|
|
@ -17,9 +17,13 @@ async fn main() {
|
||||||
SubCommand::GenerateEthereumAddress(cmd) => cmd.execute(),
|
SubCommand::GenerateEthereumAddress(cmd) => cmd.execute(),
|
||||||
subcmd => {
|
subcmd => {
|
||||||
// Other commands require initialized app
|
// Other commands require initialized app
|
||||||
let config = parse_config();
|
let (config, config_warnings) = parse_config();
|
||||||
configure_logger(config.log_level);
|
configure_logger(config.log_level);
|
||||||
log::info!("config loaded from {}", config.config_path);
|
log::info!("config loaded from {}", config.config_path);
|
||||||
|
for warning in config_warnings {
|
||||||
|
log::warn!("{}", warning);
|
||||||
|
};
|
||||||
|
|
||||||
let db_config = config.database_url.parse().unwrap();
|
let db_config = config.database_url.parse().unwrap();
|
||||||
let db_client = &mut create_database_client(&db_config).await;
|
let db_client = &mut create_database_client(&db_config).await;
|
||||||
apply_migrations(db_client).await;
|
apply_migrations(db_client).await;
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::utils::crypto_rsa::{
|
||||||
use crate::utils::files::{set_file_permissions, write_file};
|
use crate::utils::files::{set_file_permissions, write_file};
|
||||||
|
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
use super::main::Config;
|
use super::main::{Config, RegistrationType};
|
||||||
|
|
||||||
struct EnvConfig {
|
struct EnvConfig {
|
||||||
config_path: String,
|
config_path: String,
|
||||||
|
@ -78,12 +78,14 @@ fn read_instance_rsa_key(storage_dir: &Path) -> RsaPrivateKey {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_config() -> Config {
|
pub fn parse_config() -> (Config, Vec<&'static str>) {
|
||||||
let env = parse_env();
|
let env = parse_env();
|
||||||
let config_yaml = std::fs::read_to_string(&env.config_path)
|
let config_yaml = std::fs::read_to_string(&env.config_path)
|
||||||
.expect("failed to load config file");
|
.expect("failed to load config file");
|
||||||
let mut config = serde_yaml::from_str::<Config>(&config_yaml)
|
let mut config = serde_yaml::from_str::<Config>(&config_yaml)
|
||||||
.expect("invalid yaml data");
|
.expect("invalid yaml data");
|
||||||
|
let mut warnings = vec![];
|
||||||
|
|
||||||
// Set parameters from environment
|
// Set parameters from environment
|
||||||
config.config_path = env.config_path;
|
config.config_path = env.config_path;
|
||||||
if let Some(environment) = env.environment {
|
if let Some(environment) = env.environment {
|
||||||
|
@ -109,8 +111,18 @@ pub fn parse_config() -> Config {
|
||||||
panic!("both ipfs_api_url and ipfs_gateway_url must be set");
|
panic!("both ipfs_api_url and ipfs_gateway_url must be set");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(registrations_open) = config.registrations_open {
|
||||||
|
// Change type if 'registrations_open' parameter is used
|
||||||
|
warnings.push("'registrations_open' setting is deprecated, use 'registration' instead");
|
||||||
|
if registrations_open {
|
||||||
|
config.registration.registration_type = RegistrationType::Open;
|
||||||
|
} else {
|
||||||
|
config.registration.registration_type = RegistrationType::Invite;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// Insert instance RSA key
|
// Insert instance RSA key
|
||||||
config.instance_rsa_key = Some(read_instance_rsa_key(&config.storage_dir));
|
config.instance_rsa_key = Some(read_instance_rsa_key(&config.storage_dir));
|
||||||
|
|
||||||
config
|
(config, warnings)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@ use std::path::PathBuf;
|
||||||
|
|
||||||
use log::{Level as LogLevel};
|
use log::{Level as LogLevel};
|
||||||
use rsa::RsaPrivateKey;
|
use rsa::RsaPrivateKey;
|
||||||
use serde::Deserialize;
|
use serde::{
|
||||||
|
Deserialize,
|
||||||
|
Deserializer,
|
||||||
|
de::Error as DeserializerError,
|
||||||
|
};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
use crate::activitypub::constants::ACTOR_KEY_SUFFIX;
|
use crate::activitypub::constants::ACTOR_KEY_SUFFIX;
|
||||||
|
@ -14,6 +18,36 @@ use super::blockchain::BlockchainConfig;
|
||||||
use super::environment::Environment;
|
use super::environment::Environment;
|
||||||
use super::MITRA_VERSION;
|
use super::MITRA_VERSION;
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq)]
|
||||||
|
pub enum RegistrationType {
|
||||||
|
Open,
|
||||||
|
Invite,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for RegistrationType {
|
||||||
|
fn default() -> Self { Self::Invite }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for RegistrationType {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
|
where D: Deserializer<'de>
|
||||||
|
{
|
||||||
|
let registration_type_str = String::deserialize(deserializer)?;
|
||||||
|
let registration_type = match registration_type_str.as_str() {
|
||||||
|
"open" => Self::Open,
|
||||||
|
"invite" => Self::Invite,
|
||||||
|
_ => return Err(DeserializerError::custom("unknown registration type")),
|
||||||
|
};
|
||||||
|
Ok(registration_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Default, Deserialize)]
|
||||||
|
pub struct RegistrationConfig {
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub registration_type: RegistrationType,
|
||||||
|
}
|
||||||
|
|
||||||
fn default_log_level() -> LogLevel { LogLevel::Info }
|
fn default_log_level() -> LogLevel { LogLevel::Info }
|
||||||
|
|
||||||
fn default_login_message() -> String { "Do not sign this message on other sites!".to_string() }
|
fn default_login_message() -> String { "Do not sign this message on other sites!".to_string() }
|
||||||
|
@ -52,8 +86,10 @@ pub struct Config {
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub(super) instance_rsa_key: Option<RsaPrivateKey>,
|
pub(super) instance_rsa_key: Option<RsaPrivateKey>,
|
||||||
|
|
||||||
|
pub(super) registrations_open: Option<bool>, // deprecated
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub registrations_open: bool, // default is false
|
pub registration: RegistrationConfig,
|
||||||
|
|
||||||
// EIP-4361 login message
|
// EIP-4361 login message
|
||||||
#[serde(default = "default_login_message")]
|
#[serde(default = "default_login_message")]
|
||||||
|
|
|
@ -10,6 +10,6 @@ pub use blockchain::{
|
||||||
};
|
};
|
||||||
pub use environment::Environment;
|
pub use environment::Environment;
|
||||||
pub use loader::parse_config;
|
pub use loader::parse_config;
|
||||||
pub use main::{Config, Instance};
|
pub use main::{Config, Instance, RegistrationType};
|
||||||
|
|
||||||
pub const MITRA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
pub const MITRA_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
|
|
|
@ -39,9 +39,12 @@ use mitra::web_client::views as web_client;
|
||||||
|
|
||||||
#[actix_web::main]
|
#[actix_web::main]
|
||||||
async fn main() -> std::io::Result<()> {
|
async fn main() -> std::io::Result<()> {
|
||||||
let config = parse_config();
|
let (config, config_warnings) = parse_config();
|
||||||
configure_logger(config.log_level);
|
configure_logger(config.log_level);
|
||||||
log::info!("config loaded from {}", config.config_path);
|
log::info!("config loaded from {}", config.config_path);
|
||||||
|
for warning in config_warnings {
|
||||||
|
log::warn!("{}", warning);
|
||||||
|
};
|
||||||
|
|
||||||
let db_pool = create_pool(&config.database_url);
|
let db_pool = create_pool(&config.database_url);
|
||||||
let mut db_client = get_database_client(&db_pool).await.unwrap();
|
let mut db_client = get_database_client(&db_pool).await.unwrap();
|
||||||
|
|
|
@ -12,7 +12,7 @@ use crate::activitypub::builders::{
|
||||||
prepare_update_person,
|
prepare_update_person,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use crate::config::Config;
|
use crate::config::{Config, RegistrationType};
|
||||||
use crate::database::{get_database_client, DatabaseError, DbPool};
|
use crate::database::{get_database_client, DatabaseError, DbPool};
|
||||||
use crate::errors::{HttpError, ValidationError};
|
use crate::errors::{HttpError, ValidationError};
|
||||||
use crate::ethereum::contracts::ContractSet;
|
use crate::ethereum::contracts::ContractSet;
|
||||||
|
@ -111,7 +111,7 @@ pub async fn create_account(
|
||||||
let db_client = &mut **get_database_client(&db_pool).await?;
|
let db_client = &mut **get_database_client(&db_pool).await?;
|
||||||
// Validate
|
// Validate
|
||||||
account_data.clean()?;
|
account_data.clean()?;
|
||||||
if !config.registrations_open {
|
if config.registration.registration_type == RegistrationType::Invite {
|
||||||
let invite_code = account_data.invite_code.as_ref()
|
let invite_code = account_data.invite_code.as_ref()
|
||||||
.ok_or(ValidationError("invite code is required"))?;
|
.ok_or(ValidationError("invite code is required"))?;
|
||||||
if !is_valid_invite_code(db_client, invite_code).await? {
|
if !is_valid_invite_code(db_client, invite_code).await? {
|
||||||
|
|
|
@ -1,7 +1,12 @@
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::{to_value, Value};
|
use serde_json::{to_value, Value};
|
||||||
|
|
||||||
use crate::config::{BlockchainConfig, Config, MITRA_VERSION};
|
use crate::config::{
|
||||||
|
BlockchainConfig,
|
||||||
|
Config,
|
||||||
|
RegistrationType,
|
||||||
|
MITRA_VERSION,
|
||||||
|
};
|
||||||
use crate::ethereum::contracts::ContractSet;
|
use crate::ethereum::contracts::ContractSet;
|
||||||
use crate::mastodon_api::{
|
use crate::mastodon_api::{
|
||||||
MASTODON_API_VERSION,
|
MASTODON_API_VERSION,
|
||||||
|
@ -139,9 +144,13 @@ impl InstanceInfo {
|
||||||
description: markdown_to_html(&config.instance_description),
|
description: markdown_to_html(&config.instance_description),
|
||||||
description_source: config.instance_description.clone(),
|
description_source: config.instance_description.clone(),
|
||||||
version: get_full_api_version(MITRA_VERSION),
|
version: get_full_api_version(MITRA_VERSION),
|
||||||
registrations: config.registrations_open,
|
registrations:
|
||||||
|
config.registration.registration_type !=
|
||||||
|
RegistrationType::Invite,
|
||||||
approval_required: false,
|
approval_required: false,
|
||||||
invites_enabled: !config.registrations_open,
|
invites_enabled:
|
||||||
|
config.registration.registration_type ==
|
||||||
|
RegistrationType::Invite,
|
||||||
stats: InstanceStats {
|
stats: InstanceStats {
|
||||||
user_count,
|
user_count,
|
||||||
status_count: post_count,
|
status_count: post_count,
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::config::{Config, MITRA_VERSION};
|
use crate::config::{Config, RegistrationType, MITRA_VERSION};
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct Software {
|
struct Software {
|
||||||
|
@ -66,7 +66,9 @@ impl NodeInfo20 {
|
||||||
software,
|
software,
|
||||||
protocols: vec!["activitypub".to_string()],
|
protocols: vec!["activitypub".to_string()],
|
||||||
services,
|
services,
|
||||||
open_registrations: config.registrations_open,
|
open_registrations:
|
||||||
|
config.registration.registration_type !=
|
||||||
|
RegistrationType::Invite,
|
||||||
usage,
|
usage,
|
||||||
metadata,
|
metadata,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue