Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
aleksandrGlebov committed May 1, 2024
1 parent 37c53e5 commit 241b734
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 0 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: ci

on:
push:
branches:
- 'main'

jobs:
docker:
runs-on: ubuntu-latest
steps:
-
name: Set up QEMU
uses: docker/setup-qemu-action@v3
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
-
name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
-
name: Build and push
uses: docker/build-push-action@v5
with:
push: true
tags: aleksglebov/licensure:back

- name: Trigger deployment
run: |
curl -v -m 30 -X POST https://licensure.tech/webhook-back?token=${{ secrets.WEBHOOK_TOKEN }}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,5 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

/.vscode
33 changes: 33 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Используем официальный образ Python 3.9 в качестве базового
FROM python:3.9-slim

# Устанавливаем Gunicorn
RUN apt-get update && apt-get install -y gunicorn

# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app

# Копируем файл requirements.txt в рабочую директорию
COPY requirements.txt .

# Устанавливаем зависимости Python из requirements.txt
RUN pip install --no-cache-dir -r requirements.txt

# Копируем остальные файлы в рабочую директорию
COPY . .

# Копируем SSL-сертификат и ключ в контейнер
COPY /etc/letsencrypt/live/licensure.tech/fullchain.pem /etc/letsencrypt/live/licensure.tech/
COPY /etc/letsencrypt/live/licensure.tech/privkey.pem /etc/letsencrypt/live/licensure.tech/

# Копируем секретный ключ из /etc/environment в контейнер
COPY /etc/environment /etc/environment

# Даем права на исполнение скрипту start_gunicorn.sh
RUN chmod +x start_gunicorn.sh

# Открываем порт 8082
EXPOSE 8082

# Запускаем скрипт start_gunicorn.sh при старте контейнера
CMD ["./start_gunicorn.sh"]
15 changes: 15 additions & 0 deletions __init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address

app = Flask(__name__)

limiter = Limiter(
get_remote_address,
app=app,
default_limits=["10 per minute"],
storage_uri="memory://"
)

# Импорт модулей
import views, auth, logic
34 changes: 34 additions & 0 deletions auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import jwt
from functools import wraps
from flask import request, jsonify
import os

SECRET_KEY = os.environ.get('SECRET_KEY')

def token_required(f):
@wraps(f)
def decorated(*args, **kwargs):
token = None

# Извлекаю токен из заголовка Authorization
if 'Authorization' in request.headers:
token = request.headers['Authorization'].replace("Bearer ", "")

# Если токен отсутствует, верну ошибку
if not token:
return jsonify({'message': 'Token is missing!'}), 403

try:
# Декодирование токена
jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
except jwt.ExpiredSignatureError:
return jsonify({'message': 'Token has expired'}), 403
except jwt.InvalidTokenError:
return jsonify({'message': 'Token is invalid'}), 403
except Exception:
return jsonify({'message': 'An error occurred while validating the token'}), 500

# Передаю управление декорированной функции
return f(*args, **kwargs)

return decorated
16 changes: 16 additions & 0 deletions deploy/deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/bin/bash

# Остановить и удалить старый контейнер, если он существует
docker stop back || true
docker rm back || true

# Удалить старый образ
docker rmi aleksglebov/licensure:back || true

# Получить последнюю версию образа из Docker Hub
docker pull aleksglebov/licensure:back

# Запустить новый контейнер
docker run -p 8082:8082 -d --name back aleksglebov/licensure:back

echo "Deployment completed successfully."
9 changes: 9 additions & 0 deletions deploy/request_handler.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#!/bin/bash

echo -e "HTTP/1.1 200 OK\r"
echo -e "Content-Type: text/plain\r"
echo -e "Connection: close\r"
echo -e "\r"
echo -e "Received request"

bash /home/defendershow/backend/deploy/webhook.sh
4 changes: 4 additions & 0 deletions deploy/socat_start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Запускает socat на порту 8888, обрабатывая каждое новое подключение с помощью request_handler.sh
socat TCP-LISTEN:8890,reuseaddr,fork EXEC:./request_handler.sh
13 changes: 13 additions & 0 deletions deploy/webhook.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#!/bin/bash

# Путь к скрипту deploy.sh
DEPLOY_SCRIPT=/home/defendershow/backend/deploy/deploy.sh

# Отправить заголовки HTTP
echo -e "HTTP/1.1 200 OK\nContent-Type: text/plain\n"

# Запустить скрипт развертывания
$DEPLOY_SCRIPT

# Вернуть ответ веб-хуку
echo "Deployment triggered successfully."
7 changes: 7 additions & 0 deletions generate_secret.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

# Генерируем случайный секретный ключ
SECRET_KEY=$(openssl rand -base64 32)

# Добавляем секретный ключ в файл /etc/environment
echo "SECRET_KEY='$SECRET_KEY'" | sudo tee -a /etc/environment
12 changes: 12 additions & 0 deletions logic.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import logging
import os
import jwt
import sqlite3
from datetime import datetime, timedelta

# Настройка логирования
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)

# Определение пути к файлу базы данных в поддиректории 'data'
db_path = os.path.join('data', 'gv.db')
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PyJWT
Flask-Limiter
Flask
7 changes: 7 additions & 0 deletions start_gunicorn.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash

gunicorn --certfile=/etc/letsencrypt/live/licensure.tech/fullchain.pem \
--keyfile=/etc/letsencrypt/live/licensure.tech/privkey.pem \
--bind 0.0.0.0:8082 \
--workers 3 \
app
16 changes: 16 additions & 0 deletions views.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import logging
from flask import jsonify, request
from .auth import token_required
from . import app
from . import logic
from . import limiter

# Настройка логирования
logging.basicConfig(format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)

@app.route('/api/test', methods=['GET'])
@limiter.limit("10 per minute")
@token_required
def test():
return jsonify({'test': "ok"}), 200

0 comments on commit 241b734

Please sign in to comment.