Download as txt, pdf, or txt
Download as txt, pdf, or txt
You are on page 1of 2

# Database

NChat will use a Postgres database to store all data. There will be n tables in the
database:
- Users: stores all user profile and preference data, user ID is primary key
- Sessions: stores all conversations which the user is a part of, inc. servers
and DMs
- Servers: todo!(), stores all servers and a list of their associated users, admin
status &c. Server ID is primary key
- Channels: stores all channels across all servers, linked to a server by its
ID.
- Tokens: stores OAuth access tokens, scope and associated users
- Static: static file storage, files stored as blobs and looked up by file ID,
which is the primary key
- Inboxes: stores incoming messages per-user
- Outboxes: stores outgoing messages per-user
- Devices: stores a list of logged-in devices and their associated users

Note: the `NCID` objects below are Strings formatted as follows:


`format!("nchat://{object_id}@{homeserver_url}")`
This is to allow for communication between multiple homeservers, as any one
homeserver would have no way of deriving the homeserver
of a user solely from their UUID without a central registry, which I want to avoid.
This does however mean that the usual foreign key
relationships will not work, so the only relationships handled by the _database_
will be between Tokens & Devices, and Users, as these are homeserver-local.

```rust
Users {
user_id: NCID, // User's unique identifier. Primary Key
username: String,
user_bio: Option<String>,
password_hash: String, // SHA256 hash of the user's password
}

// Note: this is required for secure end-to-end encryption. The server will
facilitate a Diffie-Hellman key exchange between _all_ clients of a
Devices {
device_id: NCID,
user_id: NCID,
}

DMSessions {
user_1_id: NCID -> Users,
user_2_id: NCID -> Users
}

ChannelSessions {
user_id: NCID -> Users,
channel_id: NCID -> Channels
}

// Note: this is really just a special case of the User class with no login
password
Servers {
server_id: NCID, // Server's unique identifier. Primary Key
server_name: String,
server_description: Option<String>
}
Channels {
channel_id: NCID, // Channel's unique ID. Primary Key
channel_name: String,
channel_description: Option<String>,
server_id: NCID -> Servers
}

Tokens {
token_id: Uuid, // This is what is returned to the user's client. Primary Key
user_id: NCID -> Users,
scopes: String,
is_refresh: bool, // Whether this token is a refresh token (if true), otherwise
it is an access token
expiry: Option<DateTime> // The expiry time of this token.
}

Static {
blob_id: Uuid, // Binary blob's unique ID. Primary Key
data: Blob // Unsure of exactly how this will be implemented with Postgres
}

Mailbox {
message_id: Uuid,
from: NCID, // This should be formed e.g. as nchat://<user_id>@<homeserver>
to: NCID,
message_type: MessageType,
content: String // This is encrypted, unless the type of the message is a
FriendRequest (1), in which case the format is:
// format!("nchat://<user_id>@<homeserver>/kexchange/<diffie-
hellman public shared key>/<DH mixed key>")
}

enum MessageType {
Text, // 0
FriendRequest // 1
// Other stuff maybe here in future
}
```

You might also like