first commit

This commit is contained in:
CHIEFSOFT\ameye
2025-05-03 22:16:10 -04:00
commit 108378a31e
33 changed files with 1624 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
APP_PORT=14500
FLASK_APP=project/__init__.py
FLASK_DEBUG=1
SOCKET_URL=https://dev-socket.mermsemr.com
PANEL_URL=https://dev-panel.mermsemr.com
DATABASE_URL=postgresql://merms_panel:merms_panel@10.20.30.60:5432/merms_panel
SQL_HOST=10.20.30.60
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/usr/src/app
INITIAL_PRODUCT_URL=devprov.mermsemr.com
MAIL_SERVER=smtp.gmail.com
MAIL_PORT= 465
MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
JWT_SECRET=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
+16
View File
@@ -0,0 +1,16 @@
APP_PORT=14500
FLASK_APP=project/__init__.py
FLASK_DEBUG=1
SOCKET_URL=https://dev-socket.mermsemr.com
PANEL_URL=https://dev-panel.mermsemr.com
DATABASE_URL=postgresql://merms_panel:merms_panel@10.20.30.60:5432/merms_panel
SQL_HOST=10.20.30.60
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/usr/src/app
INITIAL_PRODUCT_URL=devprov.mermsemr.com
MAIL_SERVER=smtp.gmail.com
MAIL_PORT= 465
MAIL_USERNAME=message@chiefsoft.com
MAIL_PASSWORD=may12002!
JWT_SECRET=dce6bd64f7d7101de4fed7cfc185a12851611a79bd60bbfdcc5b414b85f1fdb75e0905691c2a77ce94a7351b261fab4e183e17731ed40089f68f7290a793119f285d8ec7902d248ce15e8b1d4996ebacf5e7bcb06a38ac7ce0736f17d5c2895a499661d27095ac20aa174f9af2fba9a849dd2e6fd0aad8aa7e1ecc030c11eb8dc8dcb71d32233de3530d04f85918b9582f8b02587a7350aa34232825d4831707c7c5775026f3fdd92c5df555e6ff8b785525922709830206bbd49c371fb6e16bcab01ffccaf904108bb9789c578bce6afbb33bc77960051e680b2428d1f026473e71ef0f9997b2a6dc496e1c40509a1d289e3ff8b384c2d49e1d7719f9f4aaa1
+17
View File
@@ -0,0 +1,17 @@
FLASK_APP=project/__init__.py
FLASK_DEBUG=1
DATABASE_URL=postgresql://hello_flask:hello_flask@db:5432/hello_flask_dev
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/usr/src/app
FLASK_APP=project/__init__.py
FLASK_DEBUG=1
DATABASE_URL=postgresql://hello_flask:hello_flask@db:5432/hello_flask_dev
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/usr/src/app
+7
View File
@@ -0,0 +1,7 @@
FLASK_APP=project/__init__.py
FLASK_DEBUG=0
DATABASE_URL=postgresql://hello_flask:hello_flask@db:5432/hello_flask_prod
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/home/app/web
+3
View File
@@ -0,0 +1,3 @@
POSTGRES_USER=hello_flask
POSTGRES_PASSWORD=hello_flask
POSTGRES_DB=hello_flask_prod
+8
View File
@@ -0,0 +1,8 @@
*.pyc
__pycache
.DS_Store
#.env.dev
#.env.prod
.env.prod.db
postgres_data
postgres_data*
+8
View File
@@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="jdk" jdkName="Python 3.11" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="PyDocumentationSettings">
<option name="format" value="PLAIN" />
<option name="myDocStringFormat" value="Plain" />
</component>
</module>
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
+6
View File
@@ -0,0 +1,6 @@
<component name="InspectionProjectProfileManager">
<settings>
<option name="USE_PROJECT_PROFILE" value="false" />
<version value="1.0" />
</settings>
</component>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Black">
<option name="sdkName" value="Python 3.11" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.11" project-jdk-type="Python SDK" />
</project>
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/MyFit-CoreBackEnd.iml" filepath="$PROJECT_DIR$/.idea/MyFit-CoreBackEnd.iml" />
</modules>
</component>
</project>
Generated
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 TestDriven.io
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+47
View File
@@ -0,0 +1,47 @@
# Dockerizing Flask with Postgres, Gunicorn, and Nginx
## Want to learn how to build this?
Check out the [tutorial](https://testdriven.io/blog/dockerizing-flask-with-postgres-gunicorn-and-nginx).
## Want to use this project?
### Development
Uses the default Flask development server.
1. Rename *.env.dev-sample* to *.env.dev*.
1. Update the environment variables in the *docker-compose.yml* and *.env.dev* files.
- (M1 chip only) Remove `-slim-buster` from the Python dependency in `services/web/Dockerfile` to suppress an issue with installing psycopg2
1. Build the images and run the containers:
```sh
$ docker-compose up -d --build
```
Test it out at [http://localhost:5001](http://localhost:5001). The "web" folder is mounted into the container and your code changes apply automatically.
### Production
Uses gunicorn + nginx.
1. Rename *.env.prod-sample* to *.env.prod* and *.env.prod.db-sample* to *.env.prod.db*. Update the environment variables.
1. Build the images and run the containers:
```sh
$ docker-compose -f docker-compose.prod.yml up -d --build
```
Test it out at [http://localhost:1337](http://localhost:1337). No mounted folders. To apply changes, the image must be re-built.
git init
git add .
git commit -m "first commit"
git remote add origin https://gitlab.chiefsoft.net/MERMS/MermsCoreBackendFlask.git
git push -u origin master
+20
View File
@@ -0,0 +1,20 @@
version: '3.8'
services:
myfit-corebackend:
build: ./services/web
command: python manage.py run -h 0.0.0.0
volumes:
- ./services/web/:/usr/src/app/
ports:
- "${APP_PORT:-14500}:5000"
env_file:
- ./.env.dev
restart: always
#networks:
# default:
## driver: bridge
# ipam:
# config:
# - subnet: 10.10.33.0/24
+13
View File
@@ -0,0 +1,13 @@
version: '3.8'
services:
myfit-corebackend:
build: ./services/web
command: python manage.py run -h 0.0.0.0
volumes:
- ./services/web/:/usr/src/app/
ports:
- "${APP_PORT:-14500}:5000"
env_file:
- ./.env.dev
restart: always
+7
View File
@@ -0,0 +1,7 @@
FLASK_APP=project/__init__.py
FLASK_DEBUG=1
DATABASE_URL=postgresql://hello_flask:hello_flask@db:5432/hello_flask_dev
SQL_HOST=db
SQL_PORT=5432
DATABASE=postgres
APP_FOLDER=/usr/src/app
+4
View File
@@ -0,0 +1,4 @@
FROM nginx:1.25
RUN rm /etc/nginx/conf.d/default.conf
COPY nginx.conf /etc/nginx/conf.d
+24
View File
@@ -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/;
}
}
+23
View File
@@ -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"]
+69
View File
@@ -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"]
+2
View File
@@ -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>
+14
View File
@@ -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 "$@"
+16
View File
@@ -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 "$@"
+23
View File
@@ -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
+11
View File
@@ -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"
View File
+95
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
hi!
+45
View File
@@ -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
+15
View File
@@ -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