Database | Members | |
---|---|---|
Purpose | Track the members in the engagement. | |
Cardinality |
one Members database in the engagement
one NextMemberItem per engagement
one MemberItem per member in the engagement
|
|
Source Code | ||
Items | src/ts/dbitems/Members.ts | |
Zod Models | ||
item | MembersItem - union of NextMemberItem , MemberItem below |
|
item.item | one of NextMemberRecord , MemberRecord |
|
NextMemberItem |
||
itemId | nextmember | |
item: | NextMemberRecord |
|
kind | 'nextmember' | |
nextmnum | mnum to assign to next member | |
MemberItem |
||
itemId | number assigned to member. first (host) is 1. | |
item: | MemberRecord |
|
kind | 'member' | |
mnum | number assigned to member (same as itemId) | |
role | 'host', 'guest' or 'removed' | |
userid | userbase userid, saved from when member's user is signed up | |
dbids: | ||
user | dbid of member's User database |
Description
The Members database is created when the host creates a new engagement. It holds one item to track the next member number and also one item for each guest invited to the engagement that has not been subsequently removed.
(see userbase-js/types/index.d.ts) export interface Item { userbase item itemId: string ╭────────────────────────┐ item: any ────────────────────┬──▶│ kind: 'member' │ createdBy: Attribution │ │ mnum: 1 │ updatedBy?: Attribution │ │ ... │ fileId?: string │ ╰────────────────────────┘ fileName?: string │ fileSize?: number │ fileUploadedBy?: Attribution │ ╭────────────────────────┐ writeAccess?: AccessControl └──▶│ kind: 'nextmember' │ } │ nextmnum: 2 │ ╰────────────────────────┘ MembersRecord represents the specific type of Item.item for an entry in the Members database - either NextMemberRecord or MemberRecord.
Queries
Securepub queries the Members database in order to determine the members of the engagement and find the dbids of each member's User database.
one per one per member engagement AppId ╶╶╶╶╶╶╶╶╶╶╶► ULID-Role ╶╶╶╶╶╶╶╶╶╶╶► Members + database database RoleID ╵ ╵ └╶╶╶╶╶╶► User database
Securepub queries the Members database to derive Userbase usernames for the members in the engagement with the following procedure:
1. selecting the database from getDatabases() whose databaseId matches dbids.user 2. searching the database's users array for an object with isOwner = true and 3. selecting the corresponding username from that object ╭─────────────╮ ╭──────────────────────╮ │ Members │ │ getDatabases │ ├─────────────┤ ├──────────────────────┤ │ dbids.user │╶╶╶╶►│ databaseId (User) │ ╰─────────────╯ │ users │ │ ╶╶► isOwner true │ │ username │ ╰──────────────────────╯
Securepub records but does not directly use member Userbase userids.
Userids are visible to the host and can be used in the Userbase Admin interface.
NextMemberItem
The Members database holds one NextMemberItem
which keeps track of the next "mnum" (member
number) which will be assigned to the next member invited by the host.
Member numbers are monotonically increasing integers starting with 1.
MemberItem
The Members database holds one MemberItem
for each invited member.
Ownership and Access
The engagement host is the owner of the Members database.
Only the host may write to the Members database.
The Members database is shared readable with all members.
Zod models
The following Zod models show how the Userbase items are represented in memory.
Note that in addition to the values specified by the Userbase Item interface the kind and database attributes are added during deserialization.
export type MembersItem =
| NextMemberItem
| MemberItem
;
export const MembersItem = z.discriminatedUnion('kind', [
NextMemberItem,
MemberItem
]);
NextMemberItem
export type NextMemberItem = z.infer<typeof NextMemberItem>;
export const NextMemberItem = z.object({
kind: z.literal('nextmemberitem'),
itemId: z.string(),
item: NextMemberRecord,
updatedBy: z.custom<Attribution>(),
database: z.custom<Database>()
}).strip();
/*
* NextMemberRecord
*/
export type NextMemberRecord = z.infer<typeof NextMemberRecord>;
export const NextMemberRecord = z.object({
kind: z.literal('nextmember'),
nextbnum: z.number()
}).strip();
MemberItem
export type MemberItem = z.infer<typeof MemberItem>;
export const MemberItem = z.object({
kind: z.literal('memberitem'),
itemId: z.string(),
item: MemberRecord,
updatedBy: z.custom<Attribution>(),
database: z.custom<Database>()
}).strip();
export type MemberRecord = z.infer<typeof MemberRecord>;
export const MemberRecord = z.object({
kind: z.literal('member'),
mnum: z.number(),
role: z.union([
z.literal("host"),
z.literal("guest"),
z.literal("removed")
]),
userid: z.string(),
dbids: z.object({
user: z.string()
})
}).strip();