blob: fcab52fa61769d49eebd912a039acb642217f502 [file] [log] [blame]
Ed Tanousba9f9a62017-10-11 16:40:35 -07001#pragma once
2
Ed Tanousba9f9a62017-10-11 16:40:35 -07003#include <nlohmann/json.hpp>
4#include <pam_authenticate.hpp>
5#include <webassets.hpp>
Borawski.Lukasz16238972018-01-17 15:36:53 +01006#include <random>
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +01007#include "session_storage_singleton.hpp"
Ed Tanousba9f9a62017-10-11 16:40:35 -07008#include <crow/app.h>
9#include <crow/http_request.h>
10#include <crow/http_response.h>
11#include <boost/container/flat_map.hpp>
12#include <boost/uuid/uuid.hpp>
13#include <boost/uuid/uuid_generators.hpp>
14#include <boost/uuid/uuid_io.hpp>
15
16namespace crow {
17
18namespace PersistentData {
Borawski.Lukasz9d8fd302018-01-05 14:56:09 +010019
Ed Tanousc963aa42017-10-27 16:00:19 -070020class Middleware {
21 // todo(ed) should read this from a fixed location somewhere, not CWD
22 static constexpr const char* filename = "bmcweb_persistent_data.json";
23 int json_revision = 1;
24
25 public:
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010026 struct context {};
Ed Tanousc963aa42017-10-27 16:00:19 -070027
28 Middleware() { read_data(); }
29
30 ~Middleware() {
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010031 if (PersistentData::session_store->needs_write()) {
Ed Tanousc963aa42017-10-27 16:00:19 -070032 write_data();
33 }
34 }
35
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +010036 void before_handle(crow::request& req, response& res, context& ctx) {}
Ed Tanousc963aa42017-10-27 16:00:19 -070037
38 void after_handle(request& req, response& res, context& ctx) {}
39
40 // TODO(ed) this should really use protobuf, or some other serialization
41 // library, but adding another dependency is somewhat outside the scope of
42 // this application for the moment
43 void read_data() {
44 std::ifstream persistent_file(filename);
45 int file_revision = 0;
46 if (persistent_file.is_open()) {
47 // call with exceptions disabled
48 auto data = nlohmann::json::parse(persistent_file, nullptr, false);
49 if (!data.is_discarded()) {
Kowalski, Kamil5cef0f72018-02-15 15:26:51 +010050 auto jRevision = data.find("revision");
51 auto jUuid = data.find("system_uuid");
52 auto jSessions = data.find("sessions");
53
54 file_revision = 0;
55 if (jRevision != data.end()) {
56 if (jRevision->is_number_integer()) {
57 file_revision = jRevision->get<int>();
58 }
59 }
60
61 system_uuid = "";
62 if (jUuid != data.end()) {
63 if (jUuid->is_string()) {
64 system_uuid = jUuid->get<std::string>();
65 }
66 }
67
68 if (jSessions != data.end()) {
69 if (jSessions->is_object()) {
70 for (const auto& elem : *jSessions) {
71 UserSession newSession;
72
73 if (newSession.fromJson(elem)) {
74 session_store->auth_tokens.emplace(newSession.unique_id,
75 std::move(newSession));
76 }
77 }
78 }
79 }
Ed Tanousc963aa42017-10-27 16:00:19 -070080 }
81 }
82 bool need_write = false;
83
84 if (system_uuid.empty()) {
85 system_uuid = boost::uuids::to_string(boost::uuids::random_generator()());
86 need_write = true;
87 }
88 if (file_revision < json_revision) {
89 need_write = true;
90 }
91 // write revision changes or system uuid changes immediately
92 if (need_write) {
93 write_data();
94 }
95 }
96
97 void write_data() {
98 std::ofstream persistent_file(filename);
99 nlohmann::json data;
Kowalski, Kamil2b7981f2018-01-31 13:24:59 +0100100 data["sessions"] = PersistentData::session_store->auth_tokens;
Ed Tanousc963aa42017-10-27 16:00:19 -0700101 data["system_uuid"] = system_uuid;
102 data["revision"] = json_revision;
103 persistent_file << data;
104 }
105
Ed Tanousc963aa42017-10-27 16:00:19 -0700106 std::string system_uuid;
Ed Tanousba9f9a62017-10-11 16:40:35 -0700107};
108
109} // namespaec PersistentData
110} // namespace crow