first commit
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
FROM nginx:1.25
|
||||
|
||||
RUN rm /etc/nginx/conf.d/default.conf
|
||||
COPY nginx.conf /etc/nginx/conf.d
|
||||
@@ -0,0 +1,24 @@
|
||||
upstream hello_flask {
|
||||
server web:5000;
|
||||
}
|
||||
|
||||
server {
|
||||
|
||||
listen 80;
|
||||
|
||||
location / {
|
||||
proxy_pass http://hello_flask;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header Host $host;
|
||||
proxy_redirect off;
|
||||
}
|
||||
|
||||
location /static/ {
|
||||
alias /home/app/web/project/static/;
|
||||
}
|
||||
|
||||
location /media/ {
|
||||
alias /home/app/web/project/media/;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
# pull official base image
|
||||
FROM python:3.11.3-slim-buster
|
||||
|
||||
# set work directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# set environment variables
|
||||
ENV PYTHONDONTWRITEBYTECODE 1
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
# install system dependencies
|
||||
RUN apt-get update && apt-get install -y netcat
|
||||
|
||||
# install dependencies
|
||||
RUN pip install --upgrade pip
|
||||
COPY ./requirements.txt /usr/src/app/requirements.txt
|
||||
RUN pip install -r requirements.txt
|
||||
|
||||
# copy project
|
||||
COPY . /usr/src/app/
|
||||
|
||||
# run entrypoint.sh
|
||||
ENTRYPOINT ["/usr/src/app/entrypoint.sh"]
|
||||
@@ -0,0 +1,69 @@
|
||||
###########
|
||||
# BUILDER #
|
||||
###########
|
||||
|
||||
# pull official base image
|
||||
FROM python:3.11.3-slim-buster as builder
|
||||
|
||||
# set work directory
|
||||
WORKDIR /usr/src/app
|
||||
|
||||
# set environment variables
|
||||
ENV PYTHONDONTWRITEBYTECODE 1
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
# install system dependencies
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends gcc
|
||||
|
||||
# lint
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install flake8==6.0.0
|
||||
COPY . /usr/src/app/
|
||||
RUN flake8 --ignore=E501,F401 .
|
||||
|
||||
# install python dependencies
|
||||
COPY ./requirements.txt .
|
||||
RUN pip wheel --no-cache-dir --no-deps --wheel-dir /usr/src/app/wheels -r requirements.txt
|
||||
|
||||
|
||||
#########
|
||||
# FINAL #
|
||||
#########
|
||||
|
||||
# pull official base image
|
||||
FROM python:3.11.3-slim-buster
|
||||
|
||||
# create directory for the app user
|
||||
RUN mkdir -p /home/app
|
||||
|
||||
# create the app user
|
||||
RUN addgroup --system app && adduser --system --group app
|
||||
|
||||
# create the appropriate directories
|
||||
ENV HOME=/home/app
|
||||
ENV APP_HOME=/home/app/web
|
||||
RUN mkdir $APP_HOME
|
||||
WORKDIR $APP_HOME
|
||||
|
||||
# install dependencies
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends netcat
|
||||
COPY --from=builder /usr/src/app/wheels /wheels
|
||||
COPY --from=builder /usr/src/app/requirements.txt .
|
||||
RUN pip install --upgrade pip
|
||||
RUN pip install --no-cache /wheels/*
|
||||
|
||||
# copy entrypoint-prod.sh
|
||||
COPY ./entrypoint.prod.sh $APP_HOME
|
||||
|
||||
# copy project
|
||||
COPY . $APP_HOME
|
||||
|
||||
# chown all the files to the app user
|
||||
RUN chown -R app:app $APP_HOME
|
||||
|
||||
# change to the app user
|
||||
USER app
|
||||
|
||||
# run entrypoint.prod.sh
|
||||
ENTRYPOINT ["/home/app/web/entrypoint.prod.sh"]
|
||||
@@ -0,0 +1,2 @@
|
||||
Hello MERMS message sent for account verification
|
||||
<a href='https://works.mermsemr.com/csignup/JWT-djhgdhjgdhdggggd'>https://works.mermsemr.com/csignup/JWT-djhgdhjgdhdggggd</a>
|
||||
@@ -0,0 +1,14 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$DATABASE" = "postgres" ]
|
||||
then
|
||||
echo "Waiting for postgres..."
|
||||
|
||||
while ! nc -z $SQL_HOST $SQL_PORT; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo "PostgreSQL started"
|
||||
fi
|
||||
|
||||
exec "$@"
|
||||
@@ -0,0 +1,16 @@
|
||||
#!/bin/sh
|
||||
|
||||
if [ "$DATABASE" = "postgres" ]
|
||||
then
|
||||
echo "Waiting for postgres..."
|
||||
|
||||
while ! nc -z $SQL_HOST $SQL_PORT; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
echo "PostgreSQL started"
|
||||
fi
|
||||
|
||||
python manage.py create_db
|
||||
|
||||
exec "$@"
|
||||
@@ -0,0 +1,23 @@
|
||||
from flask.cli import FlaskGroup
|
||||
|
||||
from project import app, db, User
|
||||
|
||||
|
||||
cli = FlaskGroup(app)
|
||||
|
||||
|
||||
@cli.command("create_db")
|
||||
def create_db():
|
||||
db.drop_all()
|
||||
db.create_all()
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@cli.command("seed_db")
|
||||
def seed_db():
|
||||
db.session.add(User(email="michael@mherman.org"))
|
||||
db.session.commit()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
cli()
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
||||
import os
|
||||
|
||||
|
||||
basedir = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
|
||||
class Config(object):
|
||||
SQLALCHEMY_DATABASE_URI = os.getenv("DATABASE_URL", "sqlite://")
|
||||
SQLALCHEMY_TRACK_MODIFICATIONS = False
|
||||
STATIC_FOLDER = f"{os.getenv('APP_FOLDER')}/project/static"
|
||||
MEDIA_FOLDER = f"{os.getenv('APP_FOLDER')}/project/media"
|
||||
@@ -0,0 +1,95 @@
|
||||
"""Application Members Models"""
|
||||
import os
|
||||
# bson,
|
||||
from dotenv import load_dotenv
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
import psycopg2
|
||||
from psycopg2.extras import NamedTupleCursor
|
||||
import pandas as pd
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# DATABASE_URL=os.environ.get('DATABASE_URL') or 'mongodb://localhost:27017/myDatabase'
|
||||
# print(DATABASE_URL)
|
||||
# client = MongoClient(DATABASE_URL)
|
||||
# db = client.myDatabase
|
||||
|
||||
dataUrl = os.getenv("DATABASE_URL")
|
||||
db = psycopg2.connect(dataUrl)
|
||||
|
||||
|
||||
class Members:
|
||||
"""User Model"""
|
||||
def __init__(self):
|
||||
return
|
||||
|
||||
|
||||
def get_member_by_uid(self, user_uid):
|
||||
"""Get a user by uid"""
|
||||
#user = db.members.find_one({"uid": user_uid, "active": True})
|
||||
GLOBAL_AVG = "SELECT username,email,account_name,firstname,lastname FROM members WHERE uid::text = '" + user_uid + "'"
|
||||
#print(GLOBAL_AVG)
|
||||
with db:
|
||||
with db.cursor() as cursor:
|
||||
cursor.execute(GLOBAL_AVG)
|
||||
account = cursor.fetchall()
|
||||
#return jsonify(hello="ameye world")
|
||||
# Convert to DataFrame
|
||||
df = pd.DataFrame(account, columns=[desc[0] for desc in db.description])
|
||||
print(df)
|
||||
if not account:
|
||||
return
|
||||
return account
|
||||
|
||||
|
||||
# def get_by_id(self, user_id):
|
||||
# """Get a user by id"""
|
||||
# user = db.users.find_one({"_id": bson.ObjectId(user_id), "active": True})
|
||||
# if not user:
|
||||
# return
|
||||
# user["_id"] = str(user["_id"])
|
||||
# user.pop("password")
|
||||
# return user
|
||||
|
||||
def get_by_username(self, username):
|
||||
"""Get a user by username"""
|
||||
print(db)
|
||||
# sqv = "SELECT * FROM members WHERE id=%s"
|
||||
# x=["1"]
|
||||
sqv = "SELECT * FROM members WHERE username='"+username+"'"
|
||||
with db:
|
||||
with db.cursor(cursor_factory=NamedTupleCursor) as cursor:
|
||||
#with db.cursor() as cursor:
|
||||
cursor.execute(sqv)
|
||||
#cursor.execute(sqv, x)
|
||||
member = cursor.fetchall()
|
||||
|
||||
if not member:
|
||||
return
|
||||
#member["_id"] = member[0]
|
||||
#str(member[0])
|
||||
return member[0]
|
||||
#return user
|
||||
|
||||
def encrypt_password(self, password):
|
||||
"""Encrypt password"""
|
||||
return generate_password_hash(password)
|
||||
|
||||
def login(self, username, password):
|
||||
"""Login a user"""
|
||||
member = self.get_by_username(username)
|
||||
# print('yyyyyyyyyyy---mmmmmm')
|
||||
# print( member )
|
||||
# print('yyyyyyyyyyy---xxxxxxxxx')
|
||||
|
||||
# for column in member:
|
||||
# print(f"{column}")
|
||||
|
||||
# print( member[3] )
|
||||
# print(self.encrypt_password(password))
|
||||
|
||||
if not member or not check_password_hash(member[3], password):
|
||||
return
|
||||
#member.pop(3)
|
||||
#member[3]=''
|
||||
return member
|
||||
@@ -0,0 +1 @@
|
||||
hi!
|
||||
@@ -0,0 +1,45 @@
|
||||
"""Validator Module"""
|
||||
import re
|
||||
#from bson.objectid import ObjectId
|
||||
|
||||
def validate(data, regex):
|
||||
"""Custom Validator"""
|
||||
return True if re.match(regex, data) else False
|
||||
|
||||
def validate_password(password: str):
|
||||
"""Password Validator"""
|
||||
# print(password)
|
||||
#reg = r"\b^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!#%*?&]{8,20}$\b"
|
||||
reg = r"\b^[A-Za-z0-9@#$%^&+=]{8,}\b"
|
||||
return validate(password, reg)
|
||||
|
||||
def validate_username(username: str):
|
||||
if not 6 <= len(username.split(' ')) <= 20:
|
||||
return {
|
||||
'name': 'Username must be between 6 and 15 words'
|
||||
}
|
||||
return True
|
||||
|
||||
def validate_signup_data(firstname,lastname,email):
|
||||
return True
|
||||
|
||||
def validate_complete_signup_data(username,password,country):
|
||||
return True
|
||||
|
||||
def validate_username_and_password(username, password):
|
||||
"""Username and Password Validator"""
|
||||
if not (username and password):
|
||||
return {
|
||||
'username': 'Username is required',
|
||||
'password': 'Password is required'
|
||||
}
|
||||
if not validate_username(username):
|
||||
return {
|
||||
'username': 'Username is invalid'
|
||||
}
|
||||
if not validate_password(password):
|
||||
return {
|
||||
'password': 'Password is invalid, Should be at least 8 characters with \
|
||||
upper and lower case letters, numbers and special characters'
|
||||
}
|
||||
return True
|
||||
@@ -0,0 +1,15 @@
|
||||
Flask==2.3.2
|
||||
Flask-SQLAlchemy==3.0.3
|
||||
gunicorn==20.1.0
|
||||
psycopg2-binary==2.9.6
|
||||
flask-smorest==0.42.3
|
||||
python-dotenv
|
||||
pyjwt
|
||||
pillow
|
||||
flask-cors
|
||||
pandas
|
||||
flasgger
|
||||
sqlalchemy
|
||||
flask-socketio
|
||||
Flask-Mail
|
||||
pycountry
|
||||
Reference in New Issue
Block a user