Eddie
2 years ago
21 changed files with 434 additions and 280 deletions
Binary file not shown.
@ -1,121 +1,16 @@
|
||||
Creative Commons Legal Code |
||||
|
||||
CC0 1.0 Universal |
||||
|
||||
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE |
||||
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN |
||||
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS |
||||
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES |
||||
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS |
||||
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM |
||||
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED |
||||
HEREUNDER. |
||||
|
||||
Statement of Purpose |
||||
|
||||
The laws of most jurisdictions throughout the world automatically confer |
||||
exclusive Copyright and Related Rights (defined below) upon the creator |
||||
and subsequent owner(s) (each and all, an "owner") of an original work of |
||||
authorship and/or a database (each, a "Work"). |
||||
|
||||
Certain owners wish to permanently relinquish those rights to a Work for |
||||
the purpose of contributing to a commons of creative, cultural and |
||||
scientific works ("Commons") that the public can reliably and without fear |
||||
of later claims of infringement build upon, modify, incorporate in other |
||||
works, reuse and redistribute as freely as possible in any form whatsoever |
||||
and for any purposes, including without limitation commercial purposes. |
||||
These owners may contribute to the Commons to promote the ideal of a free |
||||
culture and the further production of creative, cultural and scientific |
||||
works, or to gain reputation or greater distribution for their Work in |
||||
part through the use and efforts of others. |
||||
|
||||
For these and/or other purposes and motivations, and without any |
||||
expectation of additional consideration or compensation, the person |
||||
associating CC0 with a Work (the "Affirmer"), to the extent that he or she |
||||
is an owner of Copyright and Related Rights in the Work, voluntarily |
||||
elects to apply CC0 to the Work and publicly distribute the Work under its |
||||
terms, with knowledge of his or her Copyright and Related Rights in the |
||||
Work and the meaning and intended legal effect of CC0 on those rights. |
||||
|
||||
1. Copyright and Related Rights. A Work made available under CC0 may be |
||||
protected by copyright and related or neighboring rights ("Copyright and |
||||
Related Rights"). Copyright and Related Rights include, but are not |
||||
limited to, the following: |
||||
|
||||
i. the right to reproduce, adapt, distribute, perform, display, |
||||
communicate, and translate a Work; |
||||
ii. moral rights retained by the original author(s) and/or performer(s); |
||||
iii. publicity and privacy rights pertaining to a person's image or |
||||
likeness depicted in a Work; |
||||
iv. rights protecting against unfair competition in regards to a Work, |
||||
subject to the limitations in paragraph 4(a), below; |
||||
v. rights protecting the extraction, dissemination, use and reuse of data |
||||
in a Work; |
||||
vi. database rights (such as those arising under Directive 96/9/EC of the |
||||
European Parliament and of the Council of 11 March 1996 on the legal |
||||
protection of databases, and under any national implementation |
||||
thereof, including any amended or successor version of such |
||||
directive); and |
||||
vii. other similar, equivalent or corresponding rights throughout the |
||||
world based on applicable law or treaty, and any national |
||||
implementations thereof. |
||||
|
||||
2. Waiver. To the greatest extent permitted by, but not in contravention |
||||
of, applicable law, Affirmer hereby overtly, fully, permanently, |
||||
irrevocably and unconditionally waives, abandons, and surrenders all of |
||||
Affirmer's Copyright and Related Rights and associated claims and causes |
||||
of action, whether now known or unknown (including existing as well as |
||||
future claims and causes of action), in the Work (i) in all territories |
||||
worldwide, (ii) for the maximum duration provided by applicable law or |
||||
treaty (including future time extensions), (iii) in any current or future |
||||
medium and for any number of copies, and (iv) for any purpose whatsoever, |
||||
including without limitation commercial, advertising or promotional |
||||
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each |
||||
member of the public at large and to the detriment of Affirmer's heirs and |
||||
successors, fully intending that such Waiver shall not be subject to |
||||
revocation, rescission, cancellation, termination, or any other legal or |
||||
equitable action to disrupt the quiet enjoyment of the Work by the public |
||||
as contemplated by Affirmer's express Statement of Purpose. |
||||
|
||||
3. Public License Fallback. Should any part of the Waiver for any reason |
||||
be judged legally invalid or ineffective under applicable law, then the |
||||
Waiver shall be preserved to the maximum extent permitted taking into |
||||
account Affirmer's express Statement of Purpose. In addition, to the |
||||
extent the Waiver is so judged Affirmer hereby grants to each affected |
||||
person a royalty-free, non transferable, non sublicensable, non exclusive, |
||||
irrevocable and unconditional license to exercise Affirmer's Copyright and |
||||
Related Rights in the Work (i) in all territories worldwide, (ii) for the |
||||
maximum duration provided by applicable law or treaty (including future |
||||
time extensions), (iii) in any current or future medium and for any number |
||||
of copies, and (iv) for any purpose whatsoever, including without |
||||
limitation commercial, advertising or promotional purposes (the |
||||
"License"). The License shall be deemed effective as of the date CC0 was |
||||
applied by Affirmer to the Work. Should any part of the License for any |
||||
reason be judged legally invalid or ineffective under applicable law, such |
||||
partial invalidity or ineffectiveness shall not invalidate the remainder |
||||
of the License, and in such case Affirmer hereby affirms that he or she |
||||
will not (i) exercise any of his or her remaining Copyright and Related |
||||
Rights in the Work or (ii) assert any associated claims and causes of |
||||
action with respect to the Work, in either case contrary to Affirmer's |
||||
express Statement of Purpose. |
||||
|
||||
4. Limitations and Disclaimers. |
||||
|
||||
a. No trademark or patent rights held by Affirmer are waived, abandoned, |
||||
surrendered, licensed or otherwise affected by this document. |
||||
b. Affirmer offers the Work as-is and makes no representations or |
||||
warranties of any kind concerning the Work, express, implied, |
||||
statutory or otherwise, including without limitation warranties of |
||||
title, merchantability, fitness for a particular purpose, non |
||||
infringement, or the absence of latent or other defects, accuracy, or |
||||
the present or absence of errors, whether or not discoverable, all to |
||||
the greatest extent permissible under applicable law. |
||||
c. Affirmer disclaims responsibility for clearing rights of other persons |
||||
that may apply to the Work or any use thereof, including without |
||||
limitation any person's Copyright and Related Rights in the Work. |
||||
Further, Affirmer disclaims responsibility for obtaining any necessary |
||||
consents, permissions or other rights required for any use of the |
||||
Work. |
||||
d. Affirmer understands and acknowledges that Creative Commons is not a |
||||
party to this document and has no duty or obligation with respect to |
||||
this CC0 or use of the Work. |
||||
MIT No Attribution |
||||
|
||||
Copyright <YEAR> <COPYRIGHT HOLDER> |
||||
|
||||
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. |
||||
|
||||
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. |
||||
|
@ -1,3 +1,3 @@
|
||||
# Markdown-Presenter |
||||
# flask_boilerplate |
||||
|
||||
Ein kleines Projekt um Markdown Dokumente zu Presenten. |
||||
Kleines Startsetup für eine Flask Webapp mit Login und Datenbank |
@ -1,13 +0,0 @@
|
||||
from services import (UserService, UserListService) |
||||
from config import app, api, docs, CORS |
||||
|
||||
#*______________ Service Registration ______________ |
||||
api.add_resource(UserService, '/api/user/<user_id>') |
||||
docs.register(UserService) |
||||
api.add_resource(UserListService, '/api/list/user') |
||||
docs.register(UserListService) |
||||
#*______________ Application Creation ______________ |
||||
if __name__ == '__main__': |
||||
app.run(debug=True) |
||||
|
||||
|
@ -0,0 +1,43 @@
|
||||
import os |
||||
|
||||
from flask import Flask |
||||
|
||||
|
||||
def create_app(test_config=None): |
||||
# create and configure the app |
||||
app = Flask(__name__, instance_relative_config=True) |
||||
app.config.from_mapping( |
||||
SECRET_KEY='dev', |
||||
DATABASE=os.path.join(app.instance_path, 'app.sqlite'), |
||||
) |
||||
|
||||
if test_config is None: |
||||
# load the instance config, if it exists, when not testing |
||||
app.config.from_pyfile('config.py', silent=True) |
||||
else: |
||||
# load the test config if passed in |
||||
app.config.from_mapping(test_config) |
||||
|
||||
# ensure the instance folder exists |
||||
try: |
||||
os.makedirs(app.instance_path) |
||||
except OSError: |
||||
pass |
||||
|
||||
# a simple page that says hello |
||||
@app.route('/hello') |
||||
def hello(): |
||||
return 'Hello, World!' |
||||
|
||||
|
||||
from . import db |
||||
db.init_app(app) |
||||
|
||||
from . import auth |
||||
app.register_blueprint(auth.bp) |
||||
|
||||
from . import index |
||||
app.register_blueprint(index.bp) |
||||
app.add_url_rule('/', endpoint='index') |
||||
|
||||
return app |
@ -0,0 +1,95 @@
|
||||
import functools |
||||
|
||||
from flask import ( |
||||
Blueprint, flash, g, redirect, render_template, request, session, url_for |
||||
) |
||||
from werkzeug.security import check_password_hash, generate_password_hash |
||||
|
||||
from app.db import get_db |
||||
|
||||
bp = Blueprint('auth', __name__, url_prefix='/auth') |
||||
|
||||
|
||||
@bp.route('/register', methods=('GET', 'POST')) |
||||
def register(): |
||||
if request.method == 'POST': |
||||
username = request.form['username'] |
||||
password = request.form['password'] |
||||
db = get_db() |
||||
error = None |
||||
|
||||
if not username: |
||||
error = 'Username is required.' |
||||
elif not password: |
||||
error = 'Password is required.' |
||||
elif db.execute( |
||||
'SELECT id FROM user WHERE username = ?', (username,) |
||||
).fetchone() is not None: |
||||
error = 'User {} is already registered.'.format(username) |
||||
|
||||
if error is None: |
||||
db.execute( |
||||
'INSERT INTO user (username, password) VALUES (?, ?)', |
||||
(username, generate_password_hash(password)) |
||||
) |
||||
db.commit() |
||||
return redirect(url_for('auth.login')) |
||||
|
||||
flash(error) |
||||
|
||||
return render_template('auth/register.html') |
||||
|
||||
|
||||
@bp.route('/login', methods=('GET', 'POST')) |
||||
def login(): |
||||
if request.method == 'POST': |
||||
username = request.form['username'] |
||||
password = request.form['password'] |
||||
db = get_db() |
||||
error = None |
||||
user = db.execute( |
||||
'SELECT * FROM user WHERE username = ?', (username,) |
||||
).fetchone() |
||||
|
||||
if user is None: |
||||
error = 'Incorrect username.' |
||||
elif not check_password_hash(user['password'], password): |
||||
error = 'Incorrect password.' |
||||
|
||||
if error is None: |
||||
session.clear() |
||||
session['user_id'] = user['id'] |
||||
return redirect(url_for('index')) |
||||
|
||||
flash(error) |
||||
|
||||
return render_template('auth/login.html') |
||||
|
||||
|
||||
@bp.before_app_request |
||||
def load_logged_in_user(): |
||||
user_id = session.get('user_id') |
||||
|
||||
if user_id is None: |
||||
g.user = None |
||||
else: |
||||
g.user = get_db().execute( |
||||
'SELECT * FROM user WHERE id = ?', (user_id,) |
||||
).fetchone() |
||||
|
||||
|
||||
@bp.route('/logout') |
||||
def logout(): |
||||
session.clear() |
||||
return redirect(url_for('index')) |
||||
|
||||
|
||||
def login_required(view): |
||||
@functools.wraps(view) |
||||
def wrapped_view(**kwargs): |
||||
if g.user is None: |
||||
return redirect(url_for('auth.login')) |
||||
|
||||
return view(**kwargs) |
||||
|
||||
return wrapped_view |
@ -0,0 +1,41 @@
|
||||
import sqlite3 |
||||
|
||||
import click |
||||
from flask import current_app, g |
||||
from flask.cli import with_appcontext |
||||
|
||||
|
||||
def get_db(): |
||||
if 'db' not in g: |
||||
g.db = sqlite3.connect( |
||||
current_app.config['DATABASE'], |
||||
detect_types=sqlite3.PARSE_DECLTYPES |
||||
) |
||||
g.db.row_factory = sqlite3.Row |
||||
|
||||
return g.db |
||||
|
||||
|
||||
def close_db(e=None): |
||||
db = g.pop('db', None) |
||||
|
||||
if db is not None: |
||||
db.close() |
||||
|
||||
def init_db(): |
||||
db = get_db() |
||||
|
||||
with current_app.open_resource('schema.sql') as f: |
||||
db.executescript(f.read().decode('utf8')) |
||||
|
||||
|
||||
@click.command('init-db') |
||||
@with_appcontext |
||||
def init_db_command(): |
||||
"""Clear the existing data and create new tables.""" |
||||
init_db() |
||||
click.echo('Initialized the database.') |
||||
|
||||
def init_app(app): |
||||
app.teardown_appcontext(close_db) |
||||
app.cli.add_command(init_db_command) |
@ -0,0 +1,23 @@
|
||||
from flask import ( |
||||
Blueprint, flash, g, redirect, render_template, request, url_for |
||||
) |
||||
from werkzeug.exceptions import abort |
||||
|
||||
from app.auth import login_required |
||||
from app.db import get_db |
||||
|
||||
|
||||
bp = Blueprint('index', __name__) |
||||
|
||||
@bp.route('/') |
||||
@login_required |
||||
def index(): |
||||
db = get_db() |
||||
loginEvents = db.execute( |
||||
'SELECT *' |
||||
' FROM loginEvent' |
||||
' ORDER BY created DESC' |
||||
).fetchall() |
||||
return render_template('index.html', loginEvents = loginEvents) |
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
DROP TABLE IF EXISTS user; |
||||
DROP TABLE IF EXISTS post; |
||||
|
||||
CREATE TABLE user ( |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
||||
username TEXT UNIQUE NOT NULL, |
||||
password TEXT NOT NULL |
||||
); |
||||
|
||||
CREATE TABLE loginEvent ( |
||||
id INTEGER PRIMARY KEY AUTOINCREMENT, |
||||
walletId TEXT NOT NULL, |
||||
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, |
||||
eventType TEXT NOT NULL |
||||
); |
@ -0,0 +1,134 @@
|
||||
html { |
||||
font-family: sans-serif; |
||||
background: #eee; |
||||
padding: 1rem; |
||||
} |
||||
|
||||
body { |
||||
max-width: 960px; |
||||
margin: 0 auto; |
||||
background: white; |
||||
} |
||||
|
||||
h1, h2, h3, h4, h5, h6 { |
||||
font-family: serif; |
||||
color: #377ba8; |
||||
margin: 1rem 0; |
||||
} |
||||
|
||||
a { |
||||
color: #377ba8; |
||||
} |
||||
|
||||
hr { |
||||
border: none; |
||||
border-top: 1px solid lightgray; |
||||
} |
||||
|
||||
nav { |
||||
background: lightgray; |
||||
display: flex; |
||||
align-items: center; |
||||
padding: 0 0.5rem; |
||||
} |
||||
|
||||
nav h1 { |
||||
flex: auto; |
||||
margin: 0; |
||||
} |
||||
|
||||
nav h1 a { |
||||
text-decoration: none; |
||||
padding: 0.25rem 0.5rem; |
||||
} |
||||
|
||||
nav ul { |
||||
display: flex; |
||||
list-style: none; |
||||
margin: 0; |
||||
padding: 0; |
||||
} |
||||
|
||||
nav ul li a, nav ul li span, header .action { |
||||
display: block; |
||||
padding: 0.5rem; |
||||
} |
||||
|
||||
.content { |
||||
padding: 0 1rem 1rem; |
||||
} |
||||
|
||||
.content > header { |
||||
border-bottom: 1px solid lightgray; |
||||
display: flex; |
||||
align-items: flex-end; |
||||
} |
||||
|
||||
.content > header h1 { |
||||
flex: auto; |
||||
margin: 1rem 0 0.25rem 0; |
||||
} |
||||
|
||||
.flash { |
||||
margin: 1em 0; |
||||
padding: 1em; |
||||
background: #cae6f6; |
||||
border: 1px solid #377ba8; |
||||
} |
||||
|
||||
.post > header { |
||||
display: flex; |
||||
align-items: flex-end; |
||||
font-size: 0.85em; |
||||
} |
||||
|
||||
.post > header > div:first-of-type { |
||||
flex: auto; |
||||
} |
||||
|
||||
.post > header h1 { |
||||
font-size: 1.5em; |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.post .about { |
||||
color: slategray; |
||||
font-style: italic; |
||||
} |
||||
|
||||
.post .body { |
||||
white-space: pre-line; |
||||
} |
||||
|
||||
.content:last-child { |
||||
margin-bottom: 0; |
||||
} |
||||
|
||||
.content form { |
||||
margin: 1em 0; |
||||
display: flex; |
||||
flex-direction: column; |
||||
} |
||||
|
||||
.content label { |
||||
font-weight: bold; |
||||
margin-bottom: 0.5em; |
||||
} |
||||
|
||||
.content input, .content textarea { |
||||
margin-bottom: 1em; |
||||
} |
||||
|
||||
.content textarea { |
||||
min-height: 12em; |
||||
resize: vertical; |
||||
} |
||||
|
||||
input.danger { |
||||
color: #cc2f2e; |
||||
} |
||||
|
||||
input[type=submit] { |
||||
align-self: start; |
||||
min-width: 10em; |
||||
} |
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %} |
||||
|
||||
{% block header %} |
||||
<h1>{% block title %}Log In{% endblock %}</h1> |
||||
{% endblock %} |
||||
|
||||
{% block content %} |
||||
<form method="post"> |
||||
<label for="username">Username</label> |
||||
<input name="username" id="username" required> |
||||
<label for="password">Password</label> |
||||
<input type="password" name="password" id="password" required> |
||||
<input type="submit" value="Log In"> |
||||
</form> |
||||
{% endblock %} |
@ -0,0 +1,15 @@
|
||||
{% extends 'base.html' %} |
||||
|
||||
{% block header %} |
||||
<h1>{% block title %}Register{% endblock %}</h1> |
||||
{% endblock %} |
||||
|
||||
{% block content %} |
||||
<form method="post"> |
||||
<label for="username">Username</label> |
||||
<input name="username" id="username" required> |
||||
<label for="password">Password</label> |
||||
<input type="password" name="password" id="password" required> |
||||
<input type="submit" value="Register"> |
||||
</form> |
||||
{% endblock %} |
@ -0,0 +1,24 @@
|
||||
<!doctype html> |
||||
<title>{% block title %}{% endblock %} - Flaskr</title> |
||||
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap.css') }}"> |
||||
<nav> |
||||
<h1>Flaskr</h1> |
||||
<ul> |
||||
{% if g.user %} |
||||
<li><span>{{ g.user['username'] }}</span> |
||||
<li><a href="{{ url_for('auth.logout') }}">Log Out</a> |
||||
{% else %} |
||||
<li><a href="{{ url_for('auth.register') }}">Register</a> |
||||
<li><a href="{{ url_for('auth.login') }}">Log In</a> |
||||
{% endif %} |
||||
</ul> |
||||
</nav> |
||||
<section class="content"> |
||||
<header> |
||||
{% block header %}{% endblock %} |
||||
</header> |
||||
{% for message in get_flashed_messages() %} |
||||
<div class="flash">{{ message }}</div> |
||||
{% endfor %} |
||||
{% block content %}{% endblock %} |
||||
</section> |
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html' %} |
||||
|
||||
{% block header %} |
||||
<h1>{% block title %}Login Events{% endblock %}</h1> |
||||
{% endblock %} |
||||
|
||||
{% block content %} |
||||
|
||||
<a>Hello World</a> |
||||
|
||||
{% endblock %} |
@ -1,40 +0,0 @@
|
||||
from flask import Flask |
||||
from flask_restful import Api |
||||
from apispec import APISpec |
||||
from apispec.ext.marshmallow import MarshmallowPlugin |
||||
from flask_apispec.extension import FlaskApiSpec |
||||
from flask_marshmallow import Marshmallow |
||||
from flask_sqlalchemy import SQLAlchemy |
||||
from flask_cors import CORS |
||||
#!______________ App Setup _____________ _ |
||||
app = Flask(__name__, static_url_path='/static') |
||||
api_v1_cors_config = { |
||||
"origins": ["http://localhost:5000"] |
||||
} |
||||
|
||||
#!______________ CORS Setup _____________ _ |
||||
CORS(app, resources={"/api/*": api_v1_cors_config}) |
||||
|
||||
#!______________ DB Setup ______________ |
||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///markdown.db' |
||||
app.config['SECRET_KEY'] = 'InputSecretKeyHere' |
||||
db = SQLAlchemy(app) |
||||
|
||||
#!______________ Marshmallow Setup ______________ |
||||
ma = Marshmallow(app) |
||||
|
||||
#!______________ API & Swagger Setup ______________ |
||||
api = Api(app) |
||||
app.config.update({ |
||||
'APISPEC_SPEC': APISpec( |
||||
title='Markdown Presenter', |
||||
version='v0.0.1', |
||||
plugins=[MarshmallowPlugin()], |
||||
openapi_version='2.0.0' |
||||
), |
||||
'APISPEC_SWAGGER_URL': '/swagger/', |
||||
'APISPEC_SWAGGER_UI_URL': '/swagger-ui/' |
||||
}) |
||||
|
||||
#!______________ Docs Setup ______________ |
||||
docs = FlaskApiSpec(app) |
@ -1,10 +0,0 @@
|
||||
from config import db |
||||
|
||||
#!______________ DB Models ______________ |
||||
class User(db.Model): |
||||
__tablename__ = "User" |
||||
id = db.Column(db.Integer, primary_key=True) |
||||
name = db.Column(db.String(50)) |
||||
image = db.Column(db.String()) |
||||
description = db.Column(db.String()) |
||||
|
@ -1,18 +0,0 @@
|
||||
import os |
||||
from config import db |
||||
from termcolor import colored |
||||
from config import app |
||||
|
||||
def RebuildDatabase(): |
||||
if os.path.exists('acceth.db'): |
||||
print(colored('Removing existing DB', 'blue')) |
||||
os.remove('acceth.db') |
||||
|
||||
with app.app_context(): |
||||
db.create_all() |
||||
db.session.commit() |
||||
|
||||
print(colored('New DB created.', 'green')) |
||||
|
||||
if __name__ == '__main__': |
||||
RebuildDatabase() |
@ -1,25 +0,0 @@
|
||||
from marshmallow_sqlalchemy import SQLAlchemyAutoSchema |
||||
from config import db |
||||
from models import User |
||||
from marshmallow import fields |
||||
|
||||
#*______________ Base Schema ______________ |
||||
class BaseScheme(SQLAlchemyAutoSchema): |
||||
def __str__(self): |
||||
return str(self.__class__) + ": " + str(self.__dict__) |
||||
class Meta: |
||||
ordered = True |
||||
sqla_session = db.session |
||||
include_fk = True |
||||
load_instance = True |
||||
|
||||
#*______________ User Schemes ______________ |
||||
class UserSchema(BaseScheme): |
||||
class Meta(BaseScheme.Meta): |
||||
model = User |
||||
id = fields.Int() |
||||
name = fields.Str() |
||||
class UserInsertSchema(UserSchema): |
||||
user_id = fields.Int() |
||||
class UserResponseSchema(UserSchema): |
||||
name = fields.Str() |
@ -1,46 +0,0 @@
|
||||
from flask_apispec import marshal_with, doc, use_kwargs |
||||
from flask_apispec.views import MethodResource |
||||
from flask_restful import Resource |
||||
from schemes import (UserSchema, UserResponseSchema) |
||||
from config import db |
||||
from models import User |
||||
|
||||
#!______________ User ______________ |
||||
class UserService(MethodResource, Resource): |
||||
@doc(description='Get User by User_id', tags=['User']) |
||||
@marshal_with(UserResponseSchema) |
||||
def get(self, user_id): |
||||
quser = db.session.query(User).get(user_id) |
||||
return UserSchema().dump(quser) |
||||
|
||||
@doc(description='Add new User', tags=['User']) |
||||
@use_kwargs(UserSchema, location=('json')) |
||||
@marshal_with(UserResponseSchema()) |
||||
def post(self, user, user_id): |
||||
db.session.add(user) |
||||
db.session.commit() |
||||
return UserSchema().dump(user) |
||||
|
||||
@doc(description='Update User with PUT', tags=['User']) |
||||
@use_kwargs(UserSchema, location=('json')) |
||||
@marshal_with(UserResponseSchema()) |
||||
def put(self, user, user_id): |
||||
db.session.add(user) |
||||
db.session.commit() |
||||
return UserSchema().dump(user) |
||||
|
||||
@doc(description='Delete existing User', tags=['User']) |
||||
@use_kwargs(UserSchema, location=('json')) |
||||
@marshal_with(UserResponseSchema()) |
||||
def delete(self, user, user_id): |
||||
user = db.session.query(User).get(user_id) |
||||
db.session.delete(user) |
||||
db.session.commit() |
||||
return UserSchema().dump(user) |
||||
|
||||
class UserListService(MethodResource, Resource): |
||||
@doc(description='Get a List of all User', tags=['List']) |
||||
@marshal_with(UserResponseSchema(many=True)) |
||||
def get(self): |
||||
users = db.session.query(User).all() |
||||
return UserSchema(many=True).dump(users) |
Loading…
Reference in new issue