Drew Short
7 years ago
12 changed files with 436 additions and 2 deletions
-
16server/Pipfile
-
192server/Pipfile.lock
-
16server/atheneum/__init__.py
-
1server/atheneum/default_settings.py
-
0server/atheneum/model/User.py
-
1server/atheneum/model/__init__.py
-
15server/atheneum/model/user.py
-
1server/migrations/README
-
45server/migrations/alembic.ini
-
89server/migrations/env.py
-
24server/migrations/script.py.mako
-
38server/migrations/versions/7160f2b96a1c_.py
@ -0,0 +1,16 @@ |
|||
[[source]] |
|||
url = "https://pypi.org/simple" |
|||
verify_ssl = true |
|||
name = "pypi" |
|||
|
|||
[packages] |
|||
flask = ">=1.0,<1.1" |
|||
flask-sqlalchemy = ">=2.3,<2.4" |
|||
flask-migrate = ">=2.1,<2.2" |
|||
pynacl = ">=1.2,<1.3" |
|||
|
|||
[dev-packages] |
|||
python-dotenv = "*" |
|||
|
|||
[requires] |
|||
python_version = "3.6" |
@ -0,0 +1,192 @@ |
|||
{ |
|||
"_meta": { |
|||
"hash": { |
|||
"sha256": "ea0b054cc713e78e3aef06fe53568b66bebd6a78f353b3a118547f7c765ce745" |
|||
}, |
|||
"pipfile-spec": 6, |
|||
"requires": { |
|||
"python_version": "3.6" |
|||
}, |
|||
"sources": [ |
|||
{ |
|||
"name": "pypi", |
|||
"url": "https://pypi.org/simple", |
|||
"verify_ssl": true |
|||
} |
|||
] |
|||
}, |
|||
"default": { |
|||
"alembic": { |
|||
"hashes": [ |
|||
"sha256:85bd3ea7633024e4930900bc64fb58f9742dedbc6ebb6ecf25be2ea9a3c1b32e" |
|||
], |
|||
"version": "==0.9.9" |
|||
}, |
|||
"cffi": { |
|||
"hashes": [ |
|||
"sha256:151b7eefd035c56b2b2e1eb9963c90c6302dc15fbd8c1c0a83a163ff2c7d7743", |
|||
"sha256:1553d1e99f035ace1c0544050622b7bc963374a00c467edafac50ad7bd276aef", |
|||
"sha256:1b0493c091a1898f1136e3f4f991a784437fac3673780ff9de3bcf46c80b6b50", |
|||
"sha256:2ba8a45822b7aee805ab49abfe7eec16b90587f7f26df20c71dd89e45a97076f", |
|||
"sha256:3c85641778460581c42924384f5e68076d724ceac0f267d66c757f7535069c93", |
|||
"sha256:3eb6434197633b7748cea30bf0ba9f66727cdce45117a712b29a443943733257", |
|||
"sha256:4c91af6e967c2015729d3e69c2e51d92f9898c330d6a851bf8f121236f3defd3", |
|||
"sha256:770f3782b31f50b68627e22f91cb182c48c47c02eb405fd689472aa7b7aa16dc", |
|||
"sha256:79f9b6f7c46ae1f8ded75f68cf8ad50e5729ed4d590c74840471fc2823457d04", |
|||
"sha256:7a33145e04d44ce95bcd71e522b478d282ad0eafaf34fe1ec5bbd73e662f22b6", |
|||
"sha256:857959354ae3a6fa3da6651b966d13b0a8bed6bbc87a0de7b38a549db1d2a359", |
|||
"sha256:87f37fe5130574ff76c17cab61e7d2538a16f843bb7bca8ebbc4b12de3078596", |
|||
"sha256:95d5251e4b5ca00061f9d9f3d6fe537247e145a8524ae9fd30a2f8fbce993b5b", |
|||
"sha256:9d1d3e63a4afdc29bd76ce6aa9d58c771cd1599fbba8cf5057e7860b203710dd", |
|||
"sha256:a36c5c154f9d42ec176e6e620cb0dd275744aa1d804786a71ac37dc3661a5e95", |
|||
"sha256:ae5e35a2c189d397b91034642cb0eab0e346f776ec2eb44a49a459e6615d6e2e", |
|||
"sha256:b0f7d4a3df8f06cf49f9f121bead236e328074de6449866515cea4907bbc63d6", |
|||
"sha256:b75110fb114fa366b29a027d0c9be3709579602ae111ff61674d28c93606acca", |
|||
"sha256:ba5e697569f84b13640c9e193170e89c13c6244c24400fc57e88724ef610cd31", |
|||
"sha256:be2a9b390f77fd7676d80bc3cdc4f8edb940d8c198ed2d8c0be1319018c778e1", |
|||
"sha256:d5d8555d9bfc3f02385c1c37e9f998e2011f0db4f90e250e5bc0c0a85a813085", |
|||
"sha256:e55e22ac0a30023426564b1059b035973ec82186ddddbac867078435801c7801", |
|||
"sha256:e90f17980e6ab0f3c2f3730e56d1fe9bcba1891eeea58966e89d352492cc74f4", |
|||
"sha256:ecbb7b01409e9b782df5ded849c178a0aa7c906cf8c5a67368047daab282b184", |
|||
"sha256:ed01918d545a38998bfa5902c7c00e0fee90e957ce036a4000a88e3fe2264917", |
|||
"sha256:edabd457cd23a02965166026fd9bfd196f4324fe6032e866d0f3bd0301cd486f", |
|||
"sha256:fdf1c1dc5bafc32bc5d08b054f94d659422b05aba244d6be4ddc1c72d9aa70fb" |
|||
], |
|||
"version": "==1.11.5" |
|||
}, |
|||
"click": { |
|||
"hashes": [ |
|||
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d", |
|||
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b" |
|||
], |
|||
"version": "==6.7" |
|||
}, |
|||
"flask": { |
|||
"hashes": [ |
|||
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48", |
|||
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==1.0.2" |
|||
}, |
|||
"flask-migrate": { |
|||
"hashes": [ |
|||
"sha256:493f9b3795985b9b4915bf3b7d16946697f027b73545384e7d9e3a79f989d2fe", |
|||
"sha256:b709ca8642559c3c5a81a33ab10839fa052177accd5ba821047a99db635255ed" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==2.1.1" |
|||
}, |
|||
"flask-sqlalchemy": { |
|||
"hashes": [ |
|||
"sha256:3bc0fac969dd8c0ace01b32060f0c729565293302f0c4269beed154b46bec50b", |
|||
"sha256:5971b9852b5888655f11db634e87725a9031e170f37c0ce7851cf83497f56e53" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==2.3.2" |
|||
}, |
|||
"itsdangerous": { |
|||
"hashes": [ |
|||
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519" |
|||
], |
|||
"version": "==0.24" |
|||
}, |
|||
"jinja2": { |
|||
"hashes": [ |
|||
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd", |
|||
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4" |
|||
], |
|||
"version": "==2.10" |
|||
}, |
|||
"mako": { |
|||
"hashes": [ |
|||
"sha256:4e02fde57bd4abb5ec400181e4c314f56ac3e49ba4fb8b0d50bba18cb27d25ae" |
|||
], |
|||
"version": "==1.0.7" |
|||
}, |
|||
"markupsafe": { |
|||
"hashes": [ |
|||
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665" |
|||
], |
|||
"version": "==1.0" |
|||
}, |
|||
"pycparser": { |
|||
"hashes": [ |
|||
"sha256:99a8ca03e29851d96616ad0404b4aad7d9ee16f25c9f9708a11faf2810f7b226" |
|||
], |
|||
"version": "==2.18" |
|||
}, |
|||
"pynacl": { |
|||
"hashes": [ |
|||
"sha256:04e30e5bdeeb2d5b34107f28cd2f5bbfdc6c616f3be88fc6f53582ff1669eeca", |
|||
"sha256:0bfa0d94d2be6874e40f896e0a67e290749151e7de767c5aefbad1121cad7512", |
|||
"sha256:11aa4e141b2456ce5cecc19c130e970793fa3a2c2e6fbb8ad65b28f35aa9e6b6", |
|||
"sha256:13bdc1fe084ff9ac7653ae5a924cae03bf4bb07c6667c9eb5b6eb3c570220776", |
|||
"sha256:14339dc233e7a9dda80a3800e64e7ff89d0878ba23360eea24f1af1b13772cac", |
|||
"sha256:1d33e775fab3f383167afb20b9927aaf4961b953d76eeb271a5703a6d756b65b", |
|||
"sha256:2a42b2399d0428619e58dac7734838102d35f6dcdee149e0088823629bf99fbb", |
|||
"sha256:2dce05ac8b3c37b9e2f65eab56c544885607394753e9613fd159d5e2045c2d98", |
|||
"sha256:6453b0dae593163ffc6db6f9c9c1597d35c650598e2c39c0590d1757207a1ac2", |
|||
"sha256:73a5a96fb5fbf2215beee2353a128d382dbca83f5341f0d3c750877a236569ef", |
|||
"sha256:8abb4ef79161a5f58848b30ab6fb98d8c466da21fdd65558ce1d7afc02c70b5f", |
|||
"sha256:8ac1167195b32a8755de06efd5b2d2fe76fc864517dab66aaf65662cc59e1988", |
|||
"sha256:8f505f42f659012794414fa57c498404e64db78f1d98dfd40e318c569f3c783b", |
|||
"sha256:be71cd5fce04061e1f3d39597f93619c80cdd3558a6c9ba99a546f144a8d8101", |
|||
"sha256:cf6877124ae6a0698404e169b3ba534542cfbc43f939d46b927d956daf0a373a", |
|||
"sha256:d0eb5b2795b7ee2cbcfcadacbe95a13afbda048a262bd369da9904fecb568975", |
|||
"sha256:d795f506bcc9463efb5ebb0f65ed77921dcc9e0a50499dedd89f208445de9ecb", |
|||
"sha256:d8aaf7e5d6b0e0ef7d6dbf7abeb75085713d0100b4eb1a4e4e857de76d77ac45", |
|||
"sha256:e0d38fa0a75f65f556fb912f2c6790d1fa29b7dd27a1d9cc5591b281321eaaa9", |
|||
"sha256:eb2acabbd487a46b38540a819ef67e477a674481f84a82a7ba2234b9ba46f752", |
|||
"sha256:eeee629828d0eb4f6d98ac41e9a3a6461d114d1d0aa111a8931c049359298da0", |
|||
"sha256:f5ce9e26d25eb0b2d96f3ef0ad70e1d3ae89b5d60255c462252a3e456a48c053", |
|||
"sha256:fabf73d5d0286f9e078774f3435601d2735c94ce9e514ac4fb945701edead7e4" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==1.2.1" |
|||
}, |
|||
"python-dateutil": { |
|||
"hashes": [ |
|||
"sha256:1adb80e7a782c12e52ef9a8182bebeb73f1d7e24e374397af06fb4956c8dc5c0", |
|||
"sha256:e27001de32f627c22380a688bcc43ce83504a7bc5da472209b4c70f02829f0b8" |
|||
], |
|||
"version": "==2.7.3" |
|||
}, |
|||
"python-editor": { |
|||
"hashes": [ |
|||
"sha256:a3c066acee22a1c94f63938341d4fb374e3fdd69366ed6603d7b24bed1efc565" |
|||
], |
|||
"version": "==1.0.3" |
|||
}, |
|||
"six": { |
|||
"hashes": [ |
|||
"sha256:70e8a77beed4562e7f14fe23a786b54f6296e34344c23bc42f07b15018ff98e9", |
|||
"sha256:832dc0e10feb1aa2c68dcc57dbb658f1c7e65b9b61af69048abc87a2db00a0eb" |
|||
], |
|||
"version": "==1.11.0" |
|||
}, |
|||
"sqlalchemy": { |
|||
"hashes": [ |
|||
"sha256:d6cda03b0187d6ed796ff70e87c9a7dce2c2c9650a7bc3c022cd331416853c31" |
|||
], |
|||
"version": "==1.2.7" |
|||
}, |
|||
"werkzeug": { |
|||
"hashes": [ |
|||
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c", |
|||
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b" |
|||
], |
|||
"version": "==0.14.1" |
|||
} |
|||
}, |
|||
"develop": { |
|||
"python-dotenv": { |
|||
"hashes": [ |
|||
"sha256:4965ed170bf51c347a89820e8050655e9c25db3837db6602e906b6d850fad85c", |
|||
"sha256:509736185257111613009974e666568a1b031b028b61b500ef1ab4ee780089d5" |
|||
], |
|||
"index": "pypi", |
|||
"version": "==0.8.2" |
|||
} |
|||
} |
|||
} |
@ -1,3 +1,4 @@ |
|||
DEBUG = True |
|||
SECRET_KEY = b'\xb4\x89\x0f\x0f\xe5\x88\x97\xfe\x8d<\x0b@d\xe9\xa5\x87%' \ |
|||
b'\xc6\xf0@l1\xe3\x90g\xfaA.?u=s' # CHANGE ME IN REAL CONFIG |
|||
SQLALCHEMY_TRACK_MODIFICATIONS=False |
@ -0,0 +1 @@ |
|||
from atheneum.model.user import User |
@ -0,0 +1,15 @@ |
|||
from atheneum import db |
|||
|
|||
|
|||
class User(db.Model): |
|||
__tablename__ = 'user' |
|||
|
|||
id = db.Column(db.Integer, primary_key=True) |
|||
name = db.Column(db.Unicode(60), unique=True, nullable=False) |
|||
password_hash = db.Column('password_hash', db.Unicode(128), nullable=False) |
|||
password_dblt = db.Column('password_dblt', db.Unicode(32)) |
|||
password_revision = db.Column( |
|||
'password_revision', db.SmallInteger, default=0, nullable=False) |
|||
creation_time = db.Column('creation_time', db.DateTime, nullable=False) |
|||
last_login_time = db.Column('last_login_time', db.DateTime) |
|||
version = db.Column('version', db.Integer, default=1, nullable=False) |
@ -0,0 +1 @@ |
|||
Generic single-database configuration. |
@ -0,0 +1,45 @@ |
|||
# A generic, single database configuration. |
|||
|
|||
[alembic] |
|||
# template used to generate migration files |
|||
# file_template = %%(rev)s_%%(slug)s |
|||
|
|||
# set to 'true' to run the environment during |
|||
# the 'revision' command, regardless of autogenerate |
|||
# revision_environment = false |
|||
|
|||
|
|||
# Logging configuration |
|||
[loggers] |
|||
keys = root,sqlalchemy,alembic |
|||
|
|||
[handlers] |
|||
keys = console |
|||
|
|||
[formatters] |
|||
keys = generic |
|||
|
|||
[logger_root] |
|||
level = WARN |
|||
handlers = console |
|||
qualname = |
|||
|
|||
[logger_sqlalchemy] |
|||
level = WARN |
|||
handlers = |
|||
qualname = sqlalchemy.engine |
|||
|
|||
[logger_alembic] |
|||
level = INFO |
|||
handlers = |
|||
qualname = alembic |
|||
|
|||
[handler_console] |
|||
class = StreamHandler |
|||
args = (sys.stderr,) |
|||
level = NOTSET |
|||
formatter = generic |
|||
|
|||
[formatter_generic] |
|||
format = %(levelname)-5.5s [%(name)s] %(message)s |
|||
datefmt = %H:%M:%S |
@ -0,0 +1,89 @@ |
|||
from __future__ import with_statement |
|||
|
|||
import logging |
|||
from logging.config import fileConfig |
|||
|
|||
from alembic import context |
|||
from sqlalchemy import engine_from_config, pool |
|||
|
|||
# this is the Alembic Config object, which provides |
|||
# access to the values within the .ini file in use. |
|||
config = context.config |
|||
|
|||
# Interpret the config file for Python logging. |
|||
# This line sets up loggers basically. |
|||
fileConfig(config.config_file_name) |
|||
logger = logging.getLogger('alembic.env') |
|||
|
|||
# add your model's MetaData object here |
|||
# for 'autogenerate' support |
|||
# from myapp import mymodel |
|||
# target_metadata = mymodel.Base.metadata |
|||
from flask import current_app |
|||
config.set_main_option('sqlalchemy.url', |
|||
current_app.config.get('SQLALCHEMY_DATABASE_URI')) |
|||
target_metadata = current_app.extensions['migrate'].db.metadata |
|||
|
|||
# other values from the config, defined by the needs of env.py, |
|||
# can be acquired: |
|||
# my_important_option = config.get_main_option("my_important_option") |
|||
# ... etc. |
|||
|
|||
|
|||
def run_migrations_offline(): |
|||
"""Run migrations in 'offline' mode. |
|||
|
|||
This configures the context with just a URL |
|||
and not an Engine, though an Engine is acceptable |
|||
here as well. By skipping the Engine creation |
|||
we don't even need a DBAPI to be available. |
|||
|
|||
Calls to context.execute() here emit the given string to the |
|||
script output. |
|||
|
|||
""" |
|||
url = config.get_main_option("sqlalchemy.url") |
|||
context.configure(url=url) |
|||
|
|||
with context.begin_transaction(): |
|||
context.run_migrations() |
|||
|
|||
|
|||
def run_migrations_online(): |
|||
"""Run migrations in 'online' mode. |
|||
|
|||
In this scenario we need to create an Engine |
|||
and associate a connection with the context. |
|||
|
|||
""" |
|||
|
|||
# this callback is used to prevent an auto-migration from being generated |
|||
# when there are no changes to the schema |
|||
# reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html |
|||
def process_revision_directives(context, revision, directives): |
|||
if getattr(config.cmd_opts, 'autogenerate', False): |
|||
script = directives[0] |
|||
if script.upgrade_ops.is_empty(): |
|||
directives[:] = [] |
|||
logger.info('No changes in schema detected.') |
|||
|
|||
engine = engine_from_config(config.get_section(config.config_ini_section), |
|||
prefix='sqlalchemy.', |
|||
poolclass=pool.NullPool) |
|||
|
|||
connection = engine.connect() |
|||
context.configure(connection=connection, |
|||
target_metadata=target_metadata, |
|||
process_revision_directives=process_revision_directives, |
|||
**current_app.extensions['migrate'].configure_args) |
|||
|
|||
try: |
|||
with context.begin_transaction(): |
|||
context.run_migrations() |
|||
finally: |
|||
connection.close() |
|||
|
|||
if context.is_offline_mode(): |
|||
run_migrations_offline() |
|||
else: |
|||
run_migrations_online() |
@ -0,0 +1,24 @@ |
|||
"""${message} |
|||
|
|||
Revision ID: ${up_revision} |
|||
Revises: ${down_revision | comma,n} |
|||
Create Date: ${create_date} |
|||
|
|||
""" |
|||
from alembic import op |
|||
import sqlalchemy as sa |
|||
${imports if imports else ""} |
|||
|
|||
# revision identifiers, used by Alembic. |
|||
revision = ${repr(up_revision)} |
|||
down_revision = ${repr(down_revision)} |
|||
branch_labels = ${repr(branch_labels)} |
|||
depends_on = ${repr(depends_on)} |
|||
|
|||
|
|||
def upgrade(): |
|||
${upgrades if upgrades else "pass"} |
|||
|
|||
|
|||
def downgrade(): |
|||
${downgrades if downgrades else "pass"} |
@ -0,0 +1,38 @@ |
|||
"""empty message |
|||
|
|||
Revision ID: 7160f2b96a1c |
|||
Revises: |
|||
Create Date: 2018-05-15 23:39:48.110843 |
|||
|
|||
""" |
|||
import sqlalchemy as sa |
|||
from alembic import op |
|||
|
|||
# revision identifiers, used by Alembic. |
|||
revision = '7160f2b96a1c' |
|||
down_revision = None |
|||
branch_labels = None |
|||
depends_on = None |
|||
|
|||
|
|||
def upgrade(): |
|||
# ### commands auto generated by Alembic - please adjust! ### |
|||
op.create_table('user', |
|||
sa.Column('id', sa.Integer(), nullable=False), |
|||
sa.Column('name', sa.Unicode(length=60), nullable=False), |
|||
sa.Column('password_hash', sa.Unicode(length=128), nullable=False), |
|||
sa.Column('password_dblt', sa.Unicode(length=32), nullable=True), |
|||
sa.Column('password_revision', sa.SmallInteger(), nullable=False), |
|||
sa.Column('creation_time', sa.DateTime(), nullable=False), |
|||
sa.Column('last_login_time', sa.DateTime(), nullable=True), |
|||
sa.Column('version', sa.Integer(), nullable=False), |
|||
sa.PrimaryKeyConstraint('id'), |
|||
sa.UniqueConstraint('name') |
|||
) |
|||
# ### end Alembic commands ### |
|||
|
|||
|
|||
def downgrade(): |
|||
# ### commands auto generated by Alembic - please adjust! ### |
|||
op.drop_table('user') |
|||
# ### end Alembic commands ### |
Write
Preview
Loading…
Cancel
Save
Reference in new issue