Skip to content

Commit

Permalink
[fga] check workspace relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
svenefftinge committed Sep 25, 2023
1 parent f690f87 commit 1c99024
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 22 deletions.
57 changes: 45 additions & 12 deletions components/server/src/authorization/authorizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -416,21 +416,54 @@ export class Authorizer {
if (!(await isFgaWritesEnabled(userID))) {
return;
}
return this.bulkAddWorkspaceToOrg([{ orgID, userID, workspaceID, shared }]);
}

async bulkAddWorkspaceToOrg(
ids: { orgID: string; userID: string; workspaceID: string; shared: boolean }[],
): Promise<void> {
const rels: v1.RelationshipUpdate[] = [];
for (const { orgID, userID, workspaceID, shared } of ids) {
rels.push(set(rel.workspace(workspaceID).org.organization(orgID)));
rels.push(set(rel.workspace(workspaceID).owner.user(userID)));
if (shared) {
rels.push(set(rel.workspace(workspaceID).shared.anyUser));
}
rels.push(set(rel.workspace(workspaceID).org.organization(orgID)));
rels.push(set(rel.workspace(workspaceID).owner.user(userID)));
if (shared) {
rels.push(set(rel.workspace(workspaceID).shared.anyUser));
}
await this.authorizer.writeRelationships(...rels);

//TODO(se) remove this double checking once we're confident that the above works
// check if the relationships were written
try {
const wsToOrgRel = this.find(rel.workspace(workspaceID).org.organization(orgID));
const wsToOwnerRel = this.find(rel.workspace(workspaceID).owner.user(userID));
const wsSharedRel = shared ? this.find(rel.workspace(workspaceID).shared.anyUser) : Promise.resolve(true);
if (!(await wsToOrgRel)) {
log.error("Failed to write workspace to org relationship", {
orgID,
userID,
workspaceID,

shared,
});
}
if (!(await wsToOwnerRel)) {
log.error("Failed to write workspace to owner relationship", {
orgID,
userID,
workspaceID,
shared,
});
}
if (!(await wsSharedRel)) {
log.error("Failed to write workspace shared relationship", {
orgID,
userID,
workspaceID,
shared,
});
}
} catch (error) {
log.error("Failed to check workspace relationships", {
orgID,
userID,
workspaceID,
shared,
error,
});
}
}

async removeWorkspaceFromOrg(orgID: string, userID: string, workspaceID: string): Promise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ describe("RelationshipUpdater", async () => {
it("should create relationships for all user workspaces", async function () {
const user = await userDB.newUser();
const org = await orgDB.createTeam(user.id, "MyOrg");
const totalWorkspaces = 20;
const totalWorkspaces = 50;
const expectedWorkspaces: Workspace[] = [];
for (let i = 0; i < totalWorkspaces; i++) {
const workspace = await workspaceDB.store({
Expand Down
22 changes: 13 additions & 9 deletions components/server/src/authorization/relationship-updater.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { rel } from "./definitions";

@injectable()
export class RelationshipUpdater {
public static readonly version = 2;
public static readonly version = 3;

constructor(
@inject(UserDB) private readonly userDB: UserDB,
Expand Down Expand Up @@ -155,14 +155,18 @@ export class RelationshipUpdater {
limit: 500, // The largest amount of workspaces is 189 today (2023-08-24)
});

await this.authorizer.bulkAddWorkspaceToOrg(
workspaces.map((ws) => ({
orgID: ws.workspace.organizationId,
userID: ws.workspace.ownerId,
workspaceID: ws.workspace.id,
shared: !!ws.workspace.shareable,
})),
);
for (const ws of workspaces) {
await this.authorizer
.addWorkspaceToOrg(
ws.workspace.organizationId,
ws.workspace.ownerId,
ws.workspace.id,
!!ws.workspace.shareable,
)
.catch((err) => {
log.error({ userId: user.id, workspaceId: ws.workspace.id }, "Failed to update workspace", err);
});
}
}

private async updateUser(user: User): Promise<void> {
Expand Down

0 comments on commit 1c99024

Please sign in to comment.