Prechádzať zdrojové kódy

US30.1: Notifications (Server)

Rescheleit, Marius 4 rokov pred
rodič
commit
592394bbe7

+ 5 - 0
daemon/include/JsonCommander.h

@@ -146,6 +146,11 @@ private:
 	 * Executes the deletefile command
 	 */
 	Response executeDeleteFile(const Json::Value &message);
+
+	/**
+	 * Executes the notifications command
+	 */
+	Response executeNotifications(const Json::Value &message);
 };
 
 #endif

+ 39 - 0
daemon/include/Notifications.h

@@ -0,0 +1,39 @@
+#ifndef NOTIFICATIONS_H
+#define NOTIFICATIONS_H
+
+#include <map>
+#include <string>
+#include <vector>
+
+/**
+ * Namespace which holds notifications
+ */
+namespace Notifications {
+/**
+ * Add a new notification. Will be stored in messages and delivered by getMessages
+ * @param message the new notification
+ */
+void newNotification(const std::string &message);
+
+/**
+ * Get all messages for a given users
+ * Deletes all messages wihch are older than a week
+ * @param user
+ * @return vector with all messages
+ */
+std::vector<std::string> getMessages(const std::string &user);
+
+/**
+ * Stores the notifications
+ * First is the timestamp
+ * Second is the message
+ */
+extern std::vector<std::pair<long int, std::string>> messages;
+
+/**
+ * Stores information when a user get messages for the last time
+ */
+extern std::map<std::string, long int> userTimeStamps;
+}; // namespace Notifications
+
+#endif

+ 1 - 1
daemon/src/CMakeLists.txt

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8)
 
 set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
 
-add_executable(ccats src/main.cpp src/Server.cpp src/base64.cpp src/JsonCommander.cpp src/FileManager.cpp src/UserManager.cpp src/Config.cpp src/CovertChannel/CovertChannel.cpp src/CovertChannel/ForwardChannel.cpp)
+add_executable(ccats src/main.cpp src/Server.cpp src/base64.cpp src/JsonCommander.cpp src/FileManager.cpp src/UserManager.cpp src/Config.cpp src/CovertChannel/CovertChannel.cpp src/CovertChannel/ForwardChannel.cpp src/Notifications.cpp)
 
 # dependencies used by server only
 find_package(libtins 4.2 REQUIRED)

+ 19 - 0
daemon/src/JsonCommander.cpp

@@ -1,4 +1,5 @@
 #include "../include/JsonCommander.h"
+#include "../include/Notifications.h"
 #include "../include/UserManager.h"
 #include "../include/base64.h"
 
@@ -14,6 +15,7 @@ JsonCommander::JsonCommander(FileManager &fileManager) : fileManager(fileManager
 	commandsMap["head"] = &JsonCommander::executeHead;
 	commandsMap["deleteme"] = &JsonCommander::executeDeleteMe;
 	commandsMap["deletefile"] = &JsonCommander::executeDeleteFile;
+	commandsMap["notifications"] = &JsonCommander::executeNotifications;
 }
 
 JsonCommander::~JsonCommander() {}
@@ -516,3 +518,20 @@ JsonCommander::Response JsonCommander::executeDeleteFile(const Json::Value &mess
 
 	return response;
 }
+
+JsonCommander::Response JsonCommander::executeNotifications(const Json::Value &message) {
+	JsonCommander::Response response;
+	response.json["command"] = "notifications";
+
+	Json::Value array;
+	std::vector<std::string> v = Notifications::getMessages(currentUser);
+	for (int i = 0; i < v.size(); i++)
+		array.append(v.at(i));
+
+	response.action = send;
+	response.json["messages"] = array;
+	response.json["accept"] = true;
+	response.json["error"] = "";
+
+	return response;
+}

+ 48 - 0
daemon/src/Notifications.cpp

@@ -0,0 +1,48 @@
+#include "../include/Notifications.h"
+
+#include <ctime>
+
+namespace Notifications {
+std::vector<std::pair<long int, std::string>> messages;
+std::map<std::string, long int> userTimeStamps;
+}; // namespace Notifications
+
+void Notifications::newNotification(const std::string &message) {
+	long int timestamp = static_cast<long int>(time(0));
+	messages.push_back(make_pair(timestamp, message));
+}
+
+std::vector<std::string> Notifications::getMessages(const std::string &user) {
+	std::vector<std::string> ret;
+
+	// first clean up
+	long int latest = static_cast<long int>(time(0)) - 604800;
+	for (int i = 0; i < messages.size(); i++) {
+		if (messages.at(i).first < latest) {
+			messages.erase(messages.begin() + i);
+		}
+	}
+
+	auto it = userTimeStamps.find(user);
+	if (it == userTimeStamps.end()) {
+		// case user has no timestamp yet
+
+		for (int i = 0; i < messages.size(); i++) {
+			ret.push_back(messages.at(i).second);
+		}
+		userTimeStamps.insert(std::pair<std::string, long int>(user, static_cast<long int>(time(0))));
+	} else {
+		long int userTimeStamp = it->second;
+
+		for (int i = 0; i < messages.size(); i++) {
+			if (userTimeStamp <= messages.at(i).first) {
+				ret.push_back(messages.at(i).second);
+			}
+		}
+
+		// update user timestamp
+		it->second = static_cast<long int>(time(0));
+	}
+
+	return ret;
+}

+ 1 - 1
daemon/test/CMakeLists.txt

@@ -12,7 +12,7 @@ find_package(GMock REQUIRED)
 include_directories(${Boost_INCLUDE_DIR} ${JSONCPP_INCLUDE_DIRS} ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS})
 
 # Add test cpp file
-add_executable(jsonCommanderTest test/JsonCommanderTest.cpp src/JsonCommander.cpp src/FileManager.cpp src/base64.cpp test/ConfigMock.cpp test/UserManagerMock.cpp)
+add_executable(jsonCommanderTest test/JsonCommanderTest.cpp src/JsonCommander.cpp src/FileManager.cpp src/base64.cpp test/ConfigMock.cpp test/UserManagerMock.cpp src/Notifications.cpp)
 target_link_libraries(jsonCommanderTest ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES} ${JSONCPP_LIBRARIES} ${GTEST_BOTH_LIBRARIES} ${GMOCK_BOTH_LIBRARIES})
 
 add_test(

+ 115 - 0
daemon/test/JsonCommanderTest.cpp

@@ -2,6 +2,7 @@
 #include <gtest/gtest.h>
 
 #include "../include/JsonCommander.h"
+#include "../include/Notifications.h"
 #include "FileManagerMock.h"
 
 namespace {
@@ -1196,4 +1197,118 @@ TEST(DeleteFile, DisabledInConfig) {
 	EXPECT_TRUE(response.json["error"].asString().compare("") != 0);
 }
 
+TEST(Notifications, NoMessage) {
+	FileManagerMock fileManager;
+
+	JsonCommander jsonCommander(fileManager);
+
+	const std::string command = "notifications";
+
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+
+	Json::Value message;
+	message["command"] = command;
+
+	JsonCommander::Response response = jsonCommander.execute(message);
+	EXPECT_TRUE(response.action == JsonCommander::Action::send);
+	EXPECT_EQ(response.json["command"].asString(), command);
+	EXPECT_TRUE(response.json["accept"].asBool());
+	EXPECT_EQ(response.json["error"].asString(), "");
+	EXPECT_TRUE(response.json["messages"].isNull());
+}
+
+TEST(Notifications, OneMessage) {
+	FileManagerMock fileManager;
+
+	JsonCommander jsonCommander(fileManager);
+
+	const std::string command = "notifications";
+
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+	Notifications::newNotification("asdf");
+
+	Json::Value message;
+	message["command"] = command;
+
+	JsonCommander::Response response = jsonCommander.execute(message);
+	EXPECT_TRUE(response.action == JsonCommander::Action::send);
+	EXPECT_EQ(response.json["command"].asString(), command);
+	EXPECT_TRUE(response.json["accept"].asBool());
+	EXPECT_EQ(response.json["error"].asString(), "");
+	EXPECT_TRUE(response.json["messages"].isArray());
+	EXPECT_EQ(response.json["messages"][0], "asdf");
+
+	// cleaning up
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+}
+
+TEST(Notifications, OneMessageMultipleTimesCalled) {
+	FileManagerMock fileManager;
+
+	JsonCommander jsonCommander(fileManager);
+
+	const std::string command = "notifications";
+
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+	Notifications::newNotification("asdf");
+
+	Json::Value message;
+	message["command"] = command;
+
+	JsonCommander::Response response = jsonCommander.execute(message);
+	EXPECT_TRUE(response.action == JsonCommander::Action::send);
+	EXPECT_EQ(response.json["command"].asString(), command);
+	EXPECT_TRUE(response.json["accept"].asBool());
+	EXPECT_EQ(response.json["error"].asString(), "");
+	EXPECT_TRUE(response.json["messages"].isArray());
+	EXPECT_EQ(response.json["messages"][0], "asdf");
+
+	// make suhre that timestamp from message is older
+	Notifications::messages.at(0).first--;
+
+	response = jsonCommander.execute(message);
+	EXPECT_TRUE(response.action == JsonCommander::Action::send);
+	EXPECT_EQ(response.json["command"].asString(), command);
+	EXPECT_TRUE(response.json["accept"].asBool());
+	EXPECT_EQ(response.json["error"].asString(), "");
+	EXPECT_TRUE(response.json["messages"].isNull());
+
+	// cleaning up
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+}
+
+TEST(Notifications, TwoMessages) {
+	FileManagerMock fileManager;
+
+	JsonCommander jsonCommander(fileManager);
+
+	const std::string command = "notifications";
+
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+	Notifications::newNotification("asdf");
+	Notifications::newNotification("qwer");
+
+	Json::Value message;
+	message["command"] = command;
+
+	JsonCommander::Response response = jsonCommander.execute(message);
+	EXPECT_TRUE(response.action == JsonCommander::Action::send);
+	EXPECT_EQ(response.json["command"].asString(), command);
+	EXPECT_TRUE(response.json["accept"].asBool());
+	EXPECT_EQ(response.json["error"].asString(), "");
+	EXPECT_TRUE(response.json["messages"].isArray());
+	EXPECT_EQ(response.json["messages"][0], "asdf");
+	EXPECT_EQ(response.json["messages"][1], "qwer");
+
+	// cleaning up
+	Notifications::messages.clear();
+	Notifications::userTimeStamps.clear();
+}
+
 } // namespace