Skip to content

Commit

Permalink
fix(js-sdk): set the consistency parameter correctly in OpenFGAClient
Browse files Browse the repository at this point in the history
  • Loading branch information
ewanharris committed Aug 23, 2024
1 parent 2aa0771 commit a785145
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 26 deletions.
7 changes: 6 additions & 1 deletion config/clients/js/template/client.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,7 @@ export class {{appShortName}}Client extends BaseAPI {
const readRequest: ReadRequest = {
page_size: options.pageSize,
continuation_token: options.continuationToken,
consistency: options.consistency
};
if (body.user || body.object || body.relation) {
readRequest.tuple_key = body;
Expand Down Expand Up @@ -569,7 +570,8 @@ export class {{appShortName}}Client extends BaseAPI {
},
context: body.context,
contextual_tuples: { tuple_keys: body.contextualTuples || [] },
authorization_model_id: this.getAuthorizationModelId(options)
authorization_model_id: this.getAuthorizationModelId(options),
consistency: options.consistency
}, options);
}

Expand Down Expand Up @@ -630,6 +632,7 @@ export class {{appShortName}}Client extends BaseAPI {
return this.api.expand(this.getStoreId(options)!, {
authorization_model_id: this.getAuthorizationModelId(options),
tuple_key: body,
consistency: options.consistency
}, options);
}

Expand All @@ -652,6 +655,7 @@ export class {{appShortName}}Client extends BaseAPI {
type: body.type,
context: body.context,
contextual_tuples: { tuple_keys: body.contextualTuples || [] },
consistency: options.consistency
}, options);
}

Expand Down Expand Up @@ -710,6 +714,7 @@ export class {{appShortName}}Client extends BaseAPI {
user_filters: body.user_filters,
context: body.context,
contextual_tuples: body.contextualTuples || [],
consistency: options.consistency
}, options);
}

Expand Down
39 changes: 21 additions & 18 deletions config/clients/js/template/tests/client.test.ts.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
FgaValidationError,
{{appShortName}}Client,
ListUsersResponse,
ConsistencyPreference,
} from "../index";
import { baseConfig, defaultConfiguration, getNocks } from "./helpers";

Expand Down Expand Up @@ -280,10 +281,10 @@ describe("{{appTitleCaseName}} Client", () => {
relation: "admin",
object: "workspace:1",
};
const scope = nocks.read(baseConfig.storeId!, tuple);
const scope = nocks.read(baseConfig.storeId!, tuple, undefined, ConsistencyPreference.HigherConsistency);

expect(scope.isDone()).toBe(false);
const data = await fgaClient.read(tuple);
const data = await fgaClient.read(tuple, { consistency: ConsistencyPreference.HigherConsistency});

expect(scope.isDone()).toBe(true);
expect(data).toMatchObject({});
Expand Down Expand Up @@ -487,10 +488,10 @@ describe("{{appTitleCaseName}} Client", () => {
relation: "admin",
object: "workspace:1",
};
const scope = nocks.check(baseConfig.storeId!, tuple);
const scope = nocks.check(baseConfig.storeId!, tuple, undefined, undefined, undefined, ConsistencyPreference.HigherConsistency);

expect(scope.isDone()).toBe(false);
const data = await fgaClient.check(tuple);
const data = await fgaClient.check(tuple, { consistency: ConsistencyPreference.HigherConsistency });

expect(scope.isDone()).toBe(true);
expect(data).toMatchObject({ allowed: expect.any(Boolean) });
Expand All @@ -512,12 +513,12 @@ describe("{{appTitleCaseName}} Client", () => {
relation: "reader",
object: "workspace:3",
}];
const scope0 = nocks.check(defaultConfiguration.storeId!, tuples[0], defaultConfiguration.getBasePath(), { allowed: true }, 200).matchHeader("{{clientMethodHeader}}", "BatchCheck");
const scope1 = nocks.check(defaultConfiguration.storeId!, tuples[1], defaultConfiguration.getBasePath(), { allowed: false }, 200).matchHeader("{{clientMethodHeader}}", "BatchCheck");
const scope0 = nocks.check(defaultConfiguration.storeId!, tuples[0], defaultConfiguration.getBasePath(), { allowed: true }, 200, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "BatchCheck");
const scope1 = nocks.check(defaultConfiguration.storeId!, tuples[1], defaultConfiguration.getBasePath(), { allowed: false }, 200, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "BatchCheck");
const scope2 = nocks.check(defaultConfiguration.storeId!, tuples[2], defaultConfiguration.getBasePath(), {
"code": "validation_error",
"message": "relation 'workspace#reader' not found"
}, 400).matchHeader("{{clientMethodHeader}}", "BatchCheck");
}, 400, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "BatchCheck");
const scope3 = nock(defaultConfiguration.getBasePath())
.get(`/stores/${defaultConfiguration.storeId!}/authorization-models`)
.query({ page_size: 1 })
Expand All @@ -528,7 +529,7 @@ describe("{{appTitleCaseName}} Client", () => {
expect(scope0.isDone()).toBe(false);
expect(scope1.isDone()).toBe(false);
expect(scope2.isDone()).toBe(false);
const response = await fgaClient.batchCheck([tuples[0], tuples[1], tuples[2]]);
const response = await fgaClient.batchCheck([tuples[0], tuples[1], tuples[2]], { consistency: ConsistencyPreference.HigherConsistency });

expect(scope0.isDone()).toBe(true);
expect(scope1.isDone()).toBe(true);
Expand All @@ -551,10 +552,10 @@ describe("{{appTitleCaseName}} Client", () => {
relation: "admin",
object: "workspace:1",
};
const scope = nocks.expand(baseConfig.storeId!, tuple);
const scope = nocks.expand(baseConfig.storeId!, tuple, undefined, ConsistencyPreference.HigherConsistency);

expect(scope.isDone()).toBe(false);
const data = await fgaClient.expand(tuple, { authorizationModelId: "01GXSA8YR785C4FYS3C0RTG7B1" });
const data = await fgaClient.expand(tuple, { authorizationModelId: "01GXSA8YR785C4FYS3C0RTG7B1", consistency: ConsistencyPreference.HigherConsistency });

expect(scope.isDone()).toBe(true);
expect(data).toMatchObject({});
Expand All @@ -564,7 +565,7 @@ describe("{{appTitleCaseName}} Client", () => {
describe("ListObjects", () => {
it("should call the api and return the response", async () => {
const mockedResponse = { objects: ["document:roadmap"] };
const scope = nocks.listObjects(baseConfig.storeId!, mockedResponse);
const scope = nocks.listObjects(baseConfig.storeId!, mockedResponse, undefined, ConsistencyPreference.HigherConsistency);

expect(scope.isDone()).toBe(false);
const response = await fgaClient.listObjects({
Expand All @@ -583,6 +584,7 @@ describe("{{appTitleCaseName}} Client", () => {
}]
}, {
authorizationModelId: "01GAHCE4YVKPQEKZQHT2R89MQV",
consistency: ConsistencyPreference.HigherConsistency,
});

expect(scope.isDone()).toBe(true);
Expand Down Expand Up @@ -614,11 +616,11 @@ describe("{{appTitleCaseName}} Client", () => {
relation: "can_read",
object: "workspace:1",
}];
const scope0 = nocks.check(defaultConfiguration.storeId!, tuples[0], defaultConfiguration.getBasePath(), { allowed: true }).matchHeader("{{clientMethodHeader}}", "ListRelations");
const scope1 = nocks.check(defaultConfiguration.storeId!, tuples[1], defaultConfiguration.getBasePath(), { allowed: false }).matchHeader("{{clientMethodHeader}}", "ListRelations");
const scope2 = nocks.check(defaultConfiguration.storeId!, tuples[2], defaultConfiguration.getBasePath(), { allowed: true }).matchHeader("{{clientMethodHeader}}", "ListRelations");
const scope3 = nocks.check(defaultConfiguration.storeId!, tuples[3], defaultConfiguration.getBasePath(), { allowed: false }).matchHeader("{{clientMethodHeader}}", "ListRelations");
const scope4 = nocks.check(defaultConfiguration.storeId!, tuples[4], defaultConfiguration.getBasePath(), { allowed: false }).matchHeader("{{clientMethodHeader}}", "ListRelations");
const scope0 = nocks.check(defaultConfiguration.storeId!, tuples[0], defaultConfiguration.getBasePath(), { allowed: true }, undefined, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "ListRelations");
const scope1 = nocks.check(defaultConfiguration.storeId!, tuples[1], defaultConfiguration.getBasePath(), { allowed: false }, undefined, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "ListRelations");
const scope2 = nocks.check(defaultConfiguration.storeId!, tuples[2], defaultConfiguration.getBasePath(), { allowed: true }, undefined, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "ListRelations");
const scope3 = nocks.check(defaultConfiguration.storeId!, tuples[3], defaultConfiguration.getBasePath(), { allowed: false }, undefined, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "ListRelations");
const scope4 = nocks.check(defaultConfiguration.storeId!, tuples[4], defaultConfiguration.getBasePath(), { allowed: false }, undefined, ConsistencyPreference.HigherConsistency).matchHeader("X-OpenFGA-Client-Method", "ListRelations");
const scope5 = nock(defaultConfiguration.getBasePath())
.get(`/stores/${defaultConfiguration.storeId!}/authorization-models`)
.query({ page_size: 1 })
Expand All @@ -636,7 +638,7 @@ describe("{{appTitleCaseName}} Client", () => {
user: "user:81684243-9356-4421-8fbf-a4f8d36aa31b",
object: "workspace:1",
relations: ["admin", "guest", "reader", "viewer"],
});
}, { consistency: ConsistencyPreference.HigherConsistency });

expect(scope0.isDone()).toBe(true);
expect(scope1.isDone()).toBe(true);
Expand Down Expand Up @@ -771,7 +773,7 @@ describe("{{appTitleCaseName}} Client", () => {
}
}]
};
const scope = nocks.listUsers(baseConfig.storeId!, mockedResponse);
const scope = nocks.listUsers(baseConfig.storeId!, mockedResponse, undefined, ConsistencyPreference.HigherConsistency);

expect(scope.isDone()).toBe(false);
const response = await fgaClient.listUsers({
Expand Down Expand Up @@ -799,6 +801,7 @@ describe("{{appTitleCaseName}} Client", () => {
}]
}, {
authorizationModelId: "01GAHCE4YVKPQEKZQHT2R89MQV",
consistency: ConsistencyPreference.HigherConsistency
});

expect(scope.isDone()).toBe(true);
Expand Down
40 changes: 33 additions & 7 deletions config/clients/js/template/tests/helpers/nocks.ts.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import {
AuthorizationModel,
CheckRequest,
CheckResponse,
ConsistencyPreference,
CreateStoreResponse,
ExpandRequest,
ExpandResponse,
GetStoreResponse,
ListObjectsResponse,
ListStoresResponse,
ListUsersRequest,
ListUsersResponse,
ReadAssertionsResponse,
ReadAuthorizationModelResponse,
ReadAuthorizationModelsResponse,
ReadChangesResponse,
ReadRequest,
ReadResponse,
TupleKey,
TupleOperation,
Expand Down Expand Up @@ -153,9 +157,12 @@ export const getNocks = ((nock: typeof Nock) => ({
storeId: string,
tuple: TupleKey,
basePath = defaultConfiguration.getBasePath(),
consistency: ConsistencyPreference|undefined = undefined,
) => {
return nock(basePath)
.post(`/stores/${storeId}/read`)
.post(`/stores/${storeId}/read`, (body: ReadRequest) =>
body.consistency === consistency
)
.reply(200, { tuples: [], continuation_token: "" } as ReadResponse);
},
write: (
Expand Down Expand Up @@ -183,32 +190,51 @@ export const getNocks = ((nock: typeof Nock) => ({
basePath = defaultConfiguration.getBasePath(),
response: { allowed: boolean } | { code: string, message: string } = { allowed: true },
statusCode = 200,
consistency: ConsistencyPreference|undefined = undefined,
) => {
return nock(basePath)
.post(`/stores/${storeId}/check`, (body: CheckRequest) =>
body.tuple_key.user === tuple.user &&
body.tuple_key.relation === tuple.relation &&
body.tuple_key.object === tuple.object
body.tuple_key.object === tuple.object &&
body.consistency === consistency
)
.reply(statusCode, response as CheckResponse);
},
expand: (
storeId: string,
tuple: TupleKey,
basePath = defaultConfiguration.getBasePath(),
consistency: ConsistencyPreference|undefined = undefined,
) => {
return nock(basePath)
.post(`/stores/${storeId}/expand`)
.post(`/stores/${storeId}/expand`, (body: ExpandRequest) =>
body.consistency === consistency
)
.reply(200, { tree: {} } as ExpandResponse);
},
listObjects: (storeId: string, responseBody: ListObjectsResponse, basePath = defaultConfiguration.getBasePath()) => {
listObjects: (
storeId: string,
responseBody: ListObjectsResponse,
basePath = defaultConfiguration.getBasePath(),
consistency: ConsistencyPreference|undefined = undefined,
) => {
return nock(basePath)
.post(`/stores/${storeId}/list-objects`)
.post(`/stores/${storeId}/list-objects`, (body: ListUsersRequest) =>
body.consistency === consistency
)
.reply(200, responseBody);
},
listUsers: (storeId: string, responseBody: ListUsersResponse, basePath = defaultConfiguration.getBasePath()) => {
listUsers: (
storeId: string,
responseBody: ListUsersResponse,
basePath = defaultConfiguration.getBasePath(),
consistency: ConsistencyPreference|undefined = undefined
) => {
return nock(basePath)
.post(`/stores/${storeId}/list-users`)
.post(`/stores/${storeId}/list-users`, (body: ListUsersRequest) =>
body.consistency === consistency
)
.reply(200, responseBody);
},
readAssertions: (storeId: string, modelId: string, assertions: ReadAssertionsResponse["assertions"] = [], basePath = defaultConfiguration.getBasePath()) => {
Expand Down

0 comments on commit a785145

Please sign in to comment.