diff options
-rw-r--r-- | include/dchat/Room.hpp | 24 | ||||
-rw-r--r-- | 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<odhtdb::Database> database, std::shared_ptr<odhtdb::Hash> id, std::shared_ptr<odhtdb::OwnedByteArray> encryptionKey); + Room(Rooms *rooms, std::shared_ptr<odhtdb::Hash> id, std::shared_ptr<odhtdb::OwnedByteArray> encryptionKey); std::shared_ptr<User> addUser(const odhtdb::Signature::PublicKey &userPublicKey, const odhtdb::DataView groupId); // Returns null if user doesn't exist in room std::shared_ptr<User> getUserByPublicKey(const odhtdb::Signature::PublicKey &userPublicKey); void publishMessage(const std::string &msg); - std::shared_ptr<odhtdb::Database> database; + Rooms *rooms; std::shared_ptr<odhtdb::Hash> id; std::shared_ptr<odhtdb::OwnedByteArray> encryptionKey; std::string name; @@ -42,8 +44,6 @@ namespace dchat void *userdata; }; - class Rooms; - struct RoomAddMessageRequest { std::shared_ptr<Room> room; @@ -60,12 +60,22 @@ namespace dchat std::string newNickname; }; + struct RoomChangeNameRequest + { + std::shared_ptr<Room> room; + std::shared_ptr<User> 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<void(std::shared_ptr<Rooms> rooms, const char *errMsg)>; using CreateRoomCallbackFunc = std::function<void(std::shared_ptr<Room> room)>; using RoomAddUserCallbackFunc = std::function<void(std::shared_ptr<Room> room, std::shared_ptr<User> user)>; using RoomAddMessageCallbackFunc = std::function<void(const RoomAddMessageRequest &request)>; using UserChangeNicknameCallbackFunc = std::function<void(const UserChangeNicknameRequest &request)>; + using ChangeRoomNameCallbackFunc = std::function<void(const RoomChangeNameRequest &request)>; 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<odhtdb::Database> database; private: @@ -98,5 +111,8 @@ namespace dchat bool loggedIn; odhtdb::MapHash<std::shared_ptr<odhtdb::Signature::KeyPair>> roomLocalUser; odhtdb::MapHash<std::shared_ptr<odhtdb::OwnedByteArray>> 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<odhtdb::Database> _database, std::shared_ptr<odhtdb::Hash> _id, std::shared_ptr<odhtdb::OwnedByteArray> _encryptionKey) : - database(_database), + Room::Room(Rooms *_rooms, std::shared_ptr<odhtdb::Hash> _id, std::shared_ptr<odhtdb::OwnedByteArray> _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<odhtdb::Hash>(*request.nodeHash); - auto room = std::make_shared<Room>(database, roomId, encryptionKey); + auto room = std::make_shared<Room>(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<u16>(); + 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<odhtdb::Hash>(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 +} |