skeleton done
This commit is contained in:
parent
7349e8e035
commit
28ee777ed1
1
.gitignore
vendored
1
.gitignore
vendored
@ -127,3 +127,4 @@ dmypy.json
|
|||||||
|
|
||||||
# Pyre type checker
|
# Pyre type checker
|
||||||
.pyre/
|
.pyre/
|
||||||
|
.idea/
|
19
Dockerfile
Normal file
19
Dockerfile
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
FROM python:3.9-slim
|
||||||
|
|
||||||
|
ENV TZ Europe/Budapest
|
||||||
|
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
ARG RELEASE_ID
|
||||||
|
ENV RELEASE_ID ${RELEASE_ID:-""}
|
||||||
|
|
||||||
|
COPY requirements.txt ./
|
||||||
|
|
||||||
|
RUN pip install --no-cache-dir -r requirements.txt && rm -rf requirements.txt
|
||||||
|
|
||||||
|
COPY ./src .
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
ENTRYPOINT ["gunicorn", "-b", "0.0.0.0:8080", "--workers", "4", "--threads", "1", "app:app"]
|
13
requirements.txt
Normal file
13
requirements.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
flask
|
||||||
|
flask-classful
|
||||||
|
flask-security
|
||||||
|
flask-admin
|
||||||
|
gunicorn
|
||||||
|
sentry-sdk[flask]
|
||||||
|
py-healthcheck
|
||||||
|
marshmallow
|
||||||
|
flask-marshmallow
|
||||||
|
sqlalchemy
|
||||||
|
flask-sqlalchemy
|
||||||
|
marshmallow-sqlalchemy
|
||||||
|
flask-cors
|
71
src/app.py
Normal file
71
src/app.py
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import logging
|
||||||
|
from flask import Flask
|
||||||
|
import sentry_sdk
|
||||||
|
from sentry_sdk.integrations.flask import FlaskIntegration
|
||||||
|
from sentry_sdk.integrations.sqlalchemy import SqlalchemyIntegration
|
||||||
|
from healthcheck import HealthCheck
|
||||||
|
|
||||||
|
from utils.config import SENTRY_DSN, RELEASE_ID, RELEASEMODE, POSTGRES_DB, PORT, POSTGRES_HOSTNAME, POSTGRES_PASSWORD, \
|
||||||
|
POSTGRES_USERNAME, DEBUG, SECRET_KEY
|
||||||
|
from utils import db, ma, health_database_status, security, user_datastore
|
||||||
|
|
||||||
|
"""
|
||||||
|
Main Flask entrypoint
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "@tormakris"
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "app"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
if SENTRY_DSN:
|
||||||
|
sentry_sdk.init(
|
||||||
|
dsn=SENTRY_DSN,
|
||||||
|
integrations=[FlaskIntegration(), SqlalchemyIntegration()],
|
||||||
|
traces_sample_rate=1.0,
|
||||||
|
send_default_pii=True,
|
||||||
|
release=RELEASE_ID,
|
||||||
|
environment=RELEASEMODE,
|
||||||
|
_experiments={"auto_enabling_integrations": True}
|
||||||
|
)
|
||||||
|
|
||||||
|
app = Flask(__name__)
|
||||||
|
app.config['SQLALCHEMY_DATABASE_URI'] = \
|
||||||
|
f"postgresql://{POSTGRES_USERNAME}:{POSTGRES_PASSWORD}@{POSTGRES_HOSTNAME}:5432/{POSTGRES_DB}"
|
||||||
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
app.config['SECRET_KEY'] = SECRET_KEY
|
||||||
|
|
||||||
|
health = HealthCheck()
|
||||||
|
db.init_app(app)
|
||||||
|
ma.init_app(app)
|
||||||
|
security.init_app(app, user_datastore)
|
||||||
|
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
fmt="%(asctime)s - %(levelname)s - %(module)s - %(message)s"
|
||||||
|
)
|
||||||
|
|
||||||
|
handler = logging.StreamHandler()
|
||||||
|
handler.setFormatter(formatter)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
logger.setLevel(logging.DEBUG)
|
||||||
|
logger.addHandler(handler)
|
||||||
|
|
||||||
|
# api.add_resource(SampleResource, "/sample")
|
||||||
|
|
||||||
|
health.add_check(health_database_status)
|
||||||
|
app.add_url_rule("/healthz", "healthcheck", view_func=lambda: health.run())
|
||||||
|
|
||||||
|
|
||||||
|
@app.before_first_request
|
||||||
|
def init_db():
|
||||||
|
db.create_all()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app.run(
|
||||||
|
debug=bool(DEBUG),
|
||||||
|
host="0.0.0.0",
|
||||||
|
port=int(PORT),
|
||||||
|
)
|
2
src/models/__init__.py
Normal file
2
src/models/__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
from .user import User
|
||||||
|
from .role import Role
|
24
src/models/role.py
Normal file
24
src/models/role.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from flask_security import RoleMixin
|
||||||
|
|
||||||
|
from utils import db
|
||||||
|
|
||||||
|
"""
|
||||||
|
Database models
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "user"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
|
||||||
|
roles_users = db.Table('roles_users',
|
||||||
|
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
|
||||||
|
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
|
||||||
|
|
||||||
|
|
||||||
|
class Role(db.Model, RoleMixin):
|
||||||
|
id = db.Column(db.Integer(), primary_key=True)
|
||||||
|
name = db.Column(db.String(80), unique=True)
|
||||||
|
description = db.Column(db.String(255))
|
24
src/models/user.py
Normal file
24
src/models/user.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from flask_security import UserMixin
|
||||||
|
|
||||||
|
from .role import roles_users
|
||||||
|
from utils import db
|
||||||
|
|
||||||
|
"""
|
||||||
|
Database models
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "user"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
|
||||||
|
class User(db.Model, UserMixin):
|
||||||
|
id = db.Column(db.Integer, primary_key=True)
|
||||||
|
email = db.Column(db.String(255), unique=True)
|
||||||
|
password = db.Column(db.String(255))
|
||||||
|
active = db.Column(db.Boolean())
|
||||||
|
confirmed_at = db.Column(db.DateTime())
|
||||||
|
roles = db.relationship('Role', secondary=roles_users,
|
||||||
|
backref=db.backref('users', lazy='dynamic'))
|
45
src/templates/base.html
Normal file
45
src/templates/base.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<!-- Required meta tags -->
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<!-- Bootstrap CSS -->
|
||||||
|
<link rel="stylesheet" href="https://bootswatch.com/4/darkly/bootstrap.min.css">
|
||||||
|
<title>My Store Web App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-expand-lg navbar-dark bg-primary mb-3">
|
||||||
|
<div class="container">
|
||||||
|
<a class="navbar-brand" href="{{ url_for('index') }}">UnstableVortex CAFF Store</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent"
|
||||||
|
aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
|
<ul class="navbar-nav mr-auto">
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{{ url_for('index') }}">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{{ url_for('profile') }}">Profile</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{{ url_for('login') }}">Login</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item active">
|
||||||
|
<a class="nav-link" href="{{ url_for('register') }}">Register</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
<form class="form-inline my-2 my-lg-0">
|
||||||
|
<input class="form-control mr-sm-2" type="text" placeholder="Search">
|
||||||
|
<button class="btn btn-secondary my-2 my-sm-0" type="submit">Search</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="container px-2">
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
25
src/templates/index.html
Normal file
25
src/templates/index.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
{% if images %}
|
||||||
|
<div class="row mx-2">
|
||||||
|
{% for image in images %}
|
||||||
|
<div class="col-12 col-sm-6 col-md-4 px-2 mb-3">
|
||||||
|
<div class="card">
|
||||||
|
<a href="{{ url_for('item', id=image.id) }}">
|
||||||
|
<img src="{{image.preview}}" class="img-fluid" style="padding: 30px" alt="{{image.caption}}">
|
||||||
|
</a>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{image.creator}}</h5>
|
||||||
|
<p class="card-text">
|
||||||
|
{{image.caption}}
|
||||||
|
</p>
|
||||||
|
<a href="{{ url_for('download', id=image.id) }}" class="btn btn-primary" target="_blank">Download Now</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p>No images available.</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
73
src/templates/item.html
Normal file
73
src/templates/item.html
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="card mb-3">
|
||||||
|
<h3 class="card-header">Animation by {{ image.creator }}</h3>
|
||||||
|
<!-- <div class="card-body">-->
|
||||||
|
<!-- <h5 class="card-title">Special title treatment</h5>-->
|
||||||
|
<!-- <h6 class="card-subtitle text-muted">Support card subtitle</h6>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<img src="{{image.preview}}" class="card-img" style="padding: 30px" alt="{{image.caption}}">
|
||||||
|
<div class="card-body">
|
||||||
|
<p class="card-text">{{ image.caption }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-responsive">
|
||||||
|
<tbody>
|
||||||
|
<tr class="table-active">
|
||||||
|
<th scope="row">Creator</th>
|
||||||
|
<td>{{ image.creator }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="table-active">
|
||||||
|
<th scope="row">Number of images</th>
|
||||||
|
<td>{{ image.num_anim }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr class="table-active">
|
||||||
|
<th scope="row">Creation date</th>
|
||||||
|
<td>{{ image.creation_date }}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<a href="{{ url_for('download', id=image.id) }}" class="card-link" target="_blank">Download</a>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer text-muted">
|
||||||
|
Uploaded: {{ image.upload_date }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<form>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Write a comment</legend>
|
||||||
|
<div class="form-group">
|
||||||
|
<textarea class="form-control" id="commentTextarea" rows="3" ,
|
||||||
|
placeholder="Type your comment here"></textarea>
|
||||||
|
</div>
|
||||||
|
<button type="submit" class="btn btn-primary">Submit</button>
|
||||||
|
</fieldset>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if comments %}
|
||||||
|
{% for comment in comments %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h4 class="card-title">{{ comment.user }}</h4>
|
||||||
|
<h6 class="card-subtitle mb-2 text-muted">{{ comment.date }}</h6>
|
||||||
|
<p class="card-text">{{ comment.text }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<p>No comments yet.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
17
src/templates/login.html
Normal file
17
src/templates/login.html
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1 class="display-3">Please sign in</h1>
|
||||||
|
<br>
|
||||||
|
<form action="" method="post">
|
||||||
|
<input size="50" type="text" class="form-control" placeholder="Username" name="username" value="{{request.form.username}}"></br></br>
|
||||||
|
<input type="password" class="form-control" placeholder="Password" name="password" value="{{request.form.password}}"></br></br>
|
||||||
|
<input class="btn btn-primary" type="submit" value="Sign In"></br></br>
|
||||||
|
</form>
|
||||||
|
<p>Dont't have an account? <a class="bottom" href="{{ url_for('register') }}"> Sign Up here</a></p>
|
||||||
|
{% if error %}
|
||||||
|
<p class="error"><strong>Error:</strong> {{ error }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
37
src/templates/profile.html
Normal file
37
src/templates/profile.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<div>
|
||||||
|
<h1>Welcome {{ user.username }}</h1>
|
||||||
|
<a href="upload.html" class="btn btn-primary">Upload</a>
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
{% if images %}
|
||||||
|
<div class="row mx-2">
|
||||||
|
{% for image in images %}
|
||||||
|
<div class="col-12 col-sm-6 col-md-4 px-2 mb-3">
|
||||||
|
<div class="card">
|
||||||
|
<a href="{{ url_for('item', id=image.id) }}">
|
||||||
|
<img src="{{image.preview}}" class="img-fluid" style="padding: 30px" alt="{{image.caption}}">
|
||||||
|
</a>
|
||||||
|
<div class="card-body">
|
||||||
|
<h5 class="card-title">{{image.creator}}</h5>
|
||||||
|
<p class="card-text">
|
||||||
|
{{image.caption}}
|
||||||
|
</p>
|
||||||
|
<a href="{{ url_for('download', id=image.id) }}" class="btn btn-primary" target="_blank">Download</a>
|
||||||
|
<a href="{{ url_for('delete', id=image.id) }}" class="btn btn-primary" target="_blank">Delete</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
<p>No images available.</p>
|
||||||
|
{% endif %}
|
||||||
|
{% else %}
|
||||||
|
<p><a href="{{ url_for('login') }}">Log in</a> to view your profile.</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
18
src/templates/register.html
Normal file
18
src/templates/register.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1 class="display-3">Please sign up</h1>
|
||||||
|
<br>
|
||||||
|
<form action="" method="post">
|
||||||
|
<input type="text" class="form-control" placeholder="Username" name="username" value="{{request.form.username}}"></br></br>
|
||||||
|
<input type="password" class="form-control" placeholder="Password" name="password" value="{{request.form.password}}"></br></br>
|
||||||
|
<input type="email" class="form-control" placeholder="Email" name="email" value="{{request.form.email}}"></br></br>
|
||||||
|
<input class="btn btn-primary" type="submit" value="Sign Up"></br></br>
|
||||||
|
</form>
|
||||||
|
<p class="bottom">Already have an account? <a class="bottom" href="{{ url_for('login') }}"> Sign In here</a></p>
|
||||||
|
{% if error %}
|
||||||
|
<p class="error"><strong>Error:</strong> {{ error }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
16
src/templates/upload.html
Normal file
16
src/templates/upload.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
{% extends 'webapp/base.html' %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
{% if current_user.is_authenticated %}
|
||||||
|
<div class="jumbotron">
|
||||||
|
<h1 class="display-3">File Upload</h1>
|
||||||
|
<br>
|
||||||
|
<form method="POST" action="" enctype="multipart/form-data">
|
||||||
|
<p><input type="file" name="file" accept=".caff"></p>
|
||||||
|
<p><input type="submit" value="Submit" class="btn btn-primary"></p>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p><a href="{{ url_for('login') }}">Log in</a> to upload an animation.</p>
|
||||||
|
{% endif %}
|
||||||
|
{% endblock %}
|
4
src/utils/__init__.py
Normal file
4
src/utils/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from .db import db
|
||||||
|
from .marshm import ma
|
||||||
|
from .healthchecks import health_database_status
|
||||||
|
from .security import security, user_datastore
|
27
src/utils/config.py
Normal file
27
src/utils/config.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import os
|
||||||
|
|
||||||
|
"""
|
||||||
|
Configuration
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
__author__ = "@tormakris"
|
||||||
|
__copyright__ = "Copyright 2020, Birbnetes Team"
|
||||||
|
__module_name__ = "config"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
|
||||||
|
PORT = os.environ.get("PORT", 8080)
|
||||||
|
DEBUG = os.environ.get("DEBUG", True)
|
||||||
|
|
||||||
|
SENTRY_DSN = os.environ.get("SENTRY_DSN")
|
||||||
|
RELEASE_ID = os.environ.get("RELEASE_ID", "test")
|
||||||
|
RELEASEMODE = os.environ.get("RELEASEMODE", "dev")
|
||||||
|
|
||||||
|
POSTGRES_HOSTNAME = os.getenv("POSTGRES_HOSTNAME", "localhost")
|
||||||
|
POSTGRES_USERNAME = os.getenv("POSTGRES_USERNAME", "webshop")
|
||||||
|
POSTGRES_PASSWORD = os.getenv("POSTGRES_PASSWORD", "webshop")
|
||||||
|
POSTGRES_DB = os.getenv("POSTGRES_DB", "webshop")
|
||||||
|
|
||||||
|
SECRET_KEY = os.getenv("SECRET_KEY")
|
13
src/utils/db.py
Normal file
13
src/utils/db.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
|
|
||||||
|
"""
|
||||||
|
Databse object
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "db"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
db = SQLAlchemy()
|
23
src/utils/healthchecks.py
Normal file
23
src/utils/healthchecks.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from .db import db
|
||||||
|
|
||||||
|
"""
|
||||||
|
Healthchek functions
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = "@tormakris"
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "healthchecks"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
|
||||||
|
def health_database_status():
|
||||||
|
is_database_working = True
|
||||||
|
output = 'database is ok'
|
||||||
|
try:
|
||||||
|
db.session.execute('SELECT 1')
|
||||||
|
except Exception as e:
|
||||||
|
output = str(e)
|
||||||
|
is_database_working = False
|
||||||
|
return is_database_working, output
|
14
src/utils/marshm.py
Normal file
14
src/utils/marshm.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from flask_marshmallow import Marshmallow
|
||||||
|
|
||||||
|
"""
|
||||||
|
Marshmallow
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "marshm"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
ma = Marshmallow()
|
18
src/utils/security.py
Normal file
18
src/utils/security.py
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
"""
|
||||||
|
Flask-Security
|
||||||
|
"""
|
||||||
|
|
||||||
|
__author__ = '@tormakris'
|
||||||
|
__copyright__ = "Copyright 2020, UnstableVortex Team"
|
||||||
|
__module_name__ = "security"
|
||||||
|
__version__text__ = "1"
|
||||||
|
|
||||||
|
from flask_security import Security, SQLAlchemyUserDatastore
|
||||||
|
|
||||||
|
from models import User, Role
|
||||||
|
from utils import db
|
||||||
|
|
||||||
|
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
||||||
|
security = Security()
|
Loading…
Reference in New Issue
Block a user