diff --git a/.sqlx/query-23e11c1e470c49de109c7c88f4e161096ac6b83d1239ce910906a0d2d3d99d02.json b/.sqlx/query-23e11c1e470c49de109c7c88f4e161096ac6b83d1239ce910906a0d2d3d99d02.json new file mode 100644 index 0000000..88a427c --- /dev/null +++ b/.sqlx/query-23e11c1e470c49de109c7c88f4e161096ac6b83d1239ce910906a0d2d3d99d02.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM list_recipients WHERE list = $1 AND recipient = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "23e11c1e470c49de109c7c88f4e161096ac6b83d1239ce910906a0d2d3d99d02" +} diff --git a/.sqlx/query-31a4c053d4c984e9d0d5820487525e07f00fada97ec87581bc80a68f3dd11ee2.json b/.sqlx/query-31a4c053d4c984e9d0d5820487525e07f00fada97ec87581bc80a68f3dd11ee2.json new file mode 100644 index 0000000..2cda393 --- /dev/null +++ b/.sqlx/query-31a4c053d4c984e9d0d5820487525e07f00fada97ec87581bc80a68f3dd11ee2.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT alias,dest FROM alias WHERE dest IN (SELECT mail FROM emails WHERE id = $1)\n ORDER BY lower(substring(alias from position('@' in alias)+1 )),lower(alias)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "alias", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "dest", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "31a4c053d4c984e9d0d5820487525e07f00fada97ec87581bc80a68f3dd11ee2" +} diff --git a/.sqlx/query-31a67e09c41b8b9cc3b3065590ab3850c915b7da3468ee658d842161098939ae.json b/.sqlx/query-31a67e09c41b8b9cc3b3065590ab3850c915b7da3468ee658d842161098939ae.json new file mode 100644 index 0000000..088666e --- /dev/null +++ b/.sqlx/query-31a67e09c41b8b9cc3b3065590ab3850c915b7da3468ee658d842161098939ae.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM emails WHERE id != $1 AND mail = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "31a67e09c41b8b9cc3b3065590ab3850c915b7da3468ee658d842161098939ae" +} diff --git a/.sqlx/query-3403255f07a53813f0a8163828bc933e6cc0d5436ad9ce5a8bfbba71a2c2903b.json b/.sqlx/query-3403255f07a53813f0a8163828bc933e6cc0d5436ad9ce5a8bfbba71a2c2903b.json new file mode 100644 index 0000000..f764c44 --- /dev/null +++ b/.sqlx/query-3403255f07a53813f0a8163828bc933e6cc0d5436ad9ce5a8bfbba71a2c2903b.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO emails (id, mail, type) VALUES ($1, $2, 'list') ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "3403255f07a53813f0a8163828bc933e6cc0d5436ad9ce5a8bfbba71a2c2903b" +} diff --git a/.sqlx/query-449dea2a3a52b67cf88878708ed00e7ff430ad3e46452940a61bd7d7dc06b204.json b/.sqlx/query-449dea2a3a52b67cf88878708ed00e7ff430ad3e46452940a61bd7d7dc06b204.json new file mode 100644 index 0000000..c99fae5 --- /dev/null +++ b/.sqlx/query-449dea2a3a52b67cf88878708ed00e7ff430ad3e46452940a61bd7d7dc06b204.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM list_recipients WHERE list = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "449dea2a3a52b67cf88878708ed00e7ff430ad3e46452940a61bd7d7dc06b204" +} diff --git a/.sqlx/query-46015003c53421ce280ca79e445796bd51dc72b1437a341ebe50549ac527c0be.json b/.sqlx/query-46015003c53421ce280ca79e445796bd51dc72b1437a341ebe50549ac527c0be.json new file mode 100644 index 0000000..f14a094 --- /dev/null +++ b/.sqlx/query-46015003c53421ce280ca79e445796bd51dc72b1437a341ebe50549ac527c0be.json @@ -0,0 +1,28 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT list_recipients.list as list,recipient\n FROM emails,list_recipients\n WHERE id = $1 AND emails.type = 'list' AND emails.mail = list_recipients.list\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "list", + "type_info": "Text" + }, + { + "ordinal": 1, + "name": "recipient", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false, + false + ] + }, + "hash": "46015003c53421ce280ca79e445796bd51dc72b1437a341ebe50549ac527c0be" +} diff --git a/.sqlx/query-542eacaa20dcac0437aafce6545630ffe65b7a8196d09ec1491374def326a258.json b/.sqlx/query-542eacaa20dcac0437aafce6545630ffe65b7a8196d09ec1491374def326a258.json new file mode 100644 index 0000000..07a784f --- /dev/null +++ b/.sqlx/query-542eacaa20dcac0437aafce6545630ffe65b7a8196d09ec1491374def326a258.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT id FROM accounts WHERE sub = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Uuid" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "542eacaa20dcac0437aafce6545630ffe65b7a8196d09ec1491374def326a258" +} diff --git a/.sqlx/query-567f765aebef4fbebd557387ab45e43200402bc30f6d982ba7c583a0c976d7f6.json b/.sqlx/query-567f765aebef4fbebd557387ab45e43200402bc30f6d982ba7c583a0c976d7f6.json new file mode 100644 index 0000000..91083e6 --- /dev/null +++ b/.sqlx/query-567f765aebef4fbebd557387ab45e43200402bc30f6d982ba7c583a0c976d7f6.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM emails WHERE id = $1 AND mail = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "567f765aebef4fbebd557387ab45e43200402bc30f6d982ba7c583a0c976d7f6" +} diff --git a/.sqlx/query-681be1e58f24e62eb2643204044e6f783d54ce228d9830fb4d46b13c6efffcb8.json b/.sqlx/query-681be1e58f24e62eb2643204044e6f783d54ce228d9830fb4d46b13c6efffcb8.json new file mode 100644 index 0000000..8ed1a8a --- /dev/null +++ b/.sqlx/query-681be1e58f24e62eb2643204044e6f783d54ce228d9830fb4d46b13c6efffcb8.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO list_recipients (list, recipient, type) VALUES ($1, $2, 'list') ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "681be1e58f24e62eb2643204044e6f783d54ce228d9830fb4d46b13c6efffcb8" +} diff --git a/.sqlx/query-7869c07f3affdabc150961ed9b9c0e1f8202208e32fca3b7c5da979b94aba02a.json b/.sqlx/query-7869c07f3affdabc150961ed9b9c0e1f8202208e32fca3b7c5da979b94aba02a.json new file mode 100644 index 0000000..7cd8a92 --- /dev/null +++ b/.sqlx/query-7869c07f3affdabc150961ed9b9c0e1f8202208e32fca3b7c5da979b94aba02a.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM alias WHERE alias = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "7869c07f3affdabc150961ed9b9c0e1f8202208e32fca3b7c5da979b94aba02a" +} diff --git a/.sqlx/query-8518449399c2ade2867d714efe1cfc8660b3a1bc735e69d5e92d85d00b81bcd2.json b/.sqlx/query-8518449399c2ade2867d714efe1cfc8660b3a1bc735e69d5e92d85d00b81bcd2.json new file mode 100644 index 0000000..bc48cad --- /dev/null +++ b/.sqlx/query-8518449399c2ade2867d714efe1cfc8660b3a1bc735e69d5e92d85d00b81bcd2.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO emails (id, mail, type) VALUES ($1, $2, 'alias') ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "8518449399c2ade2867d714efe1cfc8660b3a1bc735e69d5e92d85d00b81bcd2" +} diff --git a/.sqlx/query-9e23f135b4ec69fa4d99f797fd54c1fb7db93b3452c77065572a1c303e36cfdc.json b/.sqlx/query-9e23f135b4ec69fa4d99f797fd54c1fb7db93b3452c77065572a1c303e36cfdc.json new file mode 100644 index 0000000..49d4517 --- /dev/null +++ b/.sqlx/query-9e23f135b4ec69fa4d99f797fd54c1fb7db93b3452c77065572a1c303e36cfdc.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT mail \n FROM emails \n WHERE id = $1 AND type = 'list'\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "mail", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false + ] + }, + "hash": "9e23f135b4ec69fa4d99f797fd54c1fb7db93b3452c77065572a1c303e36cfdc" +} diff --git a/.sqlx/query-a17528ac7ef8aec3fe2de5925256d78201238e168fdea110af801682f03c8159.json b/.sqlx/query-a17528ac7ef8aec3fe2de5925256d78201238e168fdea110af801682f03c8159.json new file mode 100644 index 0000000..2a03395 --- /dev/null +++ b/.sqlx/query-a17528ac7ef8aec3fe2de5925256d78201238e168fdea110af801682f03c8159.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO accounts (id, sub) VALUES ($1, $2)", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "a17528ac7ef8aec3fe2de5925256d78201238e168fdea110af801682f03c8159" +} diff --git a/.sqlx/query-b1a3280e13824a918d2264dd7b5fdb1ce846aad8cb343c734169d9ecf6484ba2.json b/.sqlx/query-b1a3280e13824a918d2264dd7b5fdb1ce846aad8cb343c734169d9ecf6484ba2.json new file mode 100644 index 0000000..bf7cab3 --- /dev/null +++ b/.sqlx/query-b1a3280e13824a918d2264dd7b5fdb1ce846aad8cb343c734169d9ecf6484ba2.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO emails (id, mail, type) VALUES ($1, $2, 'primary') ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [] + }, + "hash": "b1a3280e13824a918d2264dd7b5fdb1ce846aad8cb343c734169d9ecf6484ba2" +} diff --git a/.sqlx/query-bbc7f016c7bd8e4ddfc3b393ce55e8d5a72158d502ac9b75da84cb9451d934e2.json b/.sqlx/query-bbc7f016c7bd8e4ddfc3b393ce55e8d5a72158d502ac9b75da84cb9451d934e2.json new file mode 100644 index 0000000..dc09b52 --- /dev/null +++ b/.sqlx/query-bbc7f016c7bd8e4ddfc3b393ce55e8d5a72158d502ac9b75da84cb9451d934e2.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE accounts SET password = $1 WHERE id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Uuid" + ] + }, + "nullable": [] + }, + "hash": "bbc7f016c7bd8e4ddfc3b393ce55e8d5a72158d502ac9b75da84cb9451d934e2" +} diff --git a/.sqlx/query-bd78c0a43f02328f6381ed68f79f812bd7cda553263260860812f646da20b7a1.json b/.sqlx/query-bd78c0a43f02328f6381ed68f79f812bd7cda553263260860812f646da20b7a1.json new file mode 100644 index 0000000..ff8c266 --- /dev/null +++ b/.sqlx/query-bd78c0a43f02328f6381ed68f79f812bd7cda553263260860812f646da20b7a1.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT mail \n FROM emails \n WHERE id = $1 AND type = 'primary'\n ORDER BY lower(substring(mail from position('@' in mail)+1 )),lower(mail)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "mail", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Uuid" + ] + }, + "nullable": [ + false + ] + }, + "hash": "bd78c0a43f02328f6381ed68f79f812bd7cda553263260860812f646da20b7a1" +} diff --git a/.sqlx/query-c4d597b5651efad2cc83bf83088a88be3bafeb004a9ffc4d21362c3897bd22d0.json b/.sqlx/query-c4d597b5651efad2cc83bf83088a88be3bafeb004a9ffc4d21362c3897bd22d0.json new file mode 100644 index 0000000..14378cc --- /dev/null +++ b/.sqlx/query-c4d597b5651efad2cc83bf83088a88be3bafeb004a9ffc4d21362c3897bd22d0.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM alias WHERE dest = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "c4d597b5651efad2cc83bf83088a88be3bafeb004a9ffc4d21362c3897bd22d0" +} diff --git a/.sqlx/query-ce862ed5cde153f4003bb2b28e3bbb9545e0d4f3847afcfb787a38dee1b38ec0.json b/.sqlx/query-ce862ed5cde153f4003bb2b28e3bbb9545e0d4f3847afcfb787a38dee1b38ec0.json new file mode 100644 index 0000000..b248ce9 --- /dev/null +++ b/.sqlx/query-ce862ed5cde153f4003bb2b28e3bbb9545e0d4f3847afcfb787a38dee1b38ec0.json @@ -0,0 +1,23 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM emails WHERE id = $1 AND mail = $2", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Uuid", + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "ce862ed5cde153f4003bb2b28e3bbb9545e0d4f3847afcfb787a38dee1b38ec0" +} diff --git a/.sqlx/query-ebe5f8137e9f535eaf7d494b89d4bb442783e5e2135b53cada6d256e976c4857.json b/.sqlx/query-ebe5f8137e9f535eaf7d494b89d4bb442783e5e2135b53cada6d256e976c4857.json new file mode 100644 index 0000000..0949a22 --- /dev/null +++ b/.sqlx/query-ebe5f8137e9f535eaf7d494b89d4bb442783e5e2135b53cada6d256e976c4857.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "INSERT INTO alias (alias, type, dest) VALUES ($1, 'alias', $2) ON CONFLICT DO NOTHING", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text", + "Text" + ] + }, + "nullable": [] + }, + "hash": "ebe5f8137e9f535eaf7d494b89d4bb442783e5e2135b53cada6d256e976c4857" +} diff --git a/.sqlx/query-f66e03782ba7379cdacb638e0dc2e867408e04290d94df064e874f8d565f9fa7.json b/.sqlx/query-f66e03782ba7379cdacb638e0dc2e867408e04290d94df064e874f8d565f9fa7.json new file mode 100644 index 0000000..8a27a1a --- /dev/null +++ b/.sqlx/query-f66e03782ba7379cdacb638e0dc2e867408e04290d94df064e874f8d565f9fa7.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT COUNT(*) FROM emails WHERE mail = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "count", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + null + ] + }, + "hash": "f66e03782ba7379cdacb638e0dc2e867408e04290d94df064e874f8d565f9fa7" +} diff --git a/.sqlx/query-fbbb39ffb5ff4a6b7e26ec9133e297f55bdc832f35b04fb8da0c75cb52e02298.json b/.sqlx/query-fbbb39ffb5ff4a6b7e26ec9133e297f55bdc832f35b04fb8da0c75cb52e02298.json new file mode 100644 index 0000000..e48d3ae --- /dev/null +++ b/.sqlx/query-fbbb39ffb5ff4a6b7e26ec9133e297f55bdc832f35b04fb8da0c75cb52e02298.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "DELETE FROM emails WHERE mail = $1", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [] + }, + "hash": "fbbb39ffb5ff4a6b7e26ec9133e297f55bdc832f35b04fb8da0c75cb52e02298" +} diff --git a/Cargo.lock b/Cargo.lock index 49dbaef..b92c0fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1292,35 +1292,6 @@ version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" -[[package]] -name = "mail_accounts" -version = "0.1.0" -dependencies = [ - "argon2", - "axum", - "axum-extra", - "base64 0.21.2", - "color-eyre", - "cookie", - "envious", - "futures-util", - "itertools 0.11.0", - "jwt-simple", - "once_cell", - "openidconnect", - "parking_lot", - "secrecy", - "serde", - "serde_urlencoded", - "sqlx", - "tera", - "thiserror", - "tokio", - "tracing", - "tracing-subscriber", - "uuid", -] - [[package]] name = "matchers" version = "0.1.0" @@ -2599,6 +2570,35 @@ dependencies = [ "uuid", ] +[[package]] +name = "stalwart-accounts" +version = "0.1.0" +dependencies = [ + "argon2", + "axum", + "axum-extra", + "base64 0.21.2", + "color-eyre", + "cookie", + "envious", + "futures-util", + "itertools 0.11.0", + "jwt-simple", + "once_cell", + "openidconnect", + "parking_lot", + "secrecy", + "serde", + "serde_urlencoded", + "sqlx", + "tera", + "thiserror", + "tokio", + "tracing", + "tracing-subscriber", + "uuid", +] + [[package]] name = "stringprep" version = "0.1.3" diff --git a/Cargo.toml b/Cargo.toml index e0ad22d..a58a4b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mail_accounts" +name = "stalwart-accounts" version = "0.1.0" authors = ["traxys "] edition = "2021" diff --git a/flake.nix b/flake.nix index 264ed94..0f8d2d4 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,14 @@ RUST_DOC_PATH = "${rust}/share/doc/rust/html/std/index.html"; }; - defaultPackage = naersk'.buildPackage ./.; - }); + packages.default = naersk'.buildPackage { + src = ./.; + + postInstall = '' + mkdir -p $out/share + cp -r templates $out/share + ''; + }; + }) + // {nixosModules.stalwart-accounts = import ./nixos self;}; } diff --git a/nixos/default.nix b/nixos/default.nix new file mode 100644 index 0000000..ee860bd --- /dev/null +++ b/nixos/default.nix @@ -0,0 +1,153 @@ +self: { + lib, + pkgs, + config, + options, + ... +}: +with lib; { + options.services.stalwart-accounts = { + enable = mkEnableOption "stalwart-accounts, an account manager for stalwart mail server"; + + package = mkOption { + type = types.package; + inherit (self.packages.${config.nixpkgs.system}) default; + }; + + logLevel = mkOption { + type = types.str; + default = "info"; + }; + + settings = { + jwtSecret = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + The JWT secret to be used by the application. Should be passed through environmentFile, + with MAIL_ADMIN_JWT_SECRET. + ''; + }; + + oidcEndpoint = mkOption { + type = types.str; + }; + + oidcClientId = mkOption { + type = types.str; + }; + + oidcClientSecret = mkOption { + type = types.nullOr types.str; + default = null; + description = "The environment variable MAIL_ADMIN_CLIENT_SECRET should be preferred"; + }; + + domain = mkOption { + type = types.str; + }; + + scopes = mkOption { + type = types.str; + default = "openid,profile"; + }; + + mailDomain = mkOption { + type = types.str; + }; + + databaseUrl = mkOption { + type = types.str; + default = "postgres://${config.services.stalwart-accounts.user}/stalwart-accounts?host=/var/run/postgresql"; + }; + + port = mkOption { + type = types.port; + default = 8080; + }; + }; + + user = mkOption { + type = types.str; + default = "stalwart-accounts"; + }; + + environmentFile = mkOption { + type = types.nullOr types.path; + default = null; + }; + }; + + config = let + cfg = config.services.stalwart-accounts; + in + mkIf cfg.enable { + systemd.services.stalwart-accounts = { + description = "stalwart-accounts"; + after = ["network.target" "postgresql.service"]; + wantedBy = ["multi-user.target"]; + + serviceConfig = { + Type = "simple"; + User = cfg.user; + ExecStart = "${cfg.package}/bin/stalwart-accounts"; + EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; + WorkingDirectory = "${cfg.package}/share"; + # Security + NoNewPrivileges = true; + # Sandboxing + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + PrivateDevices = true; + PrivateUsers = true; + ProtectHostname = true; + ProtectClock = true; + ProtectKernelTunables = true; + ProtectKernelModules = true; + ProtectKernelLogs = true; + ProtectControlGroups = true; + RestrictAddressFamilies = ["AF_UNIX AF_INET AF_INET6"]; + LockPersonality = true; + MemoryDenyWriteExecute = true; + RestrictRealtime = true; + RestrictSUIDSGID = true; + PrivateMounts = true; + }; + + environment = { + RUST_LOG = cfg.logLevel; + MAIL_ADMIN_DATABASE_URL = cfg.settings.databaseUrl; + MAIL_ADMIN_DOMAIN = cfg.settings.domain; + MAIL_ADMIN_OIDC_ENDPOINT = cfg.settings.oidcEndpoint; + MAIL_ADMIN_CLIENT_ID = cfg.settings.oidcClientId; + MAIL_ADMIN_SCOPES = cfg.settings.scopes; + MAIL_ADMIN_MAIL_DOMAIN = cfg.settings.mailDomain; + MAIL_ADMIN_JWT_SECRET = cfg.settings.jwtSecret; + MAIL_ADMIN_CLIENT_SECRET = cfg.settings.oidcClientSecret; + MAIL_ADMIN_PORT = toString cfg.settings.port; + }; + }; + + services.postgresql = + mkIf (cfg.settings.databaseUrl == options.services.stalwart-accounts.settings.databaseUrl.default) + { + ensureUsers = [ + { + name = cfg.user; + ensureDBOwnership = true; + } + ]; + ensureDatabases = ["stalwart-accounts"]; + }; + + users = mkIf (cfg.user == "stalwart-accounts") { + users.stalwart-accounts = { + description = "stalwart-accounts user"; + group = "stalwart-accounts"; + isSystemUser = true; + }; + groups.stalwart-accounts = {}; + }; + }; +} diff --git a/queries.md b/queries.md index 1729376..06bb096 100644 --- a/queries.md +++ b/queries.md @@ -5,9 +5,18 @@ 100 GB quota ```sql -SELECT name, 'individual' as type, password as secret, '' as description, 107374182400 as quota -FROM accounts -WHERE secret != NULL AND name = ? +SELECT + mail as name, + 'individual' as type, + password as secret, + '' as description, + 107374182400 as quota +FROM emails + JOIN accounts ON emails.id = accounts.id +WHERE + type = 'primary' + AND mail = $1 + AND password IS NOT NULL ``` ## members @@ -19,47 +28,51 @@ SELECT NULL as member_of WHERE 1=0 ## recipients ```sql -SELECT name -FROM emails JOIN accounts on emails.id = accounts.id -WHERE mail = ? + SELECT dest as name FROM alias WHERE alias = $1 +UNION + SELECT mail as name + FROM emails + WHERE id = (SELECT id FROM emails WHERE type = 'list' AND mail = $1) + AND type = 'primary' +UNION + SELECT mail as name FROM emails WHERE mail = $1 ``` ## emails ```sql -SELECT mail as address -FROM ( - SELECT name || '@familleboyer.net' as mail, 0 as type FROM accounts WHERE name = ? - UNION - SELECT mail, (alias)::int + 1 as type - FROM emails JOIN accounts ON accounts.id = emails.id - WHERE name = ? -) as mails -ORDER BY type +SELECT mais as address +FROM emails +WHERE + (id = (SELECT id FROM emails WHERE mail = $1) AND type = 'alias') + OR mail = $1 +ORDER BY type, mail ``` ## verify ```sql -SELECT mail as address -FROM ( - SELECT name || '@familleboyer.net' as mail FROM accounts - UNION - SELECT mail - FROM emails JOIN accounts ON accounts.id = emails.id - WHERE NOT alias -) as mails -WHERE mail LIKE '%' || ? || '%' ORDER BY mail LIMIT 5 +SELECT mail as address +FROM emails +WHERE + mail LIKE '%' || $1 || '%' + AND type = 'primary' +ORDER BY address +LIMIT 5 ``` ## expand ```sql -SELECT NULL as address WHERE 1=0 +SELECT recipient as address +FROM list_recipients +WHERE list = $1 +ORDER BY address +LIMIT 50 ``` ## domains ```sql -SELECT 1 WHERE ? = 'familleboyer.net' +SELECT 1 FROM emails WHERE mail LIKE '%@' || $1 LIMIT 1 ``` diff --git a/src/main.rs b/src/main.rs index 6865dfd..0a79d16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -991,7 +991,7 @@ async fn set_password( Ok(Redirect::to("/")) } -#[tokio::main] +#[tokio::main(flavor = "current_thread")] async fn main() -> color_eyre::Result<()> { color_eyre::install()?; diff --git a/templates/home.html b/templates/home.html index edd2456..31ac4da 100644 --- a/templates/home.html +++ b/templates/home.html @@ -180,7 +180,7 @@ {{ self::delete_modal(modal_id="listDelete" ~ loop.index, confirm_text="Delete list '" ~ list.mail ~ "'", action="/list/delete", - payload=["name", list.mail]) + payload=["mail", list.mail]) }}

Recipients