From be8a56fb21f0ce58e7d0b33fdf56c12df149def2 Mon Sep 17 00:00:00 2001 From: traxys Date: Mon, 9 Oct 2023 13:41:26 +0200 Subject: [PATCH 01/10] Fix issue with deleting list recipients --- templates/home.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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

From e1d539e893a539971f768129386e11028d8e853c Mon Sep 17 00:00:00 2001 From: traxys Date: Mon, 9 Oct 2023 16:36:35 +0200 Subject: [PATCH 02/10] Rework stalwart queries --- queries.md | 65 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 26 deletions(-) diff --git a/queries.md b/queries.md index 1729376..d8ac383 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 = ? + 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 = ? +UNION + SELECT mail as name + FROM emails + WHERE id = (SELECT id FROM emails WHERE type = 'list' AND mail = ?) + AND type = 'primary' +UNION + SELECT mail as name FROM emails WHERE mail = ? ``` ## 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 = ?) AND type = 'alias') + OR mail = ? +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 '%' || ? || '%' + 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 = ? +ORDER BY address +LIMIT 50 ``` ## domains ```sql -SELECT 1 WHERE ? = 'familleboyer.net' +SELECT 1 FROM emails WHERE mail LIKE '%@' || ? LIMIT 1 ``` From b1df749b24d5a451815cf8b89b38fa836afc8655 Mon Sep 17 00:00:00 2001 From: traxys Date: Tue, 10 Oct 2023 20:35:10 +0200 Subject: [PATCH 03/10] Add a nixos module --- flake.nix | 5 +- nixos/default.nix | 146 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 nixos/default.nix diff --git a/flake.nix b/flake.nix index 264ed94..3e36f55 100644 --- a/flake.nix +++ b/flake.nix @@ -29,6 +29,7 @@ RUST_DOC_PATH = "${rust}/share/doc/rust/html/std/index.html"; }; - defaultPackage = naersk'.buildPackage ./.; - }); + packages.default = naersk'.buildPackage ./.; + }) + // {nixosModules.stalwart-accounts = import ./nixos self;}; } diff --git a/nixos/default.nix b/nixos/default.nix new file mode 100644 index 0000000..f65229f --- /dev/null +++ b/nixos/default.nix @@ -0,0 +1,146 @@ +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"; + }; + }; + + 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/mail_accounts"; + EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; + # 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; + }; + }; + + services.postgresql = + mkIf (cfg.settings.databaseUrl == options.services.stalwart-accounts.settings.databaseUrl.default) + { + ensureUsers = [ + { + name = cfg.user; + ensurePermissions = {"DATABASE \"stalwart-accounts\"" = "ALL PRIVILEGES";}; + } + ]; + ensureDatabases = ["stalwart-accounts"]; + }; + + users = mkIf (cfg.user == "stalwart-accounts") { + users.stalwart-accounts = { + description = "stalwart-accounts user"; + group = "stalwart-accounts"; + isSystemUser = true; + }; + groups.stalwart-accounts = {}; + }; + }; +} From 54feff4cc61bc6bc9937b2fdbbdb66350921bfcb Mon Sep 17 00:00:00 2001 From: traxys Date: Tue, 10 Oct 2023 20:42:12 +0200 Subject: [PATCH 04/10] Add sqlx queries for offline build --- ...161096ac6b83d1239ce910906a0d2d3d99d02.json | 15 ++++++++++ ...25e07f00fada97ec87581bc80a68f3dd11ee2.json | 28 +++++++++++++++++++ ...b3850c915b7da3468ee658d842161098939ae.json | 23 +++++++++++++++ ...c933e6cc0d5436ad9ce5a8bfbba71a2c2903b.json | 15 ++++++++++ ...00e7ff430ad3e46452940a61bd7d7dc06b204.json | 14 ++++++++++ ...796bd51dc72b1437a341ebe50549ac527c0be.json | 28 +++++++++++++++++++ ...630ffe65b7a8196d09ec1491374def326a258.json | 22 +++++++++++++++ ...5e43200402bc30f6d982ba7c583a0c976d7f6.json | 15 ++++++++++ ...e6f783d54ce228d9830fb4d46b13c6efffcb8.json | 15 ++++++++++ ...c0e1f8202208e32fca3b7c5da979b94aba02a.json | 14 ++++++++++ ...cfc8660b3a1bc735e69d5e92d85d00b81bcd2.json | 15 ++++++++++ ...4c1fb7db93b3452c77065572a1c303e36cfdc.json | 22 +++++++++++++++ ...6d78201238e168fdea110af801682f03c8159.json | 15 ++++++++++ ...fdb1ce846aad8cb343c734169d9ecf6484ba2.json | 15 ++++++++++ ...5e8d5a72158d502ac9b75da84cb9451d934e2.json | 15 ++++++++++ ...f812bd7cda553263260860812f646da20b7a1.json | 22 +++++++++++++++ ...a88be3bafeb004a9ffc4d21362c3897bd22d0.json | 14 ++++++++++ ...bbb9545e0d4f3847afcfb787a38dee1b38ec0.json | 23 +++++++++++++++ ...4bb442783e5e2135b53cada6d256e976c4857.json | 15 ++++++++++ ...2e867408e04290d94df064e874f8d565f9fa7.json | 22 +++++++++++++++ ...297f55bdc832f35b04fb8da0c75cb52e02298.json | 14 ++++++++++ 21 files changed, 381 insertions(+) create mode 100644 .sqlx/query-23e11c1e470c49de109c7c88f4e161096ac6b83d1239ce910906a0d2d3d99d02.json create mode 100644 .sqlx/query-31a4c053d4c984e9d0d5820487525e07f00fada97ec87581bc80a68f3dd11ee2.json create mode 100644 .sqlx/query-31a67e09c41b8b9cc3b3065590ab3850c915b7da3468ee658d842161098939ae.json create mode 100644 .sqlx/query-3403255f07a53813f0a8163828bc933e6cc0d5436ad9ce5a8bfbba71a2c2903b.json create mode 100644 .sqlx/query-449dea2a3a52b67cf88878708ed00e7ff430ad3e46452940a61bd7d7dc06b204.json create mode 100644 .sqlx/query-46015003c53421ce280ca79e445796bd51dc72b1437a341ebe50549ac527c0be.json create mode 100644 .sqlx/query-542eacaa20dcac0437aafce6545630ffe65b7a8196d09ec1491374def326a258.json create mode 100644 .sqlx/query-567f765aebef4fbebd557387ab45e43200402bc30f6d982ba7c583a0c976d7f6.json create mode 100644 .sqlx/query-681be1e58f24e62eb2643204044e6f783d54ce228d9830fb4d46b13c6efffcb8.json create mode 100644 .sqlx/query-7869c07f3affdabc150961ed9b9c0e1f8202208e32fca3b7c5da979b94aba02a.json create mode 100644 .sqlx/query-8518449399c2ade2867d714efe1cfc8660b3a1bc735e69d5e92d85d00b81bcd2.json create mode 100644 .sqlx/query-9e23f135b4ec69fa4d99f797fd54c1fb7db93b3452c77065572a1c303e36cfdc.json create mode 100644 .sqlx/query-a17528ac7ef8aec3fe2de5925256d78201238e168fdea110af801682f03c8159.json create mode 100644 .sqlx/query-b1a3280e13824a918d2264dd7b5fdb1ce846aad8cb343c734169d9ecf6484ba2.json create mode 100644 .sqlx/query-bbc7f016c7bd8e4ddfc3b393ce55e8d5a72158d502ac9b75da84cb9451d934e2.json create mode 100644 .sqlx/query-bd78c0a43f02328f6381ed68f79f812bd7cda553263260860812f646da20b7a1.json create mode 100644 .sqlx/query-c4d597b5651efad2cc83bf83088a88be3bafeb004a9ffc4d21362c3897bd22d0.json create mode 100644 .sqlx/query-ce862ed5cde153f4003bb2b28e3bbb9545e0d4f3847afcfb787a38dee1b38ec0.json create mode 100644 .sqlx/query-ebe5f8137e9f535eaf7d494b89d4bb442783e5e2135b53cada6d256e976c4857.json create mode 100644 .sqlx/query-f66e03782ba7379cdacb638e0dc2e867408e04290d94df064e874f8d565f9fa7.json create mode 100644 .sqlx/query-fbbb39ffb5ff4a6b7e26ec9133e297f55bdc832f35b04fb8da0c75cb52e02298.json 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" +} From b28e6363c45ec3d00120d9dd2d920f77fd82d4b7 Mon Sep 17 00:00:00 2001 From: traxys Date: Tue, 10 Oct 2023 21:19:02 +0200 Subject: [PATCH 05/10] Rename to stalwart-accounts --- Cargo.lock | 58 +++++++++++++++++++++++------------------------ Cargo.toml | 2 +- nixos/default.nix | 2 +- 3 files changed, 31 insertions(+), 31 deletions(-) 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/nixos/default.nix b/nixos/default.nix index f65229f..3086697 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -85,7 +85,7 @@ with lib; { serviceConfig = { Type = "simple"; User = cfg.user; - ExecStart = "${cfg.package}/bin/mail_accounts"; + ExecStart = "${cfg.package}/bin/stalwart-accounts"; EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; # Security NoNewPrivileges = true; From 46a646b67ba6d014bb28976188eed06d264831fe Mon Sep 17 00:00:00 2001 From: traxys Date: Wed, 11 Oct 2023 12:36:22 +0200 Subject: [PATCH 06/10] Expose port settings in nixos module --- nixos/default.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nixos/default.nix b/nixos/default.nix index 3086697..7b29f44 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -60,6 +60,11 @@ with lib; { 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 { @@ -119,6 +124,7 @@ with lib; { 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; }; }; From 6a34258a3078f55ec9493e26f217427341f1305b Mon Sep 17 00:00:00 2001 From: traxys Date: Fri, 13 Oct 2023 20:24:42 +0200 Subject: [PATCH 07/10] Use single threaded runtime --- src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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()?; From 6277631144a818ece314e2739e144f83179cedbf Mon Sep 17 00:00:00 2001 From: traxys Date: Fri, 13 Oct 2023 20:43:53 +0200 Subject: [PATCH 08/10] Correctly package templates --- flake.nix | 9 ++++++++- nixos/default.nix | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index 3e36f55..0f8d2d4 100644 --- a/flake.nix +++ b/flake.nix @@ -29,7 +29,14 @@ RUST_DOC_PATH = "${rust}/share/doc/rust/html/std/index.html"; }; - packages.default = 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 index 7b29f44..7c35bc0 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -92,6 +92,7 @@ with lib; { User = cfg.user; ExecStart = "${cfg.package}/bin/stalwart-accounts"; EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile; + WorkingDirectory = "${cfg.package}/share"; # Security NoNewPrivileges = true; # Sandboxing From 2225d626b9d99c94ec448897faec7aee6b63d360 Mon Sep 17 00:00:00 2001 From: traxys Date: Tue, 5 Dec 2023 23:16:43 +0100 Subject: [PATCH 09/10] Requests as postgresql --- queries.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/queries.md b/queries.md index d8ac383..06bb096 100644 --- a/queries.md +++ b/queries.md @@ -15,7 +15,7 @@ FROM emails JOIN accounts ON emails.id = accounts.id WHERE type = 'primary' - AND mail = ? + AND mail = $1 AND password IS NOT NULL ``` @@ -28,14 +28,14 @@ SELECT NULL as member_of WHERE 1=0 ## recipients ```sql - SELECT dest as name FROM alias WHERE alias = ? + 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 = ?) + WHERE id = (SELECT id FROM emails WHERE type = 'list' AND mail = $1) AND type = 'primary' UNION - SELECT mail as name FROM emails WHERE mail = ? + SELECT mail as name FROM emails WHERE mail = $1 ``` ## emails @@ -44,8 +44,8 @@ UNION SELECT mais as address FROM emails WHERE - (id = (SELECT id FROM emails WHERE mail = ?) AND type = 'alias') - OR mail = ? + (id = (SELECT id FROM emails WHERE mail = $1) AND type = 'alias') + OR mail = $1 ORDER BY type, mail ``` @@ -55,7 +55,7 @@ ORDER BY type, mail SELECT mail as address FROM emails WHERE - mail LIKE '%' || ? || '%' + mail LIKE '%' || $1 || '%' AND type = 'primary' ORDER BY address LIMIT 5 @@ -66,7 +66,7 @@ LIMIT 5 ```sql SELECT recipient as address FROM list_recipients -WHERE list = ? +WHERE list = $1 ORDER BY address LIMIT 50 ``` @@ -74,5 +74,5 @@ LIMIT 50 ## domains ```sql -SELECT 1 FROM emails WHERE mail LIKE '%@' || ? LIMIT 1 +SELECT 1 FROM emails WHERE mail LIKE '%@' || $1 LIMIT 1 ``` From e4013ec9742837dbf7b102fa8885df48f611a85a Mon Sep 17 00:00:00 2001 From: traxys Date: Tue, 5 Dec 2023 23:17:14 +0100 Subject: [PATCH 10/10] EnsureDBOwnership --- nixos/default.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/default.nix b/nixos/default.nix index 7c35bc0..ee860bd 100644 --- a/nixos/default.nix +++ b/nixos/default.nix @@ -135,7 +135,7 @@ with lib; { ensureUsers = [ { name = cfg.user; - ensurePermissions = {"DATABASE \"stalwart-accounts\"" = "ALL PRIVILEGES";}; + ensureDBOwnership = true; } ]; ensureDatabases = ["stalwart-accounts"];