Files
OwnCord/Server/db/mappers.go
T
J3vbandClaude Opus 4.8 81a0b63e65 feat(e2ee): F3 identity/TOFU + W2-4/W3-3 hardening — checkpoint before F3 UI
WIP save point. Server + W2-4/W3-3 complete and gate-green; F3 voice E2EE
identity keys + TOFU implemented and MITM-verified-closed; the F3 voice-panel
UI (safety-number display, verified/mismatch badge, re-pin modal) is still TODO.

- W2-4 attachment link (coverage confirmed); W3-3a XFF CIDR pre-parse;
  W3-3b update-binary TOCTOU (single-handle verify + O_EXCL staging)
- F3 server: migration 017 identity_public_key, PATCH /users/me persist,
  ready/member_join/user_update carry key, signed voice_e2ee_announce
- F3 client: ECDSA identity keypair (keyring + pin store), publish wired into
  ready, verifyPeerAnnounce pin-before-legacy, rePinPeerIdentity recovery
- Gates: server full CI mirror green (-race/-deadlock/lint/4 build tags);
  client typecheck/lint/format + 3337 vitest green. Rust CI-verify only.

Next: build F3 voice-panel UI, then adversarial review, then finalize commit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-23 21:07:09 +02:00

91 lines
2.4 KiB
Go

package db
import "github.com/owncord/server/db/dbgen"
// This file holds the conversions from sqlc-generated row/model types
// (db/dbgen) to the domain model types this package exposes. sqlc emits int64
// for integer columns and *string for nullable text; the domain models use
// narrower Go types (int, bool, non-pointer string) for ergonomics, so each
// delegating read maps through one of these helpers. See docs/plans/sqlc-adoption.md.
// derefString returns the pointed-to string, or "" when the pointer is nil.
// Used for columns the schema allows to be NULL but the domain model exposes
// as a plain string (device, ip_address).
func derefString(s *string) string {
if s == nil {
return ""
}
return *s
}
// ptrI64toI narrows a *int64 (sqlc's nullable-integer type) to a *int, which
// the domain models use for optional counts (e.g. invite max_uses).
func ptrI64toI(p *int64) *int {
if p == nil {
return nil
}
v := int(*p)
return &v
}
// ptrItoI64 widens a *int to a *int64 for passing into a generated params
// struct (the inverse of ptrI64toI).
func ptrItoI64(p *int) *int64 {
if p == nil {
return nil
}
v := int64(*p)
return &v
}
// b2i64 converts a bool to sqlc's int64 representation of a SQLite boolean.
func b2i64(b bool) int64 {
if b {
return 1
}
return 0
}
// strToNullPtr returns nil for an empty string, else a pointer to it — so
// empty strings are written as NULL in optional TEXT columns (matches the
// former nullableString helper).
func strToNullPtr(s string) *string {
if s == "" {
return nil
}
return &s
}
// userFromGen maps a generated user row to the domain User model.
func userFromGen(u dbgen.User) *User {
return &User{
ID: u.ID,
Username: u.Username,
PasswordHash: u.Password,
Avatar: u.Avatar,
RoleID: u.RoleID,
TOTPSecret: u.TotpSecret,
Status: u.Status,
CreatedAt: u.CreatedAt,
LastSeen: u.LastSeen,
Banned: u.Banned != 0,
BanReason: u.BanReason,
BanExpires: u.BanExpires,
IdentityPublicKey: u.IdentityPublicKey,
}
}
// sessionFromGen maps a generated session row to the domain Session model.
func sessionFromGen(s dbgen.Session) Session {
return Session{
ID: s.ID,
UserID: s.UserID,
TokenHash: s.Token,
Device: derefString(s.Device),
IP: derefString(s.IpAddress),
CreatedAt: s.CreatedAt,
LastUsed: s.LastUsed,
ExpiresAt: s.ExpiresAt,
}
}