Commit 19657b0c authored by Stephane Glondu's avatar Stephane Glondu

The administrator can download a zip archive of election data

parent 74634462
......@@ -20,6 +20,7 @@ The non-OCaml prerequisites are:
* [SQLite3](https://www.sqlite.org/)
* [OpenSSL](https://www.openssl.org/)
* [Wget](https://www.gnu.org/software/wget/) or [curl](http://curl.haxx.se/)
* [Zip](http://www.info-zip.org/Zip.html)
* [Unzip](http://www.info-zip.org/UnZip.html)
* [aspcud](http://www.cs.uni-potsdam.de/wv/aspcud/) (optional)
* [ncurses](http://invisible-island.net/ncurses/)
......@@ -29,7 +30,7 @@ These libraries and tools are pretty common, and might be directly part
of your operating system. On [Debian](http://www.debian.org/) and its
derivatives, they can be installed with the following command:
sudo apt install build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates unzip aspcud libncurses-dev uuid-runtime zlib1g-dev
sudo apt install build-essential libgmp-dev libpcre3-dev pkg-config m4 libssl-dev libsqlite3-dev wget ca-certificates zip unzip aspcud libncurses-dev uuid-runtime zlib1g-dev
If you are unfamiliar with OCaml or OPAM, we provide an
`opam-bootstrap.sh` shell script that creates a whole, hopefully
......
......@@ -97,6 +97,7 @@ let election_pretty_ballot = service ~path:["elections"] ~get_params:(suffix_pro
let election_pretty_records = service ~path:["elections"] ~get_params:(suffix (uuid "uuid" ** suffix_const "pretty-records")) ()
let election_missing_voters = service ~path:["elections"] ~get_params:(suffix (uuid "uuid" ** suffix_const "missing")) ()
let election_download_archive = service ~path:["elections"] ~get_params:(suffix (uuid "uuid" ** suffix_const "archive.zip")) ()
let election_compute_encrypted_tally = post_coservice ~csrf_safe:true ~fallback:election_admin ~post_params:unit ()
let election_tally_trustees = service ~path:["elections"] ~get_params:(suffix (uuid "uuid" ** suffix_const "trustees" ** string "token")) ()
......
......@@ -400,6 +400,7 @@ let delete_election uuid =
"records";
"result.json";
"voters.txt";
"archive.zip";
]
in
let%lwt () = Lwt_list.iter_p (fun x ->
......@@ -1575,6 +1576,87 @@ let () =
)
)
let copy_file src dst =
let open Lwt_io in
chars_of_file src |> chars_to_file dst
let try_copy_file src dst =
if%lwt file_exists src then copy_file src dst else return_unit
let make_archive uuid =
let uuid_s = raw_string_of_uuid uuid in
let%lwt temp_dir =
Lwt_preemptive.detach (fun () ->
let temp_dir = Filename.temp_file "belenios" "archive" in
Sys.remove temp_dir;
Unix.mkdir temp_dir 0o700;
Unix.mkdir (temp_dir / "public") 0o755;
Unix.mkdir (temp_dir / "restricted") 0o700;
temp_dir
) ()
in
let%lwt () =
Lwt_list.iter_p (fun x ->
try_copy_file (!spool_dir / uuid_s / x) (temp_dir / "public" / x)
) [
"election.json";
"public_keys.jsons";
"threshold.json";
"public_creds.txt";
"ballots.jsons";
"result.json";
]
in
let%lwt () =
Lwt_list.iter_p (fun x ->
try_copy_file (!spool_dir / uuid_s / x) (temp_dir / "restricted" / x)
) [
"voters.txt";
"records";
]
in
let command =
Printf.ksprintf Lwt_process.shell
"cd \"%s\" && zip -r archive public restricted" temp_dir
in
let%lwt r = Lwt_process.exec command in
match r with
| Unix.WEXITED 0 ->
let fname = !spool_dir / uuid_s / "archive.zip" in
let fname_new = fname ^ ".new" in
let%lwt () = copy_file (temp_dir / "archive.zip") fname_new in
let%lwt () = Lwt_unix.rename fname_new fname in
let command = "rm", [| "rm"; "-rf"; temp_dir |] in
let%lwt _ = Lwt_process.exec command in
return_unit
| _ ->
Printf.ksprintf Ocsigen_messages.errlog
"Error while creating archive.zip for election %s, temporary directory left in %s"
uuid_s temp_dir;
return_unit
let () =
Any.register ~service:election_download_archive
(fun (uuid, ()) () ->
with_site_user (fun u ->
let%lwt metadata = Web_persist.get_election_metadata uuid in
let%lwt state = Web_persist.get_election_state uuid in
if metadata.e_owner = Some u then (
if state = `Archived then (
let uuid_s = raw_string_of_uuid uuid in
let archive_name = !spool_dir / uuid_s / "archive.zip" in
let%lwt b = file_exists archive_name in
let%lwt () = if not b then make_archive uuid else return_unit in
File.send ~content_type:"application/zip" archive_name
) else (
let service = preapply election_admin (uuid, ()) in
T.generic_page ~title:"Error" ~service
"The election is not archived!" () >>= Html5.send
)
) else forbidden ()
)
)
let find_trustee_id uuid token =
try%lwt
let%lwt tokens = Ocsipersist.find election_tokens_decrypt (raw_string_of_uuid uuid) in
......
......@@ -1895,7 +1895,10 @@ let election_admin election metadata state get_tokens_decrypt () =
]
| `Archived ->
return @@ div [
pcdata "This election is archived.";
pcdata "This election is archived. ";
a ~service:election_download_archive [
pcdata "Download archive.";
] (uuid, ());
]
in
let%lwt archive_date = match state with
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment