let
  certs = import ./common/acme/server/snakeoil-certs.nix;
  domain = certs.domain;
in
{ pkgs, ... }:
{
  name = "alps";
  meta = with pkgs.lib.maintainers; {
    maintainers = [ hmenke ];
  };

  nodes = {
    server = {
      imports = [ ./common/user-account.nix ];
      security.pki.certificateFiles = [
        certs.ca.cert
      ];
      networking.extraHosts = ''
        127.0.0.1 ${domain}
      '';
      networking.firewall.allowedTCPPorts = [
        25
        465
        993
      ];
      services.postfix = {
        enable = true;
        enableSubmission = true;
        enableSubmissions = true;

        settings.main = {
          smtp_tls_CAfile = "${certs.ca.cert}";
          smtpd_tls_chain_files = [
            "${certs.${domain}.key}"
            "${certs.${domain}.cert}"
          ];
        };
      };
      services.dovecot2 = {
        enable = true;
        enableImap = true;
        sslCACert = "${certs.ca.cert}";
        sslServerCert = "${certs.${domain}.cert}";
        sslServerKey = "${certs.${domain}.key}";
      };
    };

    client =
      { nodes, config, ... }:
      {
        security.pki.certificateFiles = [
          certs.ca.cert
        ];
        networking.extraHosts = ''
          ${nodes.server.config.networking.primaryIPAddress} ${domain}
        '';
        services.alps = {
          enable = true;
          theme = "alps";
          imaps = {
            host = domain;
            port = 993;
          };
          smtps = {
            host = domain;
            port = 465;
          };
        };
        environment.systemPackages = [
          (pkgs.writers.writePython3Bin "test-alps-login" { } ''
            from urllib.request import build_opener, HTTPCookieProcessor, Request
            from urllib.parse import urlencode, urljoin
            from http.cookiejar import CookieJar

            baseurl = "http://localhost:${toString config.services.alps.port}"
            username = "alice"
            password = "${nodes.server.config.users.users.alice.password}"
            cookiejar = CookieJar()
            cookieprocessor = HTTPCookieProcessor(cookiejar)
            opener = build_opener(cookieprocessor)

            data = urlencode({"username": username, "password": password}).encode()
            req = Request(urljoin(baseurl, "login"), data=data, method="POST")
            with opener.open(req) as ret:
                # Check that the alps_session cookie is set
                print(cookiejar)
                assert any(cookie.name == "alps_session" for cookie in cookiejar)

            req = Request(baseurl)
            with opener.open(req) as ret:
                # Check that the alps_session cookie is still there...
                print(cookiejar)
                assert any(cookie.name == "alps_session" for cookie in cookiejar)
                # ...and that we have not been redirected back to the login page
                print(ret.url)
                assert ret.url == urljoin(baseurl, "mailbox/INBOX")

            req = Request(urljoin(baseurl, "logout"))
            with opener.open(req) as ret:
                # Check that the alps_session cookie is now gone
                print(cookiejar)
                assert all(cookie.name != "alps_session" for cookie in cookiejar)
          '')
        ];
      };
  };

  testScript =
    { nodes, ... }:
    ''
      server.start()
      server.wait_for_unit("postfix.service")
      server.wait_for_unit("dovecot2.service")
      server.wait_for_open_port(465)
      server.wait_for_open_port(993)

      client.start()
      client.wait_for_unit("alps.service")
      client.wait_for_open_port(${toString nodes.client.config.services.alps.port})
      client.succeed("test-alps-login")
    '';
}
