NAWA 0.8
Web Application Framework for C++
sessions.cpp
Go to the documentation of this file.
1
6/*
7 * Copyright (C) 2019-2021 Tobias Flaig.
8 *
9 * This file is part of nawa.
10 *
11 * nawa is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License,
13 * version 3, as published by the Free Software Foundation.
14 *
15 * nawa is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public License
21 * along with nawa. If not, see <https://www.gnu.org/licenses/>.
22 */
23
24#include <catch2/catch.hpp>
25#include <nawa/Exception.h>
27#include <nawa/connection/ConnectionInitContainer.h>
29
30using namespace nawa;
31using namespace std;
32
33TEST_CASE("nawa::Session class", "[unit][session]") {
34 ConnectionInitContainer connectionInit;
35 connectionInit.requestInit.environment["REMOTE_ADDR"] = "1.2.3.4";
36
37 SECTION("Basic session handling") {
38 string sessionId;
39 {
40 Connection connection(connectionInit);
41 auto& session = connection.session();
42 session.start();
43 CHECK_NOTHROW(session.set("testKey", "testVal"));
44 CHECK(any_cast<string>(session["testKey"]) == "testVal");
45 sessionId = session.getID();
46 }
47 {
48 ConnectionInitContainer connectionInit1 = connectionInit;
49 connectionInit1.requestInit.cookieVars.insert({"SESSION", sessionId});
50 Connection connection(connectionInit1);
51 auto& session = connection.session();
52 session.start();
53 REQUIRE(session.getID() == sessionId);
54 CHECK(any_cast<string>(session["testKey"]) == "testVal");
55 }
56 }
57
58 SECTION("Session autostart") {
59 ConnectionInitContainer connectionInit1 = connectionInit;
60 connectionInit1.config.set({"session", "autostart"}, "on");
61 string sessionId;
62 {
63 Connection connection(connectionInit1);
64 auto& session = connection.session();
65 CHECK_NOTHROW(session.set("testKey", "testVal"));
66 CHECK(any_cast<string>(session["testKey"]) == "testVal");
67 sessionId = session.getID();
68 }
69 {
70 connectionInit1.requestInit.cookieVars.insert({"SESSION", sessionId});
71 Connection connection(connectionInit1);
72 auto& session = connection.session();
73 REQUIRE(session.getID() == sessionId);
74 CHECK(any_cast<string>(session["testKey"]) == "testVal");
75 }
76 }
77
78 SECTION("Attempt to access and modify inactive session") {
79 Connection connection(connectionInit);
80 auto& session = connection.session();
81 CHECK_THROWS_AS(session.set("testKey", "testVal"), Exception);
82 CHECK_THROWS_AS(session.unset("testKey"), Exception);
83 CHECK_NOTHROW(session["testKey"]);
84 }
85
86 SECTION("Invalidation of sessions") {
87 Connection connection(connectionInit);
88 auto& session = connection.session();
89 session.start();
90 CHECK_NOTHROW(session.set("testKey", "testVal"));
91 session.invalidate();
92 CHECK_THROWS_AS(session.set("testKey", "testVal"), Exception);
93 }
94
95 SECTION("Client IP check: same IP") {
96 ConnectionInitContainer connectionInit1 = connectionInit;
97 string clientIPCheckMode = GENERATE("lax", "strict");
98 connectionInit1.config.set({"session", "validate_ip"}, clientIPCheckMode);
99 string sessionId;
100 {
101 Connection connection(connectionInit1);
102 auto& session = connection.session();
103 session.start();
104 CHECK_NOTHROW(session.set("testKey", "testVal"));
105 CHECK(any_cast<string>(session["testKey"]) == "testVal");
106 sessionId = session.getID();
107 }
108 {
109 connectionInit1.requestInit.cookieVars.insert({"SESSION", sessionId});
110 Connection connection(connectionInit1);
111 auto& session = connection.session();
112 session.start();
113 REQUIRE(session.getID() == sessionId);
114 CHECK(any_cast<string>(session["testKey"]) == "testVal");
115 }
116 }
117
118 SECTION("Client IP check: different IP (lax)") {
119 ConnectionInitContainer connectionInit1 = connectionInit;
120 connectionInit1.config.set({"session", "validate_ip"}, "lax");
121 string sessionId;
122 {
123 Connection connection(connectionInit1);
124 auto& session = connection.session();
125 session.start();
126 CHECK_NOTHROW(session.set("testKey", "testVal"));
127 CHECK(any_cast<string>(session["testKey"]) == "testVal");
128 sessionId = session.getID();
129 }
130 {
131 ConnectionInitContainer connectionInit2 = connectionInit1;
132 connectionInit2.requestInit.cookieVars.insert({"SESSION", sessionId});
133 connectionInit2.requestInit.environment["REMOTE_ADDR"] = "1.2.3.5";
134 Connection connection(connectionInit2);
135 auto& session = connection.session();
136 session.start();
137 CHECK_FALSE(session.getID() == sessionId);
138 CHECK_FALSE(session.isSet("testKey"));
139 }
140 {
141 connectionInit1.requestInit.cookieVars.insert({"SESSION", sessionId});
142 Connection connection(connectionInit1);
143 auto& session = connection.session();
144 session.start();
145 REQUIRE(session.getID() == sessionId);
146 CHECK(any_cast<string>(session["testKey"]) == "testVal");
147 }
148 }
149
150 SECTION("Client IP check: different IP (strict)") {
151 ConnectionInitContainer connectionInit1 = connectionInit;
152 connectionInit1.config.set({"session", "validate_ip"}, "strict");
153 string sessionId;
154 {
155 Connection connection(connectionInit1);
156 auto& session = connection.session();
157 session.start();
158 CHECK_NOTHROW(session.set("testKey", "testVal"));
159 CHECK(any_cast<string>(session["testKey"]) == "testVal");
160 sessionId = session.getID();
161 }
162 {
163 ConnectionInitContainer connectionInit2 = connectionInit1;
164 connectionInit2.requestInit.cookieVars.insert({"SESSION", sessionId});
165 connectionInit2.requestInit.environment["REMOTE_ADDR"] = "1.2.3.5";
166 Connection connection(connectionInit2);
167 auto& session = connection.session();
168 session.start();
169 CHECK_FALSE(session.getID() == sessionId);
170 CHECK_FALSE(session.isSet("testKey"));
171 }
172 {
173 connectionInit1.requestInit.cookieVars.insert({"SESSION", sessionId});
174 Connection connection(connectionInit1);
175 auto& session = connection.session();
176 session.start();
177 CHECK_FALSE(session.getID() == sessionId);
178 CHECK_FALSE(session.isSet("testKey"));
179 }
180 }
181}
Response object to be passed back to NAWA and accessor to the request.
Exception class that can be used by apps to catch errors resulting from nawa function calls.
Class for managing sessions and getting and setting connection-independent session data.
nawa::Session & session() noexcept
Definition: Connection.cpp:348
void start(nawa::Cookie properties=Cookie())
Definition: Session.cpp:126
Definition: AppInit.h:31
TEST_CASE("nawa::Session class", "[unit][session]")
Definition: sessions.cpp:33