Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

google OIDC. Auth refactoring #6

Merged
merged 8 commits into from
Apr 15, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ concurrency:


jobs:

build:
name: "Build dev image"
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ redis-*.tgz
db.sqlite3
.secrets.env
*.spec
.secrets.env
71 changes: 49 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,37 @@
* Swagger in Django Admin Panel
* Ready for deploy by one click
* Separated configuration for dev and prod (requirements and settings)
* CI/CD: GitHub Actions/GitlabCI
* CI/CD: GitHub Actions
* Redefined default User model (main.models.py)
* MailHog, Jaeger, RabbitMQ integrations
* Mailpit, Jaeger, RabbitMQ integrations
* Multi-stage build for prod versions
* PostgreSql Backup

### How to use:

#### Clone the repo or click "Use this template" button:

git clone https://github.com/bandirom/django-blog.git

```shell
git clone https://github.com/bandirom/django-blog.git
```


#### Before running add your superuser email/password and project name in docker/prod/env/.data.env file

[email protected]
SUPERUSER_PASSWORD=secretp@ssword
PROJECT_TITLE=MyProject
```dotenv
[email protected]
SUPERUSER_PASSWORD=secretp@ssword
PROJECT_TITLE=MyProject
```

#### Run the local develop server:

docker-compose up -d --build
docker-compose logs -f
```shell
docker-compose up -d --build
docker-compose logs -f
```

##### Server will bind 8000 port. You can get access to server by browser [http://localhost:8008](http://localhost:8008)
##### Server will run on 8000 port. You can get access to server by browser [http://localhost:8000](http://localhost:8000)

Run django commands through exec:
```shell
Expand All @@ -47,21 +53,40 @@ docker-compose exec web python manage.py makemigrations
docker-compose exec web python manage.py shell
```

##### For testing mail backend you can use MailHog service
docker-compose -f docker-compose.yml -f docker/modules/mailhog.yml up -d --build
Get access to the container
```shell
docker-compose exec web sh
```

##### For run mail smtp for local development you can use Mailpit service

* Run Mailpit
```shell
docker-compose -f docker/modules/mailpit.yml up -d
```

<b>Don't forget to set SMTP mail backend in settings</b>

```dotenv
# docker/dev/env/.email.env
EMAIL_HOST=mailpit_hostname
```
Where `mailpit_hostname` is
* `docker.host.internal` for Window and macOS
* `gateway-host` for Linux OS

---

### Production environment

If your server under LoadBalancer with SSL/TLS certificate you could run simple `prod.yml` configuration

docker-compose -f prod.yml up -d --build
If your server under LoadBalancer or nginx with SSL/TLS certificate you can run `prod.yml` configuration

```shell
docker-compose -f prod.yml up -d --build
```

#### For set https connection you should have a domain name
<b> In prod.certbot.yml: </b>
**In prod.certbot.yml:**

Change the envs:
CERTBOT_EMAIL: your real email
Expand All @@ -70,10 +95,12 @@ Change the envs:

To set https for 2 and more nginx servers:

ENVSUBST_VARS: API UI
API: api.domain.com
UI: domain.com

Run command:
```dotenv
ENVSUBST_VARS: API
API: api.your-domain.com
```

docker-compose -f prod.yml -f prod.certbot.yml up -d --build
Run command:
```shell
docker-compose -f prod.yml -f prod.certbot.yml up -d --build
```
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ services:
- redis_data:/data
networks:
- separated_network
logging:
driver: none
healthcheck:
test: [ "CMD", "redis-cli","ping" ]
interval: 1m20s
Expand Down
3 changes: 1 addition & 2 deletions docker/dev/env/.email.env
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
EMAIL_HOST=gateway-host
EMAIL_HOST=host.docker.internal
EMAIL_PORT=1025
EMAIL_USE_TLS=0
EMAIL_USE_SSL=0
DEFAULT_FROM_EMAIL="Localhost <[email protected]>"
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
EMAIL_BACKEND=smtp
6 changes: 3 additions & 3 deletions docker/dev/env/.env
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ HEALTH_CHECK_URL=/application/health/
ENABLE_SILK=1
ENABLE_DEBUG_TOOLBAR=0
ENABLE_SENTRY=0
FRONTEND_URL=http://192.168.59.111:8008
BACKEND_URL=http://192.168.59.111:8008
FRONTEND_URL=http://localhost:8008
BACKEND_URL=http://localhost:8008

CHAT_PROXY=http://192.168.59.111:8005/init/
CHAT_PROXY=http://localhost:8005/init/
9 changes: 0 additions & 9 deletions docker/modules/mailhog.yml

This file was deleted.

15 changes: 15 additions & 0 deletions docker/modules/mailpit.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# SMTP Server for mail testing

services:
mailpit:
image: axllent/mailpit
restart: unless-stopped
ports:
- target: 1025
published: 1025
protocol: tcp
mode: host
- target: 8025
published: 8025
protocol: tcp
mode: host
8 changes: 0 additions & 8 deletions docker/prod/env/.email.env

This file was deleted.

8 changes: 8 additions & 0 deletions docker/prod/env/.env
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,11 @@ FRONTEND_URL=https://blog.jollymanager.com
BACKEND_URL=https://blog.jollymanager.com
CHAT_PROXY=https://chat.jollymanager.com/init/
JWT_COOKIE_DOMAIN=.jollymanager.com

EMAIL_HOST
EMAIL_PORT
EMAIL_USE_TLS=0
EMAIL_USE_SSL=0
DEFAULT_FROM_EMAIL
EMAIL_HOST_USER
EMAIL_HOST_PASSWORD
6 changes: 0 additions & 6 deletions prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ x-variables: &variables

services:
blog:
build:
context: .
dockerfile: docker/prod/web/Dockerfile
image: bandirom/blog:${APP_VERSION:-latest}
volumes:
- redis_socket:/redis_socket
Expand Down Expand Up @@ -33,9 +30,6 @@ services:
extra_hosts:
- "gateway-host:172.17.0.1"
celery:
build:
context: .
dockerfile: docker/prod/web/Dockerfile
image: bandirom/blog:${APP_VERSION:-latest}
entrypoint: ""
command: celery -A src worker --beat -l info
Expand Down
File renamed without changes.
72 changes: 72 additions & 0 deletions web/api/email_service/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from abc import ABC, abstractmethod
from typing import TYPE_CHECKING, Optional, TypedDict

from django.contrib.auth import get_user_model
from django.utils.translation import get_language

from main.tasks import send_information_email

if TYPE_CHECKING:
from main.models import UserType


User: 'UserType' = get_user_model()


class EmailSendData(TypedDict):
subject: str
template_name: str
language: str
to_email: str
context: dict
from_email: Optional[str]
file_path_attachments: Optional[str]


class BaseEmailService(ABC):
def __init__(self, user: Optional[User] = None, language: Optional[str] = None, from_email: Optional[str] = None):
self._user = user
self._locale: str = language or get_language()
self.from_email = from_email

@property
def locale(self) -> str:
return self._locale

@property
def user(self) -> User:
assert self._user, 'User object were not provided'
return self._user

@property
@abstractmethod
def template_name(self) -> str:
"""Template email path"""

@property
def to_email(self) -> str:
return self.user.email

def email_context(self, **kwargs) -> dict:
"""Provide dict with data for email template rendering"""
return {}

@property
@abstractmethod
def email_subject(self) -> str:
"""Provide email subject"""

def get_email_data(self, **kwargs) -> EmailSendData:
return {
'subject': self.email_subject,
'template_name': self.template_name,
'language': self.locale,
'to_email': self.to_email,
'context': self.email_context(**kwargs),
'from_email': self.from_email,
'file_path_attachments': None,
}

def send_email(self, **kwargs):
kwargs: dict = self.get_email_data(**kwargs)
return send_information_email.apply_async(kwargs=kwargs)
18 changes: 18 additions & 0 deletions web/api/email_service/password_reset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from django.conf import settings
from django.utils.translation import gettext_lazy as _

from api.email_service.base import BaseEmailService


class PasswordResetService(BaseEmailService):
template_name = 'emails/password_reset.html'

@property
def email_subject(self) -> str:
return _('Blog password reset')

def email_context(self, reset_url: str, **kwargs) -> dict:
return {
'full_name': self.user.full_name,
'reset_url': reset_url,
}
17 changes: 17 additions & 0 deletions web/api/email_service/sign_up.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from django.utils.translation import gettext_lazy as _

from api.email_service.base import BaseEmailService


class SignUpEmailService(BaseEmailService):
template_name = 'emails/verify_email.html'

@property
def email_subject(self) -> str:
return _('Blog register confirmation email')

def email_context(self, activate_url: str, **kwargs) -> dict:
return {
'full_name': self.user.full_name,
'activate_url': activate_url,
}
38 changes: 0 additions & 38 deletions web/api/email_services.py

This file was deleted.

2 changes: 0 additions & 2 deletions web/api/v1/actions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class FollowSerializer(serializers.Serializer):


class UserFollowSerializer(serializers.ModelSerializer):
"""For list of user following and followers"""

profile_url = serializers.URLField(source='get_absolute_url')

follow = serializers.BooleanField()
Expand Down
Loading
Loading