-
Notifications
You must be signed in to change notification settings - Fork 4
ENG-1233 Group functionality testing #678
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: eng-1238-group-creation-function
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| Feature: Group content access | ||
| User story: | ||
| * As a user of the Obsidian plugin | ||
| * Logged in through a given space's anonymous account | ||
| * I want to be able to create a group including another user outside my space | ||
| * giving that user access to my private content | ||
|
|
||
| Acceptance criteria: | ||
| * The second user should not have access to the content before I publish my content to the group | ||
| * The second user should have access after I publish my content to the group | ||
|
|
||
| Background: | ||
| Given the database is blank | ||
| And the user user1 opens the Roam plugin in space s1 | ||
| And the user user2 opens the Roam plugin in space s2 | ||
|
|
||
| Scenario Outline: Creating content | ||
| When Document are added to the database: | ||
| | $id | source_local_id | created | last_modified | _author_id | _space_id | | ||
| | d1 | ld1 | 2025/01/01 | 2025/01/01 | user1 | s1 | | ||
| And Content are added to the database: | ||
| | $id | source_local_id | _document_id | text | created | last_modified | scale | _author_id | _space_id | | ||
| | ct1 | lct1 | d1 | Claim | 2025/01/01 | 2025/01/01 | document | user1 | s1 | | ||
| Then a user logged in space s1 should see 2 PlatformAccount in the database | ||
| And a user logged in space s1 should see 1 Content in the database | ||
| And a user logged in space s2 should see 2 PlatformAccount in the database | ||
| But a user logged in space s2 should see 0 Content in the database | ||
| When user of space s1 creates group my_group | ||
| And user of space s1 adds space s2 to group my_group | ||
| Then a user logged in space s1 should see 1 Content in the database | ||
| But a user logged in space s2 should see 0 Content in the database | ||
| And ContentAccess are added to the database: | ||
| | _account_uid | _content_id | | ||
| | my_group | ct1 | | ||
| Then a user logged in space s1 should see 1 Content in the database | ||
| Then a user logged in space s2 should see 1 Content in the database |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -64,6 +64,19 @@ Given("the database is blank", async () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r = await client.from("AgentIdentifier").delete().neq("account_id", -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const r3 = await client.from("group_membership").select("group_id"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r3.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const groupIds = new Set((r3.data || []).map(({group_id})=>group_id)); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const id of groupIds) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const ur = await client.auth.admin.deleteUser(id); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(ur.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const r2 = await client.from("PlatformAccount").select("dg_account").not('dg_account', 'is', 'null'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r2.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for (const {dg_account} of r2.data || []) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const r = await client.auth.admin.deleteUser(dg_account!); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+74
to
+79
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: Use the raw PostgREST filter syntax. To filter "not null" with Supabase's .not(), pass operator "is" and JavaScript/SDK null value, e.g.:
Notes/caveats:
Sources: Remove quotes around The syntax 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r = await client.from("PlatformAccount").delete().neq("id", -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| r = await client.from("Space").delete().neq("id", -1); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -389,3 +402,40 @@ Then("query results should look like this", (table: DataTable) => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.deepEqual(truncatedResults, values); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| When("user of space {word} creates group {word}", async (spaceName: string, name: string)=>{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const localRefs = (world.localRefs || {}) as Record<string, number|string>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const spaceId = localRefs[spaceName]; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (spaceId === undefined) assert.fail("spaceId"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client = await getLoggedinDatabase(spaceId as number); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| try{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const response = await client.functions.invoke<{group_id: string}>("create-group", {body:{name}}); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(response.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| localRefs[name] = response.data!.group_id; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error((error as any).actual); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| throw error; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+406
to
+419
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add null check before accessing response.data. Line 414 uses a non-null assertion 🛡️ Proposed fix to add data validation try{
const response = await client.functions.invoke<{group_id: string}>("create-group", {body:{name}});
assert.equal(response.error, null);
- localRefs[name] = response.data!.group_id;
+ if (!response.data?.group_id) {
+ throw new Error("create-group response missing group_id");
+ }
+ localRefs[name] = response.data.group_id;
} catch (error) {
console.error((error as any).actual);
throw error;
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| When("user of space {word} adds space {word} to group {word}", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| async (space1Name: string, space2Name:string, groupName: string)=>{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const localRefs = (world.localRefs || {}) as Record<string, number|string>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const space1Id = localRefs[space1Name] as number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const space2Id = localRefs[space2Name] as number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const groupId = localRefs[groupName] as string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (space1Id === undefined) assert.fail("space1Id"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (space2Id === undefined) assert.fail("space2Id"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (groupId === undefined) assert.fail("groupId"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client1 = await getLoggedinDatabase(space1Id as number); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const client2 = await getLoggedinDatabase(space2Id as number); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const r1 = await client2.from("PlatformAccount").select("dg_account").eq("account_local_id", spaceAnonUserEmail("Roam", space2Id)).maybeSingle(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r1.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const memberId = r1.data?.dg_account; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert(!!memberId); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const r2 = await client1.from("group_membership").insert({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| group_id: groupId, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| member_id: memberId! | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert.equal(r2.error, null); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filter out null group_ids before deletion.
If
group_idcan be null in thegroup_membershiptable, this code will attempt to delete a user withid = null, which could cause an error or unexpected behavior.🛡️ Proposed fix to filter nulls
const r3 = await client.from("group_membership").select("group_id"); assert.equal(r3.error, null); - const groupIds = new Set((r3.data || []).map(({group_id})=>group_id)); + const groupIds = new Set((r3.data || []).map(({group_id})=>group_id).filter(id => id !== null)); for (const id of groupIds) { const ur = await client.auth.admin.deleteUser(id); assert.equal(ur.error, null); }📝 Committable suggestion
🤖 Prompt for AI Agents