env vars handling code: slight cleanup

This commit is contained in:
Armaël Guéneau 2025-01-03 12:01:47 +01:00
parent 5614796e71
commit 812eee1a5f
4 changed files with 49 additions and 54 deletions

View file

@ -14,34 +14,33 @@
## Configuration
Forgery reads the following environment variables:
- `FORGE_URL`: url of the forgejo instance (e.g. https://git.deuxfleurs.fr)
- `FORGE_API_TOKEN`: Forgejo API token *granting admin access*. Required. You
can generate an API token using the Forgejo web interface in `Settings ->
- `FORGE_URL` (**mandatory**): url of the forgejo instance (e.g.
https://git.deuxfleurs.fr)
- `FORGE_API_TOKEN` (**mandatory**): Forgejo API token *granting admin access*.
You can generate an API token using the Forgejo web interface in `Settings ->
Applications -> Generate New Token`.
- `ORG_NAME`: organization name (used in the notification email sent when
locking accounts)
- `ADMIN_CONTACT_EMAIL`: email that can be used to contact admins of your
instance (included in the notification email sent when locking accounts)
- `ACTUALLY_BAN_USERS`: define it to `true` to actually lock user accounts, send
notification emails and eventually delete user accounts. If not defined (the
default) or set to `false`, no actual action is taken: spammers are only
listed in the database. The variable should be set in production, but probably
not for testing.
- `STORAGE_BACKEND`: either `local` (default) or `s3`. Chose `local` to store
the application state to local files, or `s3` to store them in S3-compatible
storage (see below for corresponding configuration variables).
- `LISTEN_ADDR`: address on which the webserver listens (default: `0.0.0.0`)
- `LISTEN_PORT`: port on which the webserver listens (default: `8080`)
- `ACTUALLY_BAN_USERS` (default: `false`): define it to `true` to actually lock
user accounts, send notification emails and eventually delete user accounts.
Otherwise, no actual action is taken: spammers are only listed in the
database. The variable should be set in production, but probably not for
testing.
- `STORAGE_BACKEND` (default: `local`): either `local` or `s3`. Chose `local` to
store the application state to local files, or `s3` to store them in
S3-compatible storage (see below for corresponding configuration variables).
- `BIND_ADDR` (default: `127.0.0.1:8080`): address on which the webserver listens
Environment variables read when `ACTUALLY_BAN_USERS=true`:
- `SMTP_ADDRESS`: address of the SMTP relay used to send email notifications
- `SMTP_USERNAME`: SMTP username
- `SMTP_PASSWORD`: SMTP password
- `ADMIN_CONTACT_EMAIL`: email that can be used to contact admins of your
instance (included in the notification email sent when locking accounts)
- `ORG_NAME`: organization name (used in the notification email sent when
locking accounts)
Environment variables read when `STORAGE_BACKEND=local`:
- `STORAGE_LOCAL_DIR`: path to a local directory where to store the application
data (as two files `db.json` and `model.json`). Defaults to `.` if not
defined.
- `STORAGE_LOCAL_DIR` (default: `.`): path to a local directory where to store
the application data (as two files `db.json` and `model.json`).
Environment variables read when `STORAGE_BACKEND=s3`:
- `STORAGE_S3_BUCKET`: name of the bucket where to store the application data

View file

@ -39,13 +39,13 @@ impl SmtpConfig {
pub async fn send_locked_account_notice(
config: &Config,
smtp: &SmtpConfig,
admin_contact_email: &str,
org_name: &str,
login: &str,
email: &str,
) -> anyhow::Result<()> {
let grace_period_days = crate::GRACE_PERIOD.as_secs() / (24 * 3600);
let org_name = &config.org_name;
let forge_url = &config.forge_url;
let admin_contact_email = &config.admin_contact_email;
let email = Message::builder()
.from(smtp.username.parse().unwrap())

View file

@ -56,23 +56,20 @@ const GUESS_LEGIT_THRESHOLD: f32 = 0.3;
pub struct Config {
pub forge_url: Url,
pub forge_api_token: String,
pub org_name: String,
pub admin_contact_email: String,
pub actually_ban: ActuallyBan,
pub listen_addr: String,
pub listen_port: u16,
pub bind_addr: String,
}
impl Config {
async fn from_env() -> anyhow::Result<Self> {
let forge_url_s = env_var("FORGE_URL")?;
let forge_api_token = env_var("FORGE_API_TOKEN")?;
let org_name = env_var("ORG_NAME")?;
let admin_contact_email = env_var("ADMIN_CONTACT_EMAIL")?;
let actually_ban = match env_var("ACTUALLY_BAN_USERS").as_deref() {
Ok("true") => ActuallyBan::Yes {
smtp: SmtpConfig::from_env().await?,
admin_contact_email: env_var("ADMIN_CONTACT_EMAIL")?,
org_name: env_var("ORG_NAME")?,
},
Ok("false") => ActuallyBan::No,
Ok(_) => {
@ -83,21 +80,13 @@ impl Config {
Err(_) => ActuallyBan::No,
};
let listen_addr = env_var("LISTEN_ADDR").unwrap_or(String::from("0.0.0.0"));
let listen_port: u16 = match env_var("LISTEN_PORT").map(|s| u16::from_str_radix(&s, 10)) {
Ok(Err(e)) => return Err(anyhow!("LISTEN_PORT: invalid value ({})", e)),
Ok(Ok(p)) => p,
Err(_) => 8080,
};
let bind_addr = env_var("BIND_ADDR").unwrap_or(String::from("127.0.0.1:8080"));
Ok(Config {
forge_url: Url::parse(&forge_url_s).context("parsing FORGE_URL")?,
forge_api_token,
org_name,
admin_contact_email,
actually_ban,
listen_addr,
listen_port,
bind_addr,
})
}
}
@ -105,7 +94,11 @@ impl Config {
// Whether we are actually banning users or are instead in "testing" mode where
// we don't do anything. (Defaults to "No".)
pub enum ActuallyBan {
Yes { smtp: SmtpConfig },
Yes {
smtp: SmtpConfig,
admin_contact_email: String,
org_name: String,
},
No,
}
@ -496,15 +489,7 @@ async fn main() -> anyhow::Result<()> {
.spawn(async move { workers::lock_and_notify_users(config, storage, forge, db).await })
};
println!(
"Listening on http://{}:{}",
(if config.listen_addr == "0.0.0.0" {
"127.0.0.1"
} else {
&config.listen_addr
}),
config.listen_port
);
println!("Listening on http://{}", &config.bind_addr);
let app = Router::new()
.route("/", get(get_index).post(post_classified_index))
@ -516,10 +501,9 @@ async fn main() -> anyhow::Result<()> {
.with_state(shared_state);
let webserver = {
let listener =
tokio::net::TcpListener::bind((config.listen_addr.clone(), config.listen_port))
.await
.unwrap();
let listener = tokio::net::TcpListener::bind(&config.bind_addr)
.await
.unwrap();
axum::serve(listener, app)
};

View file

@ -237,9 +237,21 @@ pub async fn try_lock_and_notify_user(
if !notified {
match &config.actually_ban {
ActuallyBan::Yes { smtp } => {
ActuallyBan::Yes {
smtp,
admin_contact_email,
org_name,
} => {
eprintln!("Sending notification email to user {login}");
email::send_locked_account_notice(config, smtp, &login, &email).await?;
email::send_locked_account_notice(
config,
smtp,
&admin_contact_email,
&org_name,
&login,
&email,
)
.await?;
eprintln!("Success");
}
ActuallyBan::No => {