forked from openfga/sdk-generator
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(js-sdk): add example js project (openfga#305)
- Loading branch information
Showing
5 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
all: run | ||
|
||
project_name=example1 | ||
openfga_version=latest | ||
|
||
setup: | ||
npm --prefix "${project_name}" install | ||
|
||
run: | ||
npm --prefix "${project_name}" run start | ||
|
||
run-openfga: | ||
docker pull docker.io/openfga/openfga:${openfga_version} && \ | ||
docker run -p 8080:8080 docker.io/openfga/openfga:${openfga_version} run |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
## Examples of using the OpenFGA JS SDK | ||
|
||
A set of Examples on how to call the OpenFGA JS SDK | ||
|
||
### Examples | ||
Example 1: | ||
A bare-bones example. It creates a store, and runs a set of calls against it including creating a model, writing tuples and checking for access. | ||
|
||
### Running the Examples | ||
|
||
Prerequisites: | ||
- `docker` | ||
- `make` | ||
- `Node.js` 16.13.0+ | ||
|
||
#### Run using a published SDK | ||
|
||
Steps | ||
1. Clone/Copy the example folder | ||
2. If you have an OpenFGA server running, you can use it, otherwise run `make run-openfga` to spin up an instance (you'll need to switch to a different terminal after - don't forget to close it when done) | ||
3. Run `make setup` to install dependencies | ||
4. Run `make run` to run the example | ||
|
||
#### Run using a local unpublished SDK build | ||
|
||
Steps | ||
1. Build the SDK | ||
2. In the Example `package.json` change the `@openfga/sdk` dependency from a semver range like below | ||
```json | ||
"dependencies": { | ||
"@openfga/sdk": "^{{packageVersion}}" | ||
} | ||
``` | ||
to a `file:` reference like below | ||
```json | ||
"dependencies": { | ||
"@openfga/sdk": "file:../../" | ||
} | ||
``` | ||
3. If you have an OpenFGA server running, you can use it, otherwise run `make run-openfga` to spin up an instance (you'll need to switch to a different terminal after - don't forget to close it when done) | ||
4. Run `make setup` to install dependencies | ||
5. Run `make run` to run the example |
213 changes: 213 additions & 0 deletions
213
config/clients/js/template/example/example1/example1.mjs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,213 @@ | ||
import { Credentials, CredentialsMethod, FgaApiValidationError, OpenFgaClient, TypeName } from "@openfga/sdk"; | ||
|
||
async function main () { | ||
let credentials; | ||
if (process.env.FGA_CLIENT_ID) { | ||
credentials = new Credentials({ | ||
method: CredentialsMethod.ClientCredentials, | ||
config: { | ||
clientId: process.env.FGA_CLIENT_ID, | ||
clientSecret: process.env.FGA_CLIENT_SECRET, | ||
apiAudience: process.env.FGA_API_AUDIENCE, | ||
apiTokenIssuer: process.env.FGA_API_TOKEN_ISSUER | ||
} | ||
}); | ||
} | ||
|
||
const fgaClient = new OpenFgaClient({ | ||
apiUrl: process.env.FGA_API_URL || "http://localhost:8080", | ||
storeId: process.env.FGA_STORE_ID, // not needed when calling `createStore` or `listStores` | ||
authorizationModelId: process.env.FGA_AUTHORIZATION_MODEL_ID, // optional, recommended for production, | ||
credentials | ||
}); | ||
|
||
console.log("Listing stores"); | ||
const initialStores = await fgaClient.listStores(); | ||
console.log(`Stores count: ${initialStores.stores.length}`); | ||
|
||
console.log("Creating Test Store"); | ||
const createdStore = await fgaClient.createStore({name: "Test Store"}); | ||
const store = createdStore; | ||
console.log(`Test Store ID: ${store.id}`); | ||
|
||
// Set the store ID | ||
fgaClient.storeId = store.id; | ||
|
||
console.log("Listing Stores"); | ||
const { stores } = await fgaClient.listStores(); | ||
console.log(`Stores count: ${stores.length}`); | ||
|
||
console.log("Getting Current Store"); | ||
const currentStore = await fgaClient.getStore(); | ||
console.log(`Current Store Name ${currentStore.name}`); | ||
|
||
console.log("Reading Authorization Models"); | ||
const { authorization_models } = await fgaClient.readAuthorizationModels(); | ||
console.log(`Models Count: ${authorization_models.length}`); | ||
|
||
console.log("Reading Latest Authorization Model"); | ||
const { authorization_model } = await fgaClient.readLatestAuthorizationModel(); | ||
if (authorization_model) { | ||
console.log(`Latest Authorization Model ID: ${latestModel.authorization_model.id}`); | ||
} else { | ||
console.log("Latest Authorization Model not found"); | ||
} | ||
|
||
console.log("Writing an Authorization Model"); | ||
const model = await fgaClient.writeAuthorizationModel({ | ||
schema_version: "1.1", | ||
type_definitions: [ | ||
{ | ||
type: "user" | ||
}, | ||
{ | ||
type: "document", | ||
relations: { | ||
writer: { this: {} }, | ||
viewer: { | ||
union: { | ||
child: [ | ||
{ this: {} }, | ||
{ | ||
computedUserset: { | ||
relation: "writer" | ||
} | ||
} | ||
] | ||
} | ||
} | ||
}, | ||
metadata: { | ||
relations: { | ||
writer: { | ||
directly_related_user_types: [ | ||
{ type: "user" }, | ||
{ type: "user", condition: "ViewCountLessThan200" } | ||
] | ||
}, | ||
viewer: { | ||
directly_related_user_types: [ | ||
{ type: "user" } | ||
] | ||
} | ||
} | ||
} | ||
}, | ||
], | ||
conditions: { | ||
"ViewCountLessThan200": { | ||
name: "ViewCountLessThan200", | ||
expression: "ViewCount < 200", | ||
parameters: { | ||
ViewCount: { | ||
type_name: TypeName.Int | ||
}, | ||
Type: { | ||
type_name: TypeName.String | ||
}, | ||
Name: { | ||
type_name: TypeName.String | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
const authorizationModelId = model.authorization_model_id; | ||
console.log(`Authorization Model ID: ${authorizationModelId}`); | ||
|
||
console.log("Reading Authorization Models"); | ||
const models = await fgaClient.readAuthorizationModels(); | ||
console.log(`Models Count: ${models.authorization_models.length}`); | ||
|
||
console.log("Reading Latest Authorization Model"); | ||
const latestModel = await fgaClient.readLatestAuthorizationModel(); | ||
console.log(`Latest Authorization Model ID: ${latestModel.authorization_model.id}`); | ||
|
||
console.log("Writing Tuples"); | ||
await fgaClient.write({ | ||
writes: [ | ||
{ | ||
user: "user:anne", | ||
relation: "writer", | ||
object: "document:roadmap", | ||
condition: { | ||
name: "ViewCountLessThan200", | ||
context: { | ||
Name: "Roadmap", | ||
Type: "document" | ||
} | ||
} | ||
} | ||
] | ||
}, { authorizationModelId }); | ||
console.log("Done Writing Tuples"); | ||
|
||
// Set the model ID | ||
fgaClient.authorizationModelId = authorizationModelId; | ||
|
||
console.log("Reading Tuples"); | ||
const { tuples } = await fgaClient.read(); | ||
console.log(`Read Tuples: ${JSON.stringify(tuples)}`); | ||
|
||
console.log("Reading Tuple Changes"); | ||
const { changes } = await fgaClient.readChanges(); | ||
console.log(`Tuple Changes: ${JSON.stringify(changes)}`); | ||
|
||
console.log("Checking for access"); | ||
try { | ||
const { allowed } = await fgaClient.check({ | ||
user: "user:anne", | ||
relation: "viewer", | ||
object: "document:roadmap" | ||
}); | ||
console.log(`Allowed: ${allowed}`); | ||
} catch (error) { | ||
if (error instanceof FgaApiValidationError) { | ||
console.log(`Failed due to ${error.apiErrorMessage}`); | ||
} else { | ||
throw error; | ||
} | ||
} | ||
|
||
console.log("Checking for access with context"); | ||
const { allowed } = await fgaClient.check({ | ||
user: "user:anne", | ||
relation: "viewer", | ||
object: "document:roadmap", | ||
context: { | ||
ViewCount: 100 | ||
} | ||
}); | ||
console.log(`Allowed: ${allowed}`); | ||
|
||
console.log("Writing Assertions"); | ||
await fgaClient.writeAssertions([ | ||
{ | ||
user: "user:carl", | ||
relation: "writer", | ||
object: "document:budget", | ||
expectation: true | ||
}, | ||
{ | ||
user: "user:carl", | ||
relation: "writer", | ||
object: "document:roadmap", | ||
expectation: false | ||
} | ||
]); | ||
console.log("Assertions Updated"); | ||
|
||
console.log("Reading Assertions"); | ||
const { assertions} = await fgaClient.readAssertions(); | ||
console.log(`Assertions: ${JSON.stringify(assertions)}`); | ||
|
||
console.log("Deleting Current Store"); | ||
await fgaClient.deleteStore(); | ||
console.log(`Deleted Store Count: ${store.id}`); | ||
} | ||
|
||
main() | ||
.catch(error => { | ||
console.error(`error: ${error}`); | ||
process.exitCode = 1; | ||
}); |
17 changes: 17 additions & 0 deletions
17
config/clients/js/template/example/example1/package.json.mustache
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
{ | ||
"name": "example1", | ||
"private": "true", | ||
"version": "1.0.0", | ||
"description": "A bare bones example of using the OpenFGA SDK", | ||
"author": "OpenFGA", | ||
"license": "Apache-2.0", | ||
"scripts": { | ||
"start": "node example1.mjs" | ||
}, | ||
"dependencies": { | ||
"@openfga/sdk": "^{{packageVersion}}" | ||
}, | ||
"engines": { | ||
"node": ">=16.13.0" | ||
} | ||
} |