From fe99723d0a6374ee20c52b0f96c45452026da519 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Sat, 3 Nov 2018 01:09:27 +0100 Subject: Add room change event, create room func --- include/dchat/Room.hpp | 24 +++++++++++++++--- src/Room.cpp | 68 ++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 9 deletions(-) diff --git a/include/dchat/Room.hpp b/include/dchat/Room.hpp index 4422a6f..4938aea 100644 --- a/include/dchat/Room.hpp +++ b/include/dchat/Room.hpp @@ -20,17 +20,19 @@ namespace dchat std::string text; }; + class Rooms; + class Room { DISABLE_COPY(Room) public: - Room(std::shared_ptr database, std::shared_ptr id, std::shared_ptr encryptionKey); + Room(Rooms *rooms, std::shared_ptr id, std::shared_ptr encryptionKey); std::shared_ptr addUser(const odhtdb::Signature::PublicKey &userPublicKey, const odhtdb::DataView groupId); // Returns null if user doesn't exist in room std::shared_ptr getUserByPublicKey(const odhtdb::Signature::PublicKey &userPublicKey); void publishMessage(const std::string &msg); - std::shared_ptr database; + Rooms *rooms; std::shared_ptr id; std::shared_ptr encryptionKey; std::string name; @@ -42,8 +44,6 @@ namespace dchat void *userdata; }; - class Rooms; - struct RoomAddMessageRequest { std::shared_ptr room; @@ -60,12 +60,22 @@ namespace dchat std::string newNickname; }; + struct RoomChangeNameRequest + { + std::shared_ptr room; + std::shared_ptr user; + uint32_t timestampSeconds; + bool loadedFromCache; + std::string newName; + }; + // if connection failed then @rooms is null and errMsg contains the error using ConnectBoostrapNodeCallbackFunc = std::function rooms, const char *errMsg)>; using CreateRoomCallbackFunc = std::function room)>; using RoomAddUserCallbackFunc = std::function room, std::shared_ptr user)>; using RoomAddMessageCallbackFunc = std::function; using UserChangeNicknameCallbackFunc = std::function; + using ChangeRoomNameCallbackFunc = std::function; struct RoomCallbackFuncs { ConnectBoostrapNodeCallbackFunc connectCallbackFunc; @@ -73,6 +83,7 @@ namespace dchat RoomAddUserCallbackFunc addUserCallbackFunc; RoomAddMessageCallbackFunc addMessageCallbackFunc; UserChangeNicknameCallbackFunc userChangeNicknameCallbackFunc; + ChangeRoomNameCallbackFunc changeRoomNameCallbackFunc; }; class Rooms @@ -85,6 +96,8 @@ namespace dchat void loginUser(const std::string &username, const std::string &password); // Throws on failure void registerUser(const std::string &username, const std::string &password); + // Throws on failure + void createRoom(const std::string &name); std::shared_ptr database; private: @@ -98,5 +111,8 @@ namespace dchat bool loggedIn; odhtdb::MapHash> roomLocalUser; odhtdb::MapHash> roomEncryptionKey; + + std::string currentUsername; + std::string currentUserPassword; }; } \ No newline at end of file diff --git a/src/Room.cpp b/src/Room.cpp index cd6476d..30375a3 100644 --- a/src/Room.cpp +++ b/src/Room.cpp @@ -9,8 +9,8 @@ // TODO: Remove error checks when odhtdb has been improved to take care of such errors namespace dchat { - Room::Room(std::shared_ptr _database, std::shared_ptr _id, std::shared_ptr _encryptionKey) : - database(_database), + Room::Room(Rooms *_rooms, std::shared_ptr _id, std::shared_ptr _encryptionKey) : + rooms(_rooms), id(_id), encryptionKey(_encryptionKey), userdata(nullptr) @@ -48,7 +48,7 @@ namespace dchat serializer.add((const u8*)msg.data(), msg.size()); auto &keyPair = publicKeyToKeyPairMap[localUser->publicKey]; odhtdb::DatabaseNode roomNode(encryptionKey, id); - database->addData(roomNode, *keyPair, { serializer.getBuffer().data(), serializer.getSize() }); + rooms->database->addData(roomNode, *keyPair, { serializer.getBuffer().data(), serializer.getSize() }); } Rooms::Rooms(const char *address, u16 port, RoomCallbackFuncs _callbackFuncs) : @@ -74,12 +74,18 @@ namespace dchat auto encryptionKey = roomEncryptionKey[*request.nodeHash]; auto roomId = std::make_shared(*request.nodeHash); - auto room = std::make_shared(database, roomId, encryptionKey); + auto room = std::make_shared(this, roomId, encryptionKey); roomById[*request.nodeHash] = room; if(callbackFuncs.createRoomCallbackFunc) callbackFuncs.createRoomCallbackFunc(room); auto user = room->addUser(*request.creatorPublicKey, request.groupId); + auto localUserIt = roomLocalUser.find(*request.nodeHash); + if(localUserIt != roomLocalUser.end()) + { + room->localUser = user; + room->publicKeyToKeyPairMap[user->publicKey] = localUserIt->second; + } if(callbackFuncs.addUserCallbackFunc) callbackFuncs.addUserCallbackFunc(room, user); } @@ -153,6 +159,32 @@ namespace dchat } break; } + case RoomDataType::CHANGE_ROOM_NAME: + { + int userPermissionLevel = database->getUserLowestPermissionLevel(*room->id, user->publicKey); + if(userPermissionLevel != odhtdb::PERMISSION_LEVEL_ADMIN) + { + odhtdb::Log::debug("Room change name: attempted by user %s who is not an admin (permission level: %d)\n", user->publicKey.toString().c_str(), userPermissionLevel); + return; + } + + sibs::SafeDeserializer deserializer((const u8*)request.decryptedData.data + 1, request.decryptedData.size - 1); + u16 channelNameLength = deserializer.extract(); + if(channelNameLength > 0 && channelNameLength <= 32) + { + RoomChangeNameRequest roomRequest; + roomRequest.room = room; + roomRequest.user = user; + roomRequest.timestampSeconds = timestampSeconds; + roomRequest.loadedFromCache = request.loadedFromCache; + roomRequest.newName.resize(channelNameLength); + deserializer.extract((u8*)&roomRequest.newName[0], channelNameLength); + if(callbackFuncs.changeRoomNameCallbackFunc) + callbackFuncs.changeRoomNameCallbackFunc(roomRequest); + room->name = std::move(roomRequest.newName); + } + break; + } default: break; } @@ -207,10 +239,16 @@ namespace dchat auto storedNodes = database->getStoredNodeUserInfoDecrypted(username, password); loggedIn = true; + currentUsername = username; + currentUserPassword = password; for(auto &nodeInfo : storedNodes) { roomLocalUser[nodeInfo.first] = nodeInfo.second.userKeyPair; roomEncryptionKey[nodeInfo.first] = nodeInfo.second.nodeEncryptionKey; + + auto roomId = std::make_shared(nodeInfo.first); + odhtdb::DatabaseNode roomNode(nodeInfo.second.nodeEncryptionKey, roomId); + database->seed(roomNode); database->loadNode(nodeInfo.first); } } @@ -222,5 +260,25 @@ namespace dchat database->storeUserWithoutNodes(username, password); loggedIn = true; + currentUsername = username; + currentUserPassword = password; + } + + void Rooms::createRoom(const std::string &name) + { + if(!loggedIn) + throw std::runtime_error("You need to be logged in to create a room "); + + auto newNode = database->create(); + roomLocalUser[*newNode->getRequestHash()] = newNode->getNodeAdminKeyPair(); + roomEncryptionKey[*newNode->getRequestHash()] = newNode->getNodeEncryptionKey(); + + odhtdb::DatabaseNode nodeInfo(newNode->getNodeEncryptionKey(), newNode->getRequestHash()); + database->storeNodeInfoForUserEncrypted(nodeInfo, currentUsername, currentUserPassword, *newNode->getNodeAdminKeyPair()); + sibs::SafeSerializer serializer; + serializer.add(RoomDataType::CHANGE_ROOM_NAME); + serializer.add((u16)name.size()); + serializer.add(name.data(), name.size()); + database->addData(nodeInfo, *newNode->getNodeAdminKeyPair(), { serializer.getBuffer().data(), serializer.getSize() }); } -} \ No newline at end of file +} -- cgit v1.2.3