Skip to content

Commit

Permalink
Merge pull request #6 from tarsil/feature/support_for_edgy
Browse files Browse the repository at this point in the history
Support for Edgy
  • Loading branch information
tarsil authored Aug 8, 2023
2 parents 2c07ad2 + 4714dd6 commit 35f2ac6
Show file tree
Hide file tree
Showing 32 changed files with 804 additions and 92 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ build-docs: ## Runs the local docs

.PHONY: test
test: ## Runs the tests
pytest $(TESTONLY) --disable-pytest-warnings -s -vv && scripts/clean
pytest $(TESTONLY) --disable-pytest-warnings -s -vv

.PHONY: requirements
requirements: ## Install requirements for development
pip install -e .[dev,test,doc,email]
pip install -e .[dev,test,doc,email,edgy,saffier,all]

ifndef VERBOSE
.SILENT:
Expand Down
50 changes: 38 additions & 12 deletions docs/authentication.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

Like SQLAdmin, Esmerald Admin does not enfoce any authentication, but provides two out-of-the-box
optional `EmailAdminAuth` and `UsernameAdminAuth` using the [Esmerald contrib auth][models] for
Saffier that you can use.
Saffier that you can use or [models][edgy_models] for Edgy.

!!! Note
If you don't use the Esmerald models for Saffier, you can simply ignore this and use your own
If you don't use the Esmerald models for Saffier or Edgy, you can simply ignore this and use your own
implementation and follow the instructions from the [SQLAdmin][sqladmin_models].


Expand All @@ -17,7 +17,7 @@ and apply logins using `email` or `username`, your choice.
`EmailAdminAuth` and `UsernameAdminAuth` expect three parameters:

* `secret_key` - The secret to be used with your auth.
* `auth_model` - The class object of your `User`, usually derived from the [User model][user_model].
* `auth_model` - The class object of your `User`, usually derived from the [User model][user_model] for Saffier or [User model][user_model_edgy] for Edgy.
* `config` - The application settings object. It can be the [settings config][settings_config] or
the application `settings` from `esmerald.conf`. It all depends of which one you use.

Expand All @@ -27,15 +27,31 @@ This is how you could use the backends in your Esmerald application. This exampl
and it will use the [settings_config][settings_config] from Esmerald to simplify. This is not
mandatory and you can use your preferred way.

```python hl_lines="43-46"
{!> ../docs_src/auth/example.py !}
```
=== "Saffier"

```python hl_lines="43-46"
{!> ../docs_src/auth/example.py !}
```

=== "Edgy"

```python hl_lines="43-46"
{!> ../docs_src/auth/edgy.py !}
```

To use the `UsernameAdminAuth` instead:

```python
from esmerald_admin.backends.username import UsernameAdminAuth
```
=== "Saffier"

```python
from esmerald_admin.backends.saffier.username import UsernameAdminAuth
```

=== "Edgy"

```python
from esmerald_admin.backends.edgy.username import UsernameAdminAuth
```

The `User` model as you can notice, is the one that derived from Esmerald and the reason for this
is because the Esmerald models come with a lot of functionality already built-in such as password
Expand Down Expand Up @@ -70,12 +86,22 @@ override. These methods are used for the control of each Model/View in addition

Like SQLAdmin, both methods implement the same signature and should return a `bool`.

```python hl_lines="43-46"
{!> ../docs_src/auth/permissions.py !}
```
=== "Saffier"

```python hl_lines="43-46"
{!> ../docs_src/auth/permissions.py !}
```

=== "Edgy"

```python hl_lines="43-46"
{!> ../docs_src/auth/permissions_edgy.py !}
```

[models]: https://esmerald.dev/databases/saffier/models/
[edgy_models]: https://esmerald.dev/databases/edgy/models/
[user_model]: https://esmerald.dev/databases/saffier/models/#user
[user_model_edgy]: https://esmerald.dev/databases/edgy/models/#user
[sqladmin_models]: https://aminalaee.dev/sqladmin/authentication/
[settings_config]: https://esmerald.dev/application/settings/#the-settings_config
[permissions]: https://esmerald.dymmond.com/permissions/
2 changes: 2 additions & 0 deletions docs/example.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ with some complexity and organisation.

In this walk-through we will be also making sure we use as many Esmerald built-ins as possible.

**The following example will be using Saffier but the same example is applied to Edgy**.

## What we will be using

* [Esmerald directives][directives] - To generate a project scaffold with a given organisation.
Expand Down
66 changes: 53 additions & 13 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,24 @@

---

## Esmerald admin for [Saffier][saffier] ORM
## Esmerald admin for [Saffier][saffier] and [Edgy][edgy]

Esmerald admin is a flexible user interface for [Saffier ORM][saffier] built on the top of the
already existing and highly maintained [SQLAdmin][sqladmin].
Esmerald admin is a flexible user interface for [Saffier ORM][saffier] and [Edgy][edgy]
built on the top of the already existing and highly maintained [SQLAdmin][sqladmin].

The main goal, as the name of the package says, is to provide a nice, flexible and easy to use
user interface that interacts with [Saffier ORM][saffier] in a more friendly manner.
user interface that interacts with [Saffier][saffier] and [Edgy][edgy] in a more friendly manner.

## Saffier

[Saffier][saffier] is a flexible and powerfull ORM built on the top of SQLAlchemy core that allows
you to interact with almost every single SQL database out there in an asynchronous mode.

## Edgy

[Edgy][saffier] is also an extremely, flexible and powerful ORM built on the top of SQLAlchemy core
and **100% Pydantic** with more flexibility for every single use case, also in asynchronous mode.

### Documentation

Majority of the documentation for this package **can and should** be seen in the [SQLAdmin][sqladmin]
Expand All @@ -56,44 +61,71 @@ The custom, unique, Esmerald way is placed here within these docs.
* SQLAlchemy sync/async engines
* Esmerald integration
* [Saffier][saffier] support
* [Edgy][edgy] support
* Modern UI using Tabler

## Installation

**For Saffier**

```shell
$ pip install esmerald-admin
```

**For Edgy**

```shell
$ pip install esmerald-admin[edgy]
```

**For both**

```shell
$ pip install esmerald-admin[all]
```

## Quickstart

Saffier is a very powerfull ORM as mentioned before and built on the top of SQLAlchemy core but
Saffier and Edgy are very powerfull ORMs as mentioned before and built on the top of SQLAlchemy core but
also extremely flexible allowing to use the models in a `declarative` way, which is the way
SQLAdmin is expecting to use.

This makes Saffier unique since you can use the declarative models for the admin and the core
This makes both Saffier and Edgy unique since you can use the declarative models for the admin and the core
models for anything else.

See the [declarative models][saffier_declarative] for more details on this.
See the [Saffier declarative models][saffier_declarative] and [Edgy declarative models][edgy_declarative] for more details.

Let us create a some Saffier models first. This example assumes you use the [contrib user](https://esmerald.dev/databases/saffier/models/)
Let us create a some models first. This example assumes you use the [contrib user of Saffier](https://esmerald.dev/databases/saffier/models/)
and the [contrib user of Edgy](https://esmerald.dev/databases/edgy/models/)
from Esmerald.

!!! Warning
Using the user provided by Esmerald is **not mandatory** and you can use your own design.
The documentation uses the one provided by Esmerald as it is easier to explain and use.

```python
{!> ../docs_src/quickstart/models.py !}
```
=== "Saffier"

```python
{!> ../docs_src/quickstart/saffier_models.py !}
```

=== "Edgy"

```python
{!> ../docs_src/quickstart/edgy_models.py !}
```

**Now using with Esmerald**

Saffier, as mentioned before, has the [declarative models][saffier_declarative] ready to be used.
These models are **only used for the admin**.


```python
{!> ../docs_src/quickstart/app.py !}
```


Or if you want some more "organised".

=== "Settings"
Expand All @@ -102,10 +134,16 @@ Or if you want some more "organised".
{!> ../docs_src/quickstart/organised/settings.py !}
```

=== "Models"
=== "Saffier Models"

```python title="myproject/apps/accounts/models.py"
{!> ../docs_src/quickstart/organised/saffier_models.py !}
```

=== "Edgy Models"

```python title="myproject/apps/accounts/models.py"
{!> ../docs_src/quickstart/organised/models.py !}
{!> ../docs_src/quickstart/organised/edgy_models.py !}
```

=== "Admin"
Expand Down Expand Up @@ -135,5 +173,7 @@ would not be possible! ⭐️ Star his repo! ⭐️
[esmerald_admin]: https://esmerald-admin.tarsild.io
[esmerald_repo]: https://github.com/tarsil/esmerald-admin
[saffier]: https://saffier.tarsild.io
[edgy]: https://edgy.tarsild.io
[sqladmin]: https://aminalaee.dev/sqladmin/
[saffier_declarative]: https://saffier.tarsild.io/models/#declarative-models
[edgy_declarative]: https://edgy.tarsild.io/models/#declarative-models
12 changes: 12 additions & 0 deletions docs/release-notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Release Notes

## 0.3.0

### Changed

- Updated requirement versions.
- **Breaking change** - The installation does not default to install Saffier anymore. For that purpose
you will need to specify now `pip install esmerald-admin[saffier]` or `pip install esmerald-admin[edgy]`.

### Added

- Support for [Edgy](https://edgy.tarsild.io).

## 0.2.0

### Changed
Expand Down
51 changes: 51 additions & 0 deletions docs_src/auth/edgy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
from edgy import Database, Registry
from esmerald import Esmerald, EsmeraldAPISettings, Include
from esmerald.config.jwt import JWTConfig
from esmerald.contrib.auth.edgy.base_user import AbstractUser

from esmerald_admin import Admin
from esmerald_admin.backends.edgy.email import EmailAdminAuth

database = Database("sqlite:///db.sqlite")
registry = Registry(database=database)


class AppSettings(EsmeraldAPISettings):
@property
def jwt_config(self) -> JWTConfig:
return JWTConfig(signing_key=self.secret_key)


class User(AbstractUser):
"""Inherits from the user base"""

class Meta:
registry = registry


# You can use the `settings_config` directly or ESMERALD_SETTINGS_MODULE
settings = AppSettings()


def get_application():
"""
This is optional. The function is only used for organisation purposes.
"""

app = Esmerald(
routes=[Include(namespace="linezap.urls")],
on_startup=[database.connect],
on_shutdown=[database.disconnect],
settings_config=settings,
)

# EmailAdminAuth or UsernameAdminAuth
auth_backend = EmailAdminAuth(
secret_key=settings.secret_key, auth_model=User, config=settings.jwt_config
)
Admin(app, registry.engine, authentication_backend=auth_backend)

return app


app = get_application()
2 changes: 1 addition & 1 deletion docs_src/auth/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from saffier import Database, Registry

from esmerald_admin import Admin
from esmerald_admin.backends.email import EmailAdminAuth
from esmerald_admin.backends.saffier.email import EmailAdminAuth

database = Database("sqlite:///db.sqlite")
registry = Registry(database=database)
Expand Down
31 changes: 31 additions & 0 deletions docs_src/auth/permissions_edgy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from edgy import Database, Registry
from esmerald import Request
from esmerald.contrib.auth.edgy.base_user import AbstractUser

from esmerald_admin import ModelView

database = Database("sqlite:///db.sqlite")
registry = Registry(database=database)


class User(AbstractUser):
"""Inherits from the user base"""

class Meta:
registry = registry


# Use the declarative from Saffier
UserDeclarative = User.declarative()


class UserAdmin(ModelView, model=UserDeclarative):
def is_visible(self, request: Request) -> bool:
# Check incoming request
# For example request.session if using AuthenticationBackend
return True

def has_permission(self, request: Request) -> bool:
# Check incoming request
# For example request.session if using AuthenticationBackend
return True
7 changes: 5 additions & 2 deletions docs_src/quickstart/app.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
from esmerald import Esmerald
from accounts.models import User
from esmerald import Esmerald, settings

from esmerald_admin import Admin, ModelView

database, registry = settings.db_access

app = Esmerald()
admin = Admin(app, engine)
admin = Admin(app, registry.engine)

# Declarative User
DeclarativeUser = User.declarative()
Expand Down
22 changes: 22 additions & 0 deletions docs_src/quickstart/edgy_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import edgy
from edgy import Database, Registry
from esmerald.contrib.auth.edgy.base_user import AbstractUser

database = Database("sqlite:///db.sqlite")
registry = Registry(database=database)


class BaseModel(edgy.Model):
class Meta:
abstract = True
registry = registry


class User(BaseModel, AbstractUser):
"""Inherits from the user base"""

...


# Create the tables
await registry.create_all()
Loading

0 comments on commit 35f2ac6

Please sign in to comment.