feat: Require scopeId on domain tables to ensure user isolation (#73)
This commit is contained in:
parent
4f2e6b3210
commit
84cfbadc45
8 changed files with 4258 additions and 770 deletions
|
|
@ -10,8 +10,8 @@ extends: BaseHlc
|
|||
table: crdt_data_rows
|
||||
database: all
|
||||
fields:
|
||||
### Identifier for the user or client that owns the data.
|
||||
user: CrdtUser?, relation(onDelete=Cascade)
|
||||
### Identifier for the scope that owns the data.
|
||||
scope: CrdtScope?, relation(onDelete=Cascade)
|
||||
|
||||
### Reference to the table this row belongs to.
|
||||
tbl: CrdtSchemaTable?, relation(onDelete=Cascade)
|
||||
|
|
@ -38,6 +38,6 @@ fields:
|
|||
fields: List<CrdtDataField>?, relation(name=row_fields)
|
||||
|
||||
indexes:
|
||||
crdt_data_rows_user_tbl_row_idx:
|
||||
fields: userId, tblId, uuidRowId
|
||||
crdt_data_rows_scope_tbl_row_idx:
|
||||
fields: scopeId, tblId, uuidRowId
|
||||
unique: true
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ class: CrdtNode
|
|||
table: crdt_nodes
|
||||
database: all
|
||||
fields:
|
||||
### The user that owns the node.
|
||||
user: CrdtUser?, relation(name=user_nodes, onDelete=Cascade)
|
||||
### The scope that owns the node.
|
||||
scope: CrdtScope?, relation(name=scope_nodes, onDelete=Cascade)
|
||||
|
||||
### Unique identifier for the node.
|
||||
uuidNodeId: UuidValue, default=random_v7, unique
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
### CRDT scopes table.
|
||||
###
|
||||
### Normalized storage for scope IDs. The normalized data table references this
|
||||
### by integer id instead of storing the scope id string.
|
||||
class: CrdtScope
|
||||
table: crdt_scopes
|
||||
database: all
|
||||
fields:
|
||||
### Scope identifier string.
|
||||
uuidScopeId: UuidValue, default=random_v7, unique
|
||||
|
||||
### The current node id of the scope.
|
||||
currentNode: CrdtNode?, relation(optional)
|
||||
|
||||
### The nodes associated with the scope.
|
||||
nodes: List<CrdtNode>?, relation(name=scope_nodes)
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
### CRDT users table.
|
||||
###
|
||||
### Normalized storage for user IDs. The normalized data table references this
|
||||
### by integer id instead of storing the user id string.
|
||||
class: CrdtUser
|
||||
table: crdt_users
|
||||
database: all
|
||||
fields:
|
||||
### User identifier string.
|
||||
uuidUserId: UuidValue, default=random_v7, unique
|
||||
|
||||
### The current node id of the user.
|
||||
currentNode: CrdtNode?, relation(optional)
|
||||
|
||||
### The nodes associated with the user.
|
||||
nodes: List<CrdtNode>?, relation(name=user_nodes)
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
### Durable record of a terminal CRDT sync integrity violation.
|
||||
###
|
||||
### These rows are sparse diagnostic state. They record observed corruption or
|
||||
### hostile input without duplicating hot CRDT indexes.
|
||||
###
|
||||
### All identifiers are denormalized UUIDs and names so the record remains
|
||||
### useful after merge rollbacks and across databases that do not share the
|
||||
### same local CRDT metadata rows.
|
||||
class: CrdtSyncIntegrityViolation
|
||||
table: crdt_sync_integrity_violations
|
||||
database: all
|
||||
fields:
|
||||
### High-level integrity violation category.
|
||||
type: CrdtSyncViolationType
|
||||
|
||||
### Durable table name for the violated domain row.
|
||||
domainTableName: String
|
||||
|
||||
### Domain row UUID involved in the violation.
|
||||
uuidRowId: UuidValue
|
||||
|
||||
### Global scope UUID that owns the physical domain row, when known.
|
||||
ownerScopeUuid: UuidValue?
|
||||
|
||||
### Global scope UUID that attempted to operate on the row.
|
||||
incomingScopeUuid: UuidValue
|
||||
|
||||
### Merge or sync operation that observed the violation.
|
||||
operation: CrdtSyncViolationOperation
|
||||
|
||||
### UUID of the node that authored the rejected change, when known.
|
||||
uuidNodeId: UuidValue?
|
||||
|
||||
### Local CRDT metadata row id observed for the rejected operation, when known.
|
||||
crdtDataRowId: int?
|
||||
|
||||
### Last observed HLC datetime for the rejected change, when known.
|
||||
hlcDatetime: DateTime?
|
||||
|
||||
### Last observed HLC counter for the rejected change, when known.
|
||||
hlcCounter: int?
|
||||
|
||||
### First time this violation key was observed.
|
||||
firstSeenAt: DateTime
|
||||
|
||||
### Most recent time this violation key was observed.
|
||||
lastSeenAt: DateTime
|
||||
|
||||
### Number of times this violation key has been observed.
|
||||
occurrences: int
|
||||
|
||||
indexes:
|
||||
crdt_sync_integrity_violations_key_idx:
|
||||
fields: type, operation, domainTableName, uuidRowId, ownerScopeUuid, incomingScopeUuid
|
||||
unique: true
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
### Merge or sync operation that observed an integrity violation.
|
||||
enum: CrdtSyncViolationOperation
|
||||
serialized: byName
|
||||
values:
|
||||
- mergeInsert
|
||||
- mergeUpdate
|
||||
- mergeDelete
|
||||
- outboundInsert
|
||||
- outboundUpdate
|
||||
- outboundDelete
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
### High-level category of a durable CRDT sync integrity violation.
|
||||
enum: CrdtSyncViolationType
|
||||
serialized: byName
|
||||
values:
|
||||
- ownershipCollision
|
||||
- missingDomainRow
|
||||
|
|
@ -10,12 +10,12 @@ resolution: workspace
|
|||
|
||||
dependencies:
|
||||
meta: ^1.16.0
|
||||
serverpod: 3.5.0-beta.9
|
||||
serverpod_database: 3.5.0-beta.9
|
||||
serverpod: 3.5.0-beta.10
|
||||
serverpod_database: 3.5.0-beta.10
|
||||
serverpod_offline_sync_client: 0.0.1
|
||||
serverpod_offline_sync_shared: 0.0.1
|
||||
|
||||
dev_dependencies:
|
||||
lints: '>=3.0.0 <7.0.0'
|
||||
serverpod_test: 3.5.0-beta.9
|
||||
serverpod_test: 3.5.0-beta.10
|
||||
test: ^1.25.5
|
||||
|
|
|
|||
Loading…
Reference in a new issue