- User model with Ed25519 keypair identity - Register/login on home server (creates keypair) - Join guest servers with signature verification - Public endpoints for cross-server identity - Channel and message CRUD - JWT authentication middleware Architecture: Home server model, no federation, client-driven sync
127 lines
2.8 KiB
Dart
127 lines
2.8 KiB
Dart
import 'package:objectbox/objectbox.dart';
|
|
|
|
/// User entity - works for both HOME and GUEST servers
|
|
///
|
|
/// On HOME server:
|
|
/// - isLocal = true
|
|
/// - stores password, encrypted private key
|
|
/// - this is where identity lives
|
|
///
|
|
/// On GUEST server:
|
|
/// - isLocal = false
|
|
/// - homeServer contains the URL of user's home
|
|
/// - publicKey cached for verification
|
|
@Entity()
|
|
class User {
|
|
@Id()
|
|
int id = 0;
|
|
|
|
// Global identifier: "username@homeserver.com"
|
|
@Unique()
|
|
String userId;
|
|
|
|
// Basic profile
|
|
@Index()
|
|
String username;
|
|
String? displayName;
|
|
String? avatarUrl;
|
|
String? bio;
|
|
|
|
// Identity
|
|
String publicKey; // Ed25519 public key, always stored
|
|
|
|
// HOME SERVER ONLY: Auth & key backup
|
|
String? passwordHash;
|
|
String? encryptedPrivateKey; // Encrypted with user's password
|
|
String? keyPairSalt;
|
|
|
|
// Server relationship
|
|
bool isLocal; // true = this is their home server
|
|
String? homeServer; // if guest, where is their home? (e.g., "https://my.server.com")
|
|
|
|
// Server-specific
|
|
List<String> roles; // ["admin", "moderator", "member"]
|
|
|
|
@Property(type: PropertyType.date)
|
|
DateTime createdAt;
|
|
|
|
@Property(type: PropertyType.date)
|
|
DateTime? lastSyncedAt; // When profile was last refreshed from home
|
|
|
|
User({
|
|
required this.userId,
|
|
required this.username,
|
|
required this.publicKey,
|
|
required this.isLocal,
|
|
this.displayName,
|
|
this.avatarUrl,
|
|
this.bio,
|
|
this.passwordHash,
|
|
this.encryptedPrivateKey,
|
|
this.keyPairSalt,
|
|
this.homeServer,
|
|
List<String>? roles,
|
|
DateTime? createdAt,
|
|
DateTime? lastSyncedAt,
|
|
}) : roles = roles ?? ['member'],
|
|
createdAt = createdAt ?? DateTime.now(),
|
|
lastSyncedAt = lastSyncedAt;
|
|
}
|
|
|
|
@Entity()
|
|
class Channel {
|
|
@Id()
|
|
int id = 0;
|
|
|
|
@Unique()
|
|
String name;
|
|
|
|
String? description;
|
|
|
|
@Property(type: PropertyType.date)
|
|
DateTime createdAt;
|
|
|
|
Channel({
|
|
required this.name,
|
|
this.description,
|
|
DateTime? createdAt,
|
|
}) : createdAt = createdAt ?? DateTime.now();
|
|
}
|
|
|
|
@Entity()
|
|
class Message {
|
|
@Id()
|
|
int id = 0;
|
|
|
|
int channelId;
|
|
|
|
// Author info - includes enough for cross-server profile fetch
|
|
int authorLocalId;
|
|
String authorUserId; // "alice@homeserver.com"
|
|
String? authorHomeServer; // for profile fetching
|
|
|
|
// Cached for display (snapshot at message time)
|
|
String authorUsername;
|
|
String? authorAvatarUrl;
|
|
|
|
String content;
|
|
|
|
@Property(type: PropertyType.date)
|
|
DateTime createdAt;
|
|
|
|
@Property(type: PropertyType.date)
|
|
DateTime? editedAt;
|
|
|
|
Message({
|
|
required this.channelId,
|
|
required this.authorLocalId,
|
|
required this.authorUserId,
|
|
required this.authorUsername,
|
|
required this.content,
|
|
this.authorHomeServer,
|
|
this.authorAvatarUrl,
|
|
DateTime? createdAt,
|
|
this.editedAt,
|
|
}) : createdAt = createdAt ?? DateTime.now();
|
|
}
|