Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,9 @@ jobs:
run: |
poetry run make testcov
env:
FASTID_DB_URL: postgresql+asyncpg://${{ matrix.database-user }}:${{ matrix.database-password }}@${{ matrix.database-host }}:${{ matrix.database-port }}/${{ matrix.database-name }}
FASTID_REDIS_URL: redis://${{ matrix.redis-user }}:${{ matrix.redis-password }}@${{ matrix.redis-host }}:${{ matrix.redis-port }}
FASTID_GOOGLE_OAUTH_ENABLED: 1
FASTID_YANDEX_OAUTH_ENABLED: 1
FASTID_VK_OAUTH_ENABLED: 1
FASTID_TEST_DB_URL: postgresql+asyncpg://${{ matrix.database-user }}:${{ matrix.database-password }}@${{ matrix.database-host }}:${{ matrix.database-port }}/${{ matrix.database-name }}
FASTID_TEST_REDIS_URL: redis://${{ matrix.redis-username }}:${{ matrix.redis-password }}@${{ matrix.redis-host }}:${{ matrix.redis-port }}
FASTID_SMTP_ENABLED: 1
FASTID_TELEGRAM_WIDGET_ENABLED: 1
FASTID_TELEGRAM_NOTIFICATION_ENABLED: 1
FASTID_TELEGRAM_BOT_TOKEN: 123456:BOT_SECRET
FASTID_WEBHOOK_PAGE_EXPIRES_IN_SECONDS: 0
Expand Down
29 changes: 6 additions & 23 deletions docs/docs/tutorial/social.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,24 @@
Social login allows users to authenticate using their existing accounts from popular platforms like **Google**,
**Yandex**, **Telegram** and others.

To enable social login, you need to
register your application with the respective social platform and obtain client credentials. Then, you can configure
FastID to use these credentials.
To enable social login, register your application with the respective social platform and obtain client credentials.
Then open **Admin → Settings → OAuth Providers**, edit the provider, enter its credentials, and enable it. All supported
providers are created in a disabled state. OAuth credentials are no longer read from environment variables.

## Google

Visit [https://console.cloud.google.com/apis/credentials](https://console.cloud.google.com/apis/credentials) to obtain
client credentials.

Add the following to your `.env` file:

```
FASTID_GOOGLE_OAUTH_ENABLED=1
FASTID_GOOGLE_CLIENT_ID=...
FASTID_GOOGLE_CLIENT_SECRET=...
```
In the Admin panel, enter the Google **Client ID** and **Client Secret**, then enable Google.

![google_consent.png](../img/google_consent.png)

## Yandex

Visit [https://oauth.yandex.ru](https://oauth.yandex.ru) to obtain client credentials.

Add the following to your `.env` file:

```
FASTID_YANDEX_OAUTH_ENABLED=1
FASTID_YANDEX_CLIENT_ID=...
FASTID_YANDEX_CLIENT_SECRET=...
```
In the Admin panel, enter the Yandex **Client ID** and **Client Secret**, then enable Yandex.

![yandex_consent.png](../img/yandex_consent.png)

Expand All @@ -42,11 +30,6 @@ Visit [https://t.me/BotFather](https://t.me/BotFather) to create a new bot and o
bot in the BotFather
settings.

Add the following to your `.env` file:

```
FASTID_TELEGRAM_OAUTH_ENABLED=1
FASTID_TELEGRAM_BOT_TOKEN=...
```
In the Admin panel, put the bot token in **Client Secret** and enable Telegram. Telegram does not use **Client ID**.

![telegram_consent.png](../img/telegram_consent.png)
6 changes: 6 additions & 0 deletions fastid/admin/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,16 @@
from fastid.admin.views.settings import (
AppAdmin,
EmailTemplateAdmin,
OAuthProviderAdmin,
TelegramTemplateAdmin,
WebhookAdmin,
WebhookEventAdmin,
)
from fastid.admin.views.versioning import (
AppVersionAdmin,
EmailTemplateVersionAdmin,
OAuthAccountVersionAdmin,
OAuthProviderVersionAdmin,
TelegramTemplateVersionAdmin,
TransactionAdmin,
UserVersionAdmin,
Expand Down Expand Up @@ -50,14 +53,17 @@ def create(self) -> FastAPI:
admin.add_view(NotificationAdmin)
# Settings
admin.add_view(AppAdmin)
admin.add_view(OAuthProviderAdmin)
admin.add_view(WebhookAdmin)
admin.add_view(WebhookEventAdmin)
admin.add_view(EmailTemplateAdmin)
admin.add_view(TelegramTemplateAdmin)
# Versioning
admin.add_view(TransactionAdmin)
admin.add_view(UserVersionAdmin)
admin.add_view(OAuthAccountVersionAdmin)
admin.add_view(AppVersionAdmin)
admin.add_view(OAuthProviderVersionAdmin)
admin.add_view(WebhookVersionAdmin)
admin.add_view(EmailTemplateVersionAdmin)
admin.add_view(TelegramTemplateVersionAdmin)
Expand Down
30 changes: 29 additions & 1 deletion fastid/admin/views/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from fastid.admin.views.base import BaseView
from fastid.admin.views.utils import json_format
from fastid.database.models import App, EmailTemplate, TelegramTemplate, Webhook, WebhookEvent
from fastid.database.models import App, EmailTemplate, OAuthProvider, TelegramTemplate, Webhook, WebhookEvent


class AppAdmin(BaseView, model=App):
Expand All @@ -26,6 +26,34 @@ class AppAdmin(BaseView, model=App):
]


class OAuthProviderAdmin(BaseView, model=OAuthProvider):
can_create = False
can_delete = False

name = "OAuth Provider"
name_plural = "OAuth Providers"
icon = "fa-solid fa-right-to-bracket"
category = "Settings"

column_list = [
OAuthProvider.id,
OAuthProvider.name,
OAuthProvider.enabled,
OAuthProvider.client_id,
OAuthProvider.created_at,
OAuthProvider.updated_at,
]
column_filters = [
BooleanFilter(OAuthProvider.enabled),
AllUniqueStringValuesFilter(OAuthProvider.name),
]
form_columns = [
OAuthProvider.enabled,
OAuthProvider.client_id,
OAuthProvider.client_secret,
]


class EmailTemplateAdmin(BaseView, model=EmailTemplate):
name = "Email Template"
name_plural = "Email Templates"
Expand Down
12 changes: 12 additions & 0 deletions fastid/admin/views/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from fastid.database.versioning import (
AppVersion,
EmailTemplateVersion,
OAuthAccountVersion,
OAuthProviderVersion,
TelegramTemplateVersion,
Transaction,
UserVersion,
Expand Down Expand Up @@ -66,11 +68,21 @@ class UserVersionAdmin(BaseVersionView, model=UserVersion):
name_plural = "User Versions"


class OAuthAccountVersionAdmin(BaseVersionView, model=OAuthAccountVersion):
name = "OAuth Account Version"
name_plural = "OAuth Account Versions"


class AppVersionAdmin(BaseVersionView, model=AppVersion):
name = "App Version"
name_plural = "App Versions"


class OAuthProviderVersionAdmin(BaseVersionView, model=OAuthProviderVersion):
name = "OAuth Provider Version"
name_plural = "OAuth Provider Versions"


class EmailTemplateVersionAdmin(BaseVersionView, model=EmailTemplateVersion):
name = "Email Template Version"
name_plural = "Email Template Versions"
Expand Down
9 changes: 8 additions & 1 deletion fastid/cache/config.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
from pydantic import AliasChoices, Field
from pydantic_settings import SettingsConfigDict

from fastid.core.config import branding_settings
from fastid.core.schemas import ENV_PREFIX, BaseSettings


class RedisSettings(BaseSettings):
url: str = "redis://default+changethis@localhost:6379/0"
url: str = Field(
default="redis://default+changethis@localhost:6379/0",
validation_alias=AliasChoices(
f"{ENV_PREFIX}redis_url",
f"{ENV_PREFIX}test_redis_url",
),
)
major_key: str = branding_settings.service_name
decode_responses: bool = True
pool_size: int = 20
Expand Down
12 changes: 12 additions & 0 deletions fastid/core/lifespan.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
from fastid.database.uow import SQLAlchemyUOW
from fastid.notify.repositories import EmailTemplateSlugSpecification, TelegramTemplateSlugSpecification
from fastid.notify.utils import collect_email_templates, collect_telegram_templates
from fastid.oauth.models import OAUTH_PROVIDER_NAMES, OAuthProvider
from fastid.oauth.repositories import OAuthProviderNameSpecification
from fastid.webhooks.senders.dependencies import client as webhooks_client


Expand All @@ -25,6 +27,7 @@ async def on_startup(self) -> None:
async with self.cache.lock("seed", blocking=True):
await self.create_admin()
await self.create_templates()
await self.create_oauth_providers()
except LockError:
pass

Expand Down Expand Up @@ -55,6 +58,15 @@ async def create_templates(self) -> None:
except NoResultFoundError:
await self.uow.telegram_templates.add(telegram_t)

async def create_oauth_providers(self) -> None:
for name in OAUTH_PROVIDER_NAMES:
try:
await self.uow.oauth_providers.find(OAuthProviderNameSpecification(name))
except NoResultFoundError:
await self.uow.oauth_providers.add(
OAuthProvider(name=name, enabled=False, client_id="", client_secret=""),
)

async def on_shutdown(self) -> None:
await self.cache.client.aclose()
await webhooks_client.aclose()
Expand Down
9 changes: 7 additions & 2 deletions fastid/database/config.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
from typing import Any

from pydantic import Field, PositiveInt
from pydantic import AliasChoices, Field, PositiveInt
from pydantic_settings import SettingsConfigDict

from fastid.core.schemas import ENV_PREFIX, BaseSettings


class DBSettings(BaseSettings):
url: str
url: str = Field(
validation_alias=AliasChoices(
f"{ENV_PREFIX}db_url",
f"{ENV_PREFIX}test_db_url",
),
)
echo: bool = False

# --- pool settings ---
Expand Down
7 changes: 6 additions & 1 deletion fastid/database/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from fastid.auth.models import User
from fastid.database.base import BaseOrm
from fastid.notify.models import EmailTemplate, Notification, TelegramTemplate
from fastid.oauth.models import OAuthAccount
from fastid.oauth.models import OAuthAccount, OAuthProvider
from fastid.webhooks.models import Webhook, WebhookEvent

configure_mappers()
Expand All @@ -14,6 +14,8 @@
from fastid.database.versioning import ( # noqa: E402
AppVersion,
EmailTemplateVersion,
OAuthAccountVersion,
OAuthProviderVersion,
TelegramTemplateVersion,
Transaction,
UserVersion,
Expand All @@ -24,6 +26,7 @@
"App",
"BaseOrm",
"OAuthAccount",
"OAuthProvider",
"User",
"EmailTemplate",
"TelegramTemplate",
Expand All @@ -36,4 +39,6 @@
"WebhookVersion",
"Webhook",
"WebhookEvent",
"OAuthAccountVersion",
"OAuthProviderVersion",
]
4 changes: 3 additions & 1 deletion fastid/database/uow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from fastid.apps.repositories import AppRepository
from fastid.auth.repositories import UserRepository
from fastid.notify.repositories import EmailTemplateRepository, NotificationRepository, TelegramTemplateRepository
from fastid.oauth.repositories import OAuthAccountRepository
from fastid.oauth.repositories import OAuthAccountRepository, OAuthProviderRepository
from fastid.webhooks.repositories import WebhookEventRepository, WebhookRepository

if TYPE_CHECKING:
Expand All @@ -23,6 +23,7 @@
class SQLAlchemyUOW:
users: UserRepository
oauth_accounts: OAuthAccountRepository
oauth_providers: OAuthProviderRepository
apps: AppRepository
email_templates: EmailTemplateRepository
telegram_templates: TelegramTemplateRepository
Expand All @@ -40,6 +41,7 @@ async def begin(self) -> None:
self.session = self.session_factory()
self.users = UserRepository(self.session)
self.oauth_accounts = OAuthAccountRepository(self.session)
self.oauth_providers = OAuthProviderRepository(self.session)
self.apps = AppRepository(self.session)
self.email_templates = EmailTemplateRepository(self.session)
self.telegram_templates = TelegramTemplateRepository(self.session)
Expand Down
3 changes: 3 additions & 0 deletions fastid/database/versioning.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
from fastid.apps.models import App
from fastid.auth.models import User
from fastid.notify.models import EmailTemplate, TelegramTemplate
from fastid.oauth.models import OAuthAccount, OAuthProvider
from fastid.webhooks.models import Webhook

Transaction = transaction_class(User)

UserVersion = version_class(User)
OAuthAccountVersion = version_class(OAuthAccount)
AppVersion = version_class(App)
OAuthProviderVersion = version_class(OAuthProvider)
EmailTemplateVersion = version_class(EmailTemplate)
TelegramTemplateVersion = version_class(TelegramTemplate)
WebhookVersion = version_class(Webhook)
2 changes: 0 additions & 2 deletions fastid/frontend/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from fastid.frontend.exceptions import add_exception_handlers
from fastid.frontend.router import router as pages_router
from fastid.frontend.templating import templates
from fastid.oauth.metadata import UI_META

routers = [pages_router]

Expand Down Expand Up @@ -55,4 +54,3 @@ def _set_templates_env(self) -> None:
templates.env.globals["app_title"] = branding_settings.title
templates.env.globals["favicon_url"] = self.favicon_url
templates.env.globals["logo_url"] = self.logo_url
templates.env.globals["providers_meta"] = UI_META
Loading
Loading