Coder Social home page Coder Social logo

openfga / python-sdk Goto Github PK

View Code? Open in Web Editor NEW
35.0 15.0 11.0 889 KB

OpenFGA SDK for Python 3 - https://pypi.org/project/openfga-sdk/

Home Page: https://openfga.dev

License: Apache License 2.0

Python 99.98% Makefile 0.02%
access-control authorization fga security zanzibar fine-grained-authorization openfga

python-sdk's Introduction

OpenFGA

Go Reference GitHub release (latest SemVer) Docker Pulls Codecov Go Report CII Best Practices Join our community Twitter FOSSA Status Artifact HUB OpenSSF Scorecard SLSA 3

A high-performance and flexible authorization/permission engine built for developers and inspired by Google Zanzibar.

OpenFGA is designed to make it easy for developers to model their application permissions and add and integrate fine-grained authorization into their applications.

It allows in-memory data storage for quick development, as well as pluggable database modules. It currently supports PostgreSQL 14, MySQL 8 and SQLite (currently in beta).

It offers an HTTP API and a gRPC API. It has SDKs for Java, Node.js/JavaScript, GoLang, Python and .NET. Look in our Community section for third-party SDKs and tools. It can also be used as a library.

Getting Started

The following section aims to help you get started quickly. Please look at our official documentation for in-depth information.

Setup and Installation

ℹī¸ The following sections setup an OpenFGA server using the default configuration values. These are for rapid development and not for a production environment. Data written to an OpenFGA instance using the default configuration with the memory storage engine will not persist after the service is stopped.

For more information on how to configure the OpenFGA server, please take a look at our official documentation on Running in Production.

Docker

OpenFGA is available on Dockerhub, so you can quickly start it using the in-memory datastore by running the following commands:

docker pull openfga/openfga
docker run -p 8080:8080 -p 3000:3000 openfga/openfga run

Tip

The OPENFGA_HTTP_ADDR environment variable can used to configure the address at which the playground expects the OpenFGA server to be. For example, docker run -e OPENFGA_PLAYGROUND_ENABLED=true -e OPENFGA_HTTP_ADDR=0.0.0.0:4000 -p 4000:4000 -p 3000:3000 openfga/openfga run will start the OpenFGA server on port 4000, and configure the playground too.

Docker Compose

docker-compose.yaml provides an example of how to launch OpenFGA with Postgres using docker compose.

  1. First, either clone this repo or curl the docker-compose.yaml file with the following command:

    curl -LO https://openfga.dev/docker-compose.yaml
  2. Then, run the following command:

    docker compose up

Package Managers

If you are a Homebrew user, you can install OpenFGA with the following command:

brew install openfga

Pre-compiled Binaries

Download your platform's latest release and extract it. Then run the binary with the command:

./openfga run

Building from Source

There are two recommended options for building OpenFGA from source code:

Building from source with go install

Make sure you have Go 1.20 or later installed. See the Go downloads page.

You can install from source using Go modules:

  1. First, make sure $GOBIN is on your shell $PATH:

    export PATH=$PATH:$(go env GOBIN)
  2. Then use the install command:

    go install github.com/openfga/openfga/cmd/openfga
  3. Run the server with:

    ./openfga run

Building from source with go build

Alternatively you can build OpenFGA by cloning the project from this Github repo, and then building it with the go build command:

  1. Clone the repo to a local directory, and navigate to that directory:

    git clone https://github.com/openfga/openfga.git && cd openfga
  2. Then use the build command:

    go build -o ./openfga ./cmd/openfga
  3. Run the server with:

    ./openfga run

Verifying the Installation

Now that you have Set up and Installed OpenFGA, you can test your installation by creating an OpenFGA Store.

curl -X POST 'localhost:8080/stores' \
--header 'Content-Type: application/json' \
--data-raw '{
    "name": "openfga-demo"
}'

If everything is running correctly, you should get a response with information about the newly created store, for example:

{
  "id": "01G3EMTKQRKJ93PFVDA1SJHWD2",
  "name": "openfga-demo",
  "created_at": "2022-05-19T17:11:12.888680Z",
  "updated_at": "2022-05-19T17:11:12.888680Z"
}

Playground

The Playground facilitates rapid development by allowing you to visualize and model your application's authorization model(s) and manage relationship tuples with a locally running OpenFGA instance.

To run OpenFGA with the Playground disabled, provide the --playground-enabled=false flag.

./openfga run --playground-enabled=false

Once OpenFGA is running, by default, the Playground can be accessed at http://localhost:3000/playground.

In the event that a port other than the default port is required, the --playground-port flag can be set to change it. For example,

./openfga run --playground-enabled --playground-port 3001

Profiler (pprof)

Profiling through pprof can be enabled on the OpenFGA server by providing the --profiler-enabled flag.

./openfga run --profiler-enabled

This will start serving profiling data on port 3001. You can see that data by visiting http://localhost:3001/debug/pprof.

If you need to serve the profiler on a different address, you can do so by specifying the --profiler-addr flag. For example,

./openfga run --profiler-enabled --profiler-addr :3002

Once the OpenFGA server is running, in another window you can run the following command to generate a compressed CPU profile:

go tool pprof -proto -seconds 60 http://localhost:3001/debug/pprof/profile
# will collect data for 60 seconds and generate a file like pprof.samples.cpu.001.pb.gz

That file can be analyzed visually by running the following command and then visiting http://localhost:8084:

go tool pprof -http=localhost:8084 pprof.samples.cpu.001.pb.gz

Next Steps

Take a look at examples of how to:

Don't hesitate to browse the official Documentation, API Reference.

Limitations

MySQL Storage engine

The MySQL storage engine has a lower length limit for some properties of a tuple compared with other storage backends. For more information see the docs.

OpenFGA's MySQL Storage Adapter was contributed to OpenFGA by @twintag. Thanks!

Production Readiness

The core OpenFGA service has been in use by Okta FGA in production since December 2021.

OpenFGA's Memory Storage Adapter was built for development purposes only, is not optimized for performance, and is not recommended for a production environment.

You can learn about more organizations using OpenFGA in production here. If your organization is using OpenFGA in production please consider adding it to the list.

The OpenFGA team will do its best to address all production issues with high priority.

Contributing

See CONTRIBUTING.

Community Meetings

We hold a monthly meeting to interact with the community, collaborate and receive/provide feedback. You can find more details, including the time, our agenda, and the meeting minutes here.

python-sdk's People

Contributors

aaguiarz avatar adriantam avatar akj2018 avatar booniepepper avatar dependabot[bot] avatar evansims avatar ewanharris avatar gilion-joel-b avatar harshal662 avatar jimmyjames avatar jpadilla avatar jrudransh avatar kimgault avatar meldsza avatar rhamzeh avatar snyk-bot avatar tjtanjin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python-sdk's Issues

`list_users` should accept a `FgaObject` type for the `users` parameter

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

Currently we accept a str for the users parameter in list_users this should be of type FgaObject

Expectation

The list_users call should accept FgaObject and look like below

        response = await fga_client.list_users(
            ClientListUsersRequest(
                object=FgaObject(type="document",id="roadmap"),
                relation="viewer",
                user_filters=[
                    UserTypeFilter(type="user")
                ],
                context=dict(ViewCount=100),
            )
        )

Reproduction

  1. Call the list_users endpoint
  2. The API call will fail

OpenFGA SDK version

v0.4.3

OpenFGA version

v1.5.4

SDK Configuration

Using the example

Logs

No response

References

No response

`TupleKey` should support `relation=None`

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

The docs describe how to use the read() method with a TupleKey with no relation set to get a list of all relations a user has with an object. Currently the TupleKey object validation prevents the relation from being None.

Expectation

Not to throw an error when omitting relation or setting to None.

Reproduction

Essentially the code from the docs:

body = TupleKey(
            user="user:bob",
            object="document:123",

)

Working around the validation and submitting the query confirms the behavior describes from the docs (i.e., listing the relations) works as expected:

Issuing a query with a workaround:

body = TupleKey(
            user="user:bob",
            relation="",
            object="document:123",

)
body._relation = None

# call `read(body)` ...

OpenFGA SDK version

0.4.0 (but the code in main appears broken)

OpenFGA version

v1.5.0

SDK Configuration

[default options]

Logs

No response

References

No response

OpenTelemetry instrumentation

Checklist

Describe the problem you'd like to have solved

Given how important is to keep authorization performant, it'd be great if the sdk was instrumented so one could see traces of authorization calls, checks, writes, etc.

Describe the ideal solution

Instrument the sdk with OpenTelemetry

Alternatives and current workarounds

Write a custom instrumentation relying on monkey-patching techniques or instrument at the application level.

References

https://github.com/open-telemetry/opentelemetry-python

Additional context

No response

Styling: standard library should be imported before custom library

Currently, the client/client.py imports custom libraries before the standard libraries as per PEP 8 style. The order should be

  1. Standard library imports.
  2. Related third party imports.
  3. Local application/library specific imports.

Furthermore, it may be good to have clean up the import so that we only import what is needed (#23).

Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. The corresponding SDK generator issue is openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/openfga_sdk/client/client.py will help us as well.

Styling: README should import only the class and method instead of entire module

Currently, the (README file)[https://github.com/openfga/python-sdk/blob/main/README.md] suggests importing openfga_sdk as a whole. For example, we have import openfga_sdk.

This is contrary to best practice in that only the relevant classes/methods should be imported. Instead, we should do something like

from openfga_sdk import ClientConfiguration

This will also require updating the example so that it does not have the prefix openfga_sdk.

As an example,

import openfga_sdk
from openfga_sdk.client import OpenFgaClient


async def main():
    configuration = openfga_sdk.ClientConfiguration(
        api_scheme = OPENFGA_API_SCHEME, # optional, defaults to "https"
        api_host = OPENFGA_API_HOST, # required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
        store_id = OPENFGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores`
        authorization_model_id = OPENFGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request
    )
    # Enter a context with an instance of the OpenFgaClient
    async with OpenFgaClient(configuration) as fga_client:
        api_response = await fga_client.read_authorization_models()
        await fga_client.close()

should become

from openfga_sdk import ClientConfiguration
from openfga_sdk.client import OpenFgaClient


async def main():
    configuration = ClientConfiguration(
        api_scheme = OPENFGA_API_SCHEME, # optional, defaults to "https"
        api_host = OPENFGA_API_HOST, # required, define without the scheme (e.g. api.fga.example instead of https://api.fga.example)
        store_id = OPENFGA_STORE_ID, # optional, not needed when calling `CreateStore` or `ListStores`
        authorization_model_id = OPENFGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request
    )
    # Enter a context with an instance of the OpenFgaClient
    async with OpenFgaClient(configuration) as fga_client:
        api_response = await fga_client.read_authorization_models()
        await fga_client.close()

Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

Export metrics

Checklist

Describe the problem you'd like to have solved

As a consumer of the SDK, I would like to hook it to my dashboards to get data on several metrics.

Describe the ideal solution

Integrate the OpenTelemetry Python API https://github.com/open-telemetry/opentelemetry-python/tree/main/opentelemetry-api (API docs)

Expose only from the inner OpenFgaApi. We need to be able to report the following metrics

Metric Name Type Description
fga-client.request.duration Histogram The total request time for FGA requests
fga-client.query.duration Histogram The amount of time the FGA server took to process the request
fga-client.credentials.request Counter The total number of times a new token was requested when using ClientCredentials

And the metrics should have the following attributes associated with them

Attribute Name Type Description
fga-client.response.model_id string The authorization model ID that the FGA server used
fga-client.request.method string The FGA method/action that was performed
fga-client.request.store_id string The store ID that was sent as part of the request
fga-client.request.model_id string The authorization model ID that was sent as part of the request, if any
fga-client.request.client_id string The client ID associated with the request, if any
fga-client.user string The user that is associated with the action of the request for check and list users
http.status_code int The status code of the response
http.method string The HTTP method for the request
http.host string Host identifier of the origin the request was sent to

We should create an overall meter for OpenFgaApi and then create counters, histograms as required for each metric we report.

For the semantically named attributes we can use the semantic conventions package https://pypi.org/project/opentelemetry-semantic-conventions/

Fix README on pypi

We published v0.0.1, but it does not have the proper README in the published package - we should fix that.

e.g.

from setuptools import setup

# read the contents of your README file
from pathlib import Path
this_directory = Path(__file__).parent
long_description = (this_directory / "README.md").read_text()

setup(
    name='an_example_package',
    # other arguments omitted
    long_description=long_description,
    long_description_content_type='text/markdown'
)

https://packaging.python.org/en/latest/guides/making-a-pypi-friendly-readme/

Read and write using different tuple models

Checklist

Describe the problem you'd like to have solved

I added the SDK to our backend yesterday and found that there are two different models being used when reading from the store and writing to the store.

from openfga_sdk import ReadRequestTupleKey, Tuple as FgaTuple
from openfga_sdk.client.models import ClientTuple

What's the reason for this? It would just save us some code to convert between them and make things cleaner with a single model/source of truth in the backend.

Thanks!

Describe the ideal solution

Read and write uses the same model for tuples

Alternatives and current workarounds

Cast in between them when reading, altering, and writing back to the store.

References

No response

Additional context

No response

README: add import and client initialization as comments for each code block

In the SDK README, for each code block examples, it will be helpful if

  • import modules are noted as comments
  • client initialization are noted as comments

For example,

body = CreateStoreRequest(
    name = "FGA Demo Store",
)
response = await fga_client.create_store(body)
# response.id = "01FQH7V8BEG3GPQW93KTRFR8JB"

should be

#from openfga_sdk.client import OpenFgaClient
#from openfga_sdk.models.create_store_request import CreateStoreRequest

# initialize fga_client
body = CreateStoreRequest(
    name = "FGA Demo Store",
)
response = await fga_client.create_store(body)
# response.id = "01FQH7V8BEG3GPQW93KTRFR8JB"

We want to do this for the examples listed in https://github.com/openfga/python-sdk/blob/main/README.md. Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

README: break up WriteAuthorizationModelRequest into smaller understandable pieces

Currently, the WriteAuthorizationModelRequest object used for (write authorization model)[https://github.com/openfga/python-sdk/blob/main/README.md#write-authorization-model] is large and difficult to understand. Ideally, we want to break it apart into smaller pieces

For example,

body = WriteAuthorizationModelRequest(
    schema_version = "1.1",
    type_definitions=[
        TypeDefinition(
            type="user",
        ),
        TypeDefinition(
            type="document",
            relations=dict(
                writer=Userset(
                    this=dict(),
                ),
                viewer=Userset(
                    union=Usersets(
                        child=[
                            Userset(this=dict()),
                            Userset(computed_userset=ObjectRelation(
                                object="",
                                relation="writer",
                            )),
                        ],
                    ),
                ),
            )
        ),
    ],
)

can be broken up as

user_type =  TypeDefinition(
    type="user",
)
document_type = TypeDefinition(
    type="document",
    relations=dict(
        writer=Userset(
            this=dict(),
        ),
        viewer=Userset(
            union=Usersets(
                child=[
                    Userset(this=dict()),
                    Userset(computed_userset=ObjectRelation(
                        object="",
                        relation="writer",
                     )),
                 ],
            )
        ),
    ),
)
        
body = WriteAuthorizationModelRequest(
    schema_version = "1.1",
    type_definitions=[
        user_type,
        document_type,
    ],
)

(and we break the document type relations into smaller pieces etc.)

The code in question is in

body = WriteAuthorizationModelRequest(

Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

get_store should have an optional store_id parameter

In the current implementation, get_store return the OpenFGA store specified in the client_api configuration.
Except by listing all the stores with list_stores, I don't see any other way to get a specific store different of the one defined in the configuration.
A way to arrange that would be to add an optional store_id parameter to get_store.

Part of openfga/sdk-generator#118

Support for conditions?

By submitting an issue to this repository, you agree to the terms within the OpenFGA Code of Conduct.

Describe the problem you'd like to have solved

I'd like the Python SDK to support conditions. According to the official documentation, this is not supported yet. Is there any plans to do so, and if yes, under which timeframe?

Thanks! :)

README: double slash used as comments in example

Some of the README examples are incorrect in that double slash // are used in place of # as comments.

The offending lines are

Ideally, we will also fix the SDK generator here and here so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

Drop code that deals with Python 2 compatibility

Checklist

Describe the problem you'd like to have solved

We have code that deals with Python 2 compatibility even though we never supported it, this means extra dependencies and extra code.

Describe the ideal solution

Drop anything to do with Python 2 compatibility or <3.10, if new features from Python 3.10+ can be used to simplify some code paths we should try it

Alternatives and current workarounds

No response

References

No response

Additional context

No response

Users want to have control over the request timeout

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

OpenFgaApi methods support passing in a _request_timeout:

:param _request_timeout: timeout setting for this request. If one
number provided, it will be total request
timeout. It can also be a pair (tuple) of
(connection, read) timeouts.

However the options_to_kwargs

def options_to_kwargs(options: dict[str, int | str] = None):
"""
Return kwargs with continuation_token and page_size
"""
kwargs = {}
if options is not None:
if options.get("page_size"):
kwargs["page_size"] = options["page_size"]
if options.get("continuation_token"):
kwargs["continuation_token"] = options["continuation_token"]
if options.get("headers"):
kwargs["_headers"] = options["headers"]
if options.get("retry_params"):
kwargs["_retry_params"] = options["retry_params"]
return kwargs
does not pass in that option down from the OpenFgaClient methods to the OpenFgaApi methods

Expectation

A user should be able to set the request timeout on a method.

Note that instead of just allowing passing in _request_timeout per method, this should be done like in the Java SDK.

Users should be able to configure a default timeout in the Configuration/ClientConfiguration, and override it per method.

Example in Java: https://github.com/openfga/java-sdk/blob/b1e03e523c530824f5921313c2191dc5f6d93af8/src/main/java/dev/openfga/sdk/api/configuration/BaseConfiguration.java#L22-L24

Reproduction

.

OpenFGA SDK version

v0.6.1

OpenFGA version

N/A

SDK Configuration

N/A

Logs

No response

References

https://cloud-native.slack.com/archives/C06G1NNH47N/p1723022081318009

mypy type hints

Checklist

Describe the problem you'd like to have solved

would be nice to have type hints added to the library

mypy currently complains due to openfga_sdk: module is installed, but missing library stubs or py.typed marker

https://peps.python.org/pep-0484/

Describe the ideal solution

adding type hints and a py.typed file so mypy recognizes it

Alternatives and current workarounds

disable the linting rule

References

No response

Additional context

No response

README client should call fga_client instead of api_instance

Currently, the (README file)[https://github.com/openfga/python-sdk/blob/main/README.md] is incorrect in several places where api_instance is used instead of fga_client.

The sample code for

uses api_instance instead of fga_client. The purpose of this issue is to change all these instances to use fga_client instead.

Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

Python SDK should retry on 5xx errors

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

The SDK currently retries only on 429 errors

https://github.com/openfga/python-sdk/blob/main/openfga_sdk/sync/api_client.py#L210-L234

It should retry on 429 and 5xx errors except for 501 Not Implemented

Expectation

SDK retries on 5xx errors

Reproduction

  1. Call the API
  2. Get a 500 response
  3. SDK does not retry and returns the error

OpenFGA SDK version

v0.4.1

OpenFGA version

N/A

SDK Configuration

configuration = ClientConfiguration( api_url=FGA_API_URL, # required store_id=FGA_STORE_ID, # optional, not needed when calling CreateStore or ListStores authorization_model_id=FGA_AUTHORIZATION_MODEL_ID, # Optional, can be overridden per request credentials=Credentials( method='client_credentials', configuration=CredentialConfiguration( api_issuer=FGA_API_TOKEN_ISSUER, api_audience=FGA_API_AUDIENCE, client_id=FGA_CLIENT_ID, client_secret=FGA_CLIENT_SECRET, ) ) )

Logs

No response

References

No response

Python SDK should provide a method for users to get the response headers and the raw response

Checklist

Describe the problem you'd like to have solved

As a user, I'd like to be able to get the response headers when using OpenFgaClient

Describe the ideal solution

OpenFgaClient will have get_headers() and get_raw_response() methods that allow users to retrieve the headers and raw response respectively.

Batch Methods such as non transactional write and batch check would have these methods on individual responses.

Alternatives and current workarounds

No response

References

No response

Additional context

No response

README: use different code block for different read API configuration

The READMEs' read relationship tuples example uses the same code block for different read API configuration (i.e., find if a relationship tuple stating that a certain user is a viewer of certain document, find all relationship tuples where a certain user has a relationship as any relation to a certain document, etc.)

Ideally, each type of API will have its own code block to improve reading experience.

For example,

# Find if a relationship tuple stating that a certain user is a viewer of certain document
body = TupleKey(
    user="user:81684243-9356-4421-8fbf-a4f8d36aa31b",
    relation="viewer",
    object="document:roadmap",
)

response = await fga_client.read(body)
# response = ReadResponse({"tuples": [Tuple({"key": TupleKey({"user":"...","relation":"...","object":"..."}), "timestamp": datetime.fromisoformat("...") })]})
# Find all relationship tuples where a certain user has a relationship as any relation to a certain document
body = TupleKey(
    user="user:81684243-9356-4421-8fbf-a4f8d36aa31b",
    object="document:roadmap",
)

response = await fga_client.read(body)
# response = ReadResponse({"tuples": [Tuple({"key": TupleKey({"user":"...","relation":"...","object":"..."}), "timestamp": datetime.fromisoformat("...") })]})

The code in question is in

# Find if a relationship tuple stating that a certain user is a viewer of certain document
.

Ideally, we will also fix the SDK generator so that newly generated python SDKs will have the corresponding changes. This is tracked as openfga/sdk-generator#126. However, if that is difficult to do, simply focusing on the Python SDK side https://github.com/openfga/python-sdk/blob/main/README.md will help us as well.

Client Check with contextual tuples throws an error

Please do not report security vulnerabilities here. See the Responsible Disclosure Program.

Thank you in advance for helping us to improve this library! Please read through the template below and answer all relevant questions. Your additional work here is greatly appreciated and will help us respond as quickly as possible.

By submitting an issue to this repository, you agree to the terms within the OpenFGA Code of Conduct.

Description

From Rocio on Discord

Hi, I think I found a bug while trying to use the pythonsdk to run a check request with contextual tuples.

I'm getting this error:
TypeError: 'NoneType' object is not callable

From this line. I think it should be req_body.contextual_tuples = <something>. Similar to how it's done here. Since contextual_tuples is not a callable.

Version of SDK

  • v0.2.0

OpenTelemetry Metrics with Invalid types

Checklist

  • I have looked into the README and have not found a suitable solution or answer.
  • I have looked into the documentation and have not found a suitable solution or answer.
  • I have searched the issues and have not found a suitable solution or answer.
  • I have upgraded to the latest version of OpenFGA and the issue still persists.
  • I have searched the Slack community and have not found a suitable solution or answer.
  • I agree to the terms within the OpenFGA Code of Conduct.

Description

Looks like the FGA Client Metrics have invalid types for client_id when running openfga with Preshared Keys.

Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None

This issue gets exacerbated when running opentelemetry with auto-instrumentation for logs enabled.

Expectation

Expectation is that running OpenFGA SDK with Preshared Keys does not result in exceptions on opentelemetry

Reproduction

  1. Run OpenFGA with Pre-shared keys
  2. Configure OpenFGA Python SDK with Pre-shared keys
  3. Enable OpenTelemetry Auto-Instrumentation with Logging enabled
# Also add the below line to ensure the Logging auto-isntrumentation does not swallow logs and print it to stdout
import logging
import sys
logging.getLogger().addHandler(logging.StreamHandler(sys.stdout))
  1. Run the SDK for a while and make requests

OpenFGA SDK version

0.6.1

OpenFGA version

0.5.7

OpenTelemetry Python Instrumentation Version

0.47b0

SDK Configuration

openfga_config = openfga_sdk.ClientConfiguration(
            api_url=url,
            store_id=storeid,
            credentials=Credentials(
                method="api_token",
                configuration=CredentialConfiguration(
                    api_token=token,
                ),
            ),
        )
client = openfga_sdk.OpenFgaClient(openfga_config)

Logs

Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None
Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None
Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None
Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None
Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None
Failed to encode key fga-client.request.client_id: Invalid type <class 'NoneType'> of value None
Traceback (most recent call last):
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 111, in _encode_attributes
   pb2_attributes.append(_encode_key_value(key, value))
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 92, in _encode_key_value
   return PB2KeyValue(key=key, value=_encode_value(value))
                                     ^^^^^^^^^^^^^^^^^^^^
 File "/otel-auto-instrumentation-python/opentelemetry/exporter/otlp/proto/common/_internal/__init__.py", line 88, in _encode_value
   raise Exception(f"Invalid type {type(value)} of value {value}")
Exception: Invalid type <class 'NoneType'> of value None

References

No response

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤ī¸ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.