aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/dchat/Room.hpp24
-rw-r--r--src/Room.cpp68
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
+}