Skip to content

Commit cc62c05

Browse files
Регистрация(почта+пароль), Вход по логину и паролю, Выход (#16)
1 parent e892427 commit cc62c05

29 files changed

Lines changed: 1003 additions & 34 deletions
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
name: Build, publish and deploy docker
2+
3+
on:
4+
push:
5+
branches: [ 'main' ]
6+
tags:
7+
- 'v*'
8+
9+
10+
env:
11+
REGISTRY: ghcr.io
12+
IMAGE_NAME: ${{ github.repository }}
13+
14+
jobs:
15+
build-and-push-image:
16+
name: Build and push
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: read
20+
packages: write
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v2
25+
26+
- name: Log in to the Container registry
27+
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
28+
with:
29+
registry: ${{ env.REGISTRY }}
30+
username: ${{ github.actor }}
31+
password: ${{ secrets.GITHUB_TOKEN }}
32+
33+
- name: Extract metadata (tags, labels) for Docker
34+
id: meta
35+
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
36+
with:
37+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
38+
tags: |
39+
type=ref,event=tag,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
40+
type=raw,value=latest,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
41+
type=raw,value=test,enable=true
42+
43+
- name: Build and push Docker image
44+
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
45+
with:
46+
context: .
47+
push: true
48+
tags: ${{ steps.meta.outputs.tags }}
49+
labels: ${{ steps.meta.outputs.labels }}
50+
51+
deploy-testing:
52+
name: Deploy Testing
53+
needs: build-and-push-image
54+
runs-on: [ self-hosted, Linux ]
55+
environment:
56+
name: Testing
57+
url: https://auth.api.test.profcomff.com/
58+
env:
59+
CONTAITER_NAME: com_profcomff_api_auth_test
60+
permissions:
61+
packages: read
62+
63+
steps:
64+
- name: Pull new version
65+
run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
66+
67+
- name: Migrate DB
68+
run: |
69+
docker run \
70+
--rm \
71+
--network=web \
72+
--env DB_DSN=${{ secrets.DB_DSN }} \
73+
--name ${{ env.CONTAITER_NAME }}_migration \
74+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test \
75+
alembic upgrade head
76+
77+
- name: Run new version
78+
id: run_test
79+
run: |
80+
docker stop ${{ env.CONTAITER_NAME }} || true && docker rm ${{ env.CONTAITER_NAME }} || true
81+
docker run \
82+
--detach \
83+
--restart always \
84+
--network=web \
85+
--env DB_DSN='${{ secrets.DB_DSN }}' \
86+
--env EMAIL='${{ secrets.EMAIL }}' \
87+
--env EMAIL_PASS='${{ secrets.EMAIL_PASS }}' \
88+
--env SMTP_HOST='smtp.gmail.com' \
89+
--env SMTP_PORT='587' \
90+
--name ${{ env.CONTAITER_NAME }} \
91+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:test
92+
93+
deploy-production:
94+
name: Deploy Production
95+
needs: build-and-push-image
96+
if: startsWith(github.ref, 'refs/tags/v')
97+
runs-on: [ self-hosted, Linux ]
98+
environment:
99+
name: Production
100+
url: https://auth.api.profcomff.com/
101+
env:
102+
CONTAITER_NAME: com_profcomff_api_auth
103+
permissions:
104+
packages: read
105+
106+
steps:
107+
- name: Pull new version
108+
run: docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
109+
110+
- name: Migrate DB
111+
run: |
112+
docker run \
113+
--rm \
114+
--network=web \
115+
--env DB_DSN=${{ secrets.DB_DSN }} \
116+
--name ${{ env.CONTAITER_NAME }}_migration \
117+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
118+
alembic upgrade head
119+
120+
- name: Run new version
121+
id: run_test
122+
run: |
123+
docker stop ${{ env.CONTAITER_NAME }} || true && docker rm ${{ env.CONTAITER_NAME }} || true
124+
docker run \
125+
--detach \
126+
--restart always \
127+
--network=web \
128+
--env DB_DSN='${{ secrets.DB_DSN }}' \
129+
--env EMAIL='${{ secrets.EMAIL }}' \
130+
--env EMAIL_PASS='${{ secrets.EMAIL_PASS }}' \
131+
--env SMTP_HOST='smtp.gmail.com' \
132+
--env SMTP_PORT='587' \
133+
--name ${{ env.CONTAITER_NAME }} \
134+
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest

.github/workflows/tests.yml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
name: Python package
2+
3+
on:
4+
pull_request:
5+
6+
7+
jobs:
8+
test:
9+
name: Unit tests
10+
runs-on: ubuntu-latest
11+
continue-on-error: true
12+
steps:
13+
- name: Checkout
14+
uses: actions/checkout@v3
15+
- name: Set up docker
16+
uses: docker-practice/actions-setup-docker@master
17+
- name: Run postgres
18+
run: |
19+
docker run -d -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust --name db-test postgres:15-alpine
20+
- uses: actions/setup-python@v4
21+
with:
22+
python-version: '3.10'
23+
- name: Install dependencies
24+
run: |
25+
python -m ensurepip
26+
python -m pip install --upgrade pip
27+
pip install -r requirements.txt -r requirements.dev.txt
28+
- name: Migrate DB
29+
run: |
30+
DB_DSN=postgresql://postgres@localhost:5432/postgres alembic upgrade head
31+
- name: Build coverage file
32+
run: |
33+
DB_DSN=postgresql://postgres@localhost:5432/postgres pytest --showlocals --cache-clear --cov=auth_backend tests > pytest-coverage.txt
34+
- name: Print report
35+
if: always()
36+
run: |
37+
cat pytest-coverage.txt
38+
- name: Comment coverage
39+
uses: coroo/pytest-coverage-commentator@v1.0.2

Makefile

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@ run:
22
source ./venv/bin/activate && uvicorn --reload --log-level debug auth_backend.routes.base:app
33

44
db:
5-
docker compose up -d
5+
docker run -d -p 5432:5432 -e POSTGRES_HOST_AUTH_METHOD=trust --name db-auth_api postgres:15
6+
sleep 3
67

7-
migrate:
8+
migrate: db
89
alembic upgrade head
10+
11+
test:
12+
python3 -m pytest --verbosity=2 --showlocals --log-level=DEBUG
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from .auth_method import AuthMethodMeta, AUTH_METHODS
2+
from .email import Email
3+
4+
__all__ = ["AUTH_METHODS", "AuthMethodMeta", "Email"]
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from __future__ import annotations
2+
3+
import re
4+
from abc import abstractmethod, ABCMeta
5+
6+
from fastapi import APIRouter
7+
8+
from datetime import datetime
9+
from auth_backend.base import Base
10+
11+
12+
class Session(Base):
13+
expires: datetime
14+
id: int
15+
user_id: int
16+
token: str
17+
18+
19+
AUTH_METHODS: dict[str, type[AuthMethodMeta]] = {}
20+
21+
22+
class AuthMethodMeta(metaclass=ABCMeta):
23+
router: APIRouter
24+
prefix: str
25+
tags: list[str] = []
26+
27+
@classmethod
28+
def get_name(cls) -> str:
29+
return re.sub(r"(?<!^)(?=[A-Z])", "_", cls.__name__).lower()
30+
31+
def __init__(self):
32+
self.router = APIRouter()
33+
self.router.add_api_route("/registration", self.register, methods=["POST"])
34+
self.router.add_api_route("/login", self.login, methods=["POST"], response_model=Session)
35+
36+
def __init_subclass__(cls, **kwargs):
37+
AUTH_METHODS[cls.__name__] = cls
38+
39+
@staticmethod
40+
@abstractmethod
41+
async def register(**kwargs) -> object:
42+
raise NotImplementedError()
43+
44+
@staticmethod
45+
@abstractmethod
46+
async def login(**kwargs) -> Session:
47+
raise NotImplementedError()

0 commit comments

Comments
 (0)