summaryrefslogtreecommitdiffstats
path: root/nixos/tests/web-apps/pdfding/basic.nix
blob: 10db93c5203b13018a7e05d3af6924a9a76a3659 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
{
  lib,
  pkgs,
  ...
}:
{
  name = "PdfDing sqlite";

  nodes = {
    machine =
      { ... }:
      {
        # WARNING: Do not add secrets to the world-readable /nix/store in a production deployment
        # Use a secret management scheme instead https://wiki.nixos.org/wiki/Comparison_of_secret_managing_schemes
        services.pdfding = {
          enable = true;
          secretKeyFile = pkgs.writeText "secretKeyFile" "test123";
        };

        # NOTE: on aarch64-linux github actions runer due to lack of kvm, we need to delay pdfding start and give it more time to finish
        systemd.services.pdfding.wantedBy = lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 (lib.mkForce [ ]);
        systemd.services.pdfding.serviceConfig.TimeoutStartSec =
          lib.mkIf pkgs.stdenv.hostPlatform.isAarch64 "900";

        environment.systemPackages = with pkgs; [
          sqlite
        ];

        # test email validation works
        services.pdfding.extraEnvironment = {
          EMAIL_BACKEND = "SMTP";
          SMTP_HOST = "localhost";
          SMTP_PORT = "1025";
          SMTP_USER = ""; # mailpit doesn't need auth
          SMTP_PASSWORD = "";
          SMTP_USE_TLS = "FALSE";
          SMTP_USE_SSL = "FALSE";
        };

        # enable mailpit
        services.mailpit.instances.default = { };

        # allows running nixos test on qemu without kvm, eg. github actions on aarch64-linux
        systemd.settings.Manager.DefaultDeviceTimeoutSec = lib.mkForce 1800;
        boot.initrd.kernelModules = [ "virtio_console" ];
      };
  };

  # Test the most basic user functionality expected from pdfding.
  # Heavy e2e test suite is implemented in e2e.nix
  testScript =
    { nodes, ... }:
    let
      inherit (nodes.machine.services.pdfding) port;
      mailpitApiEndpoint = "http://${nodes.machine.services.mailpit.instances.default.listen}/api/v1";
      stateDir = "/var/lib/pdfding";
    in
    # py
    ''
      import json
      from pprint import pprint

      # start vms
      start_all()

      # create admin
      machine.wait_for_unit("multi-user.target")
      machine.succeed("systemctl start pdfding.service")
      machine.wait_for_open_port(${toString port})
      machine.succeed("DJANGO_SUPERUSER_PASSWORD=admin pdfding-manage createsuperuser --no-input --username admin --email admin@localhost")

      cookie_jar = "/tmp/cookies.txt"
      endpoint = "http://localhost:${toString port}"

      with subtest("login and basic usage"):
        # login
        machine.succeed(f"""
          curl -f \
            -X POST -c {cookie_jar} -b {cookie_jar} \
            -d "csrfmiddlewaretoken=$(curl -f -c {cookie_jar} -s '{endpoint}/accountlogin/' | grep -oP 'name="csrfmiddlewaretoken" value="\\K[^"]+')" \
            -d "login=admin@localhost" \
            -d "password=admin" \
            {endpoint}/accountlogin/
        """)

        test_pdf = "${pkgs.pdfding.src}/pdfding/pdf/tests/data/dummy.pdf"

        # verify no pdfs exist in db
        machine.succeed("sqlite3 ${stateDir}/db/db.sqlite3 'SELECT COUNT(*) FROM pdf_pdf' | grep -q '^0$'")

        # upload
        machine.succeed(f"""
          csrf_token=$(curl -f -b {cookie_jar} -c {cookie_jar} -s "{endpoint}/pdf/add" | grep -oP 'name="csrfmiddlewaretoken" value="\\K[^"]+')
          curl -f \
            -c {cookie_jar} -b {cookie_jar} \
            -F "notes=" \
            -F "tag_string=" \
            -F "description=" \
            -F "collection=1" \
            -F "use_file_name=on" \
            -F "name=test-upload" \
            -F "file=@{test_pdf};type=application/pdf" \
            -F "csrfmiddlewaretoken=$csrf_token" \
            -H "Referer: {endpoint}/pdf/add" \
            {endpoint}/pdf/add
        """)

        # download
        machine.succeed(f"""
          pdf_id=$(curl -f -b {cookie_jar} -s "{endpoint}/pdf/" | grep -oP 'href="/pdf/view/\\K[^"]+' | head -1)
          curl -f -b {cookie_jar} -o /tmp/downloaded.pdf "{endpoint}/pdf/download/$pdf_id"
        """)

        # verify pdf in user's dir
        machine.succeed("test -f ${stateDir}/media/1/default/pdf/*.pdf")

        # verify one entry exists in sqlite db
        machine.succeed("sqlite3 ${stateDir}/db/db.sqlite3 'SELECT COUNT(*) FROM pdf_pdf' | grep -q '^1$'")

      with subtest("email validation"):
        # check we can reach mailpit
        machine.succeed("curl -f ${mailpitApiEndpoint}/info")

        # check that no emails exist
        result = json.loads(machine.succeed("curl -sf ${mailpitApiEndpoint}/messages"))
        pprint(result)
        assert result["total"] == 0

        # signup
        machine.succeed(f"""
          curl -f \
            -X POST -c {cookie_jar} -b {cookie_jar} \
            -d "csrfmiddlewaretoken=$(curl -f -c {cookie_jar} -s '{endpoint}/accountsignup/' | grep -oP 'name="csrfmiddlewaretoken" value="\\K[^"]+')" \
            -d "email=pdfding_new_user@example.com" \
            -d "password1=foobarbaz" \
            -d "password2=foobarbaz" \
            {endpoint}/accountsignup/
        """)

        # wait a bit for email to be processed
        machine.sleep(3)

        # verify the email was received by mailpit
        result = json.loads(machine.succeed("curl -s ${mailpitApiEndpoint}/messages"))
        pprint(result)
        assert result["total"] == 1
        assert result["messages"][0]["To"][0]["Address"] == "pdfding_new_user@example.com"
    '';

  # Debug interactively with:
  # - nix run .#nixosTests.pdfding.basic.driverInteractive -L
  # - start_all() / run_tests()
  interactive.sshBackdoor.enable = true;
  interactive.nodes.machine =
    { config, ... }:
    let
      port = config.services.pdfding.port;
    in
    {
      # not needed, only for manual interactive debugging
      virtualisation.memorySize = 4096;
      environment.systemPackages = with pkgs; [
        htop
      ];

      virtualisation.forwardPorts = map (port: {
        from = "host";
        host.port = port;
        guest.port = port;
      }) [ port ];

      # forwarded ports need to be accessible
      networking.firewall.allowedTCPPorts = [ port ];
    };

  meta.maintainers = lib.teams.ngi.members;
}