Metadata-Version: 2.4
Name: anzar
Version: 0.5.1
Summary: Anzar is a lightweight authentication and authorization framework that runs as a separate microservice
Keywords: Software Development,Authentication,Authorization,MicroService
Author: Hakou Guelfen
Author-email: Hakou Guelfen <hakoudev@gmail.com>
License-Expression: GPL-3.0
Classifier: Programming Language :: Python :: 3
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Topic :: Software Development
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.12.5
Requires-Dist: flask>=3.1.3 ; extra == 'flask'
Requires-Dist: pyjwt>=2.12.1 ; extra == 'flask'
Requires-Dist: redis>=7.3.0 ; extra == 'redis'
Requires-Python: >=3.11
Project-URL: Bug, https://gitlab.com/anzar_software/python-sdk/-/work_items
Project-URL: Documentation, https://anzar_software.gitlab.io/docs
Project-URL: Homepage, https://gitlab.com/anzar_software/python-sdk
Provides-Extra: flask
Provides-Extra: redis
Description-Content-Type: text/markdown

# Anzar SDK Documentation

## Server

```python
from flask import g
from flask import Flask, jsonify
from anzar.server import require_auth, require_role, AnzarAuth
from anzar.types import Role

app = Flask(__name__)

requireAuth = AnzarAuth(
    secret = process.env.SECRET,
    audience = process.env.AUDIENCE
    issuerBaseURL = process.env.ISSUER
)

@app.route("/protected")
@require_auth(requireAuth)
def me():
    return jsonify(g.user_id)


@app.route("/admin")
@require_role(requireAuth, roles="admin", permissions=["users:delete"])
def admin():
    return jsonify(f"admin panel, {g.user_id}")


if __name__ == "__main__":
    app.run(debug=True)
```

---


## Client

## Install The Python SDK
In a python project run the following command to install the anzar package.

**uv**
```bash
$ uv add anzar
```

**pip**
```bash
# in a virtual env run
$ pip install anzar
```

## Create Anzar Auth Instance
in your main entry file (`main.py` for example),
import `anzar.yml` and parse it as a YAML file
```python
def load_config(path: str) -> AnzarConfig:
    import yaml

    try:
        with open(path, "r") as f:
            data = yaml.safe_load(f)
        return AnzarConfig(**data)
    except Exception as e:
        import sys

        sys.exit("check your configuration file: anzar.yml")
```

import Anzar Auth and create your auth instance
```python 
# Initialize once at application startup
# The SDK will communicate with your Anzar container at the configured api_url
from anzar import Anzar

config = load_config("anzar.yml")
anzar = Anzar(config, options=None)
```


**Note** "Configuring Token Persistence"
    To keep users logged in across restarts, choose a token storage adapter.

    ```python
    from anzar.adapters import RedisStorage
    from anzar.types import SdkOptions 

    anzar = Anzar(config, SdkOptions(storage=RedisStorage()))
    ```

---

## Basic Usage
Anzar provides authentication support for email and password.

📝 **Note:** Other methods of authentication will be implemented later

### Sign Up
To sign up a user you need to call the method register with the user's information.
```python
from anzar.types import AuthResponse, ErrorCode

(data, error) = await anzar.Auth.register({
  "username": "username",
  "email": "user@example.com",
  "password": "password"
})

if data:
    print(data)

if error:
    if error.code == ErrorCode.InvalidCredentials:
        show_error("Invalid email or password.")
    elif error.code == ErrorCode.AccountNotVerified:
        show_error("Please verify your email before logging in.")
```

📝 **Note:** By default, the users are automatically signed in after they successfully sign up.
             Disabling this behavior will be implemented later

### Sign In
To sign in a user you need to call the method login.
```python
from anzar.types import ApiException, AuthResponse, ErrorCode

(response, error) = await anzar.Auth.login(
    LoginRequest(email="user@example.com", password="password")
)
if error:
    print("code:", error.code)
    print("message:", error.message)
print(response)
