Building out enums and database admin stuff.
This commit is contained in:
parent
1a6fdfbc32
commit
89878d78ec
23
admin.py
23
admin.py
|
@ -25,13 +25,14 @@
|
|||
|
||||
from rookeries import __version__ as __app_version
|
||||
from rookeries.core.config import Config
|
||||
from rookeries.core.database import init_db
|
||||
from rookeries.core.database import Base, engine, manage_db
|
||||
import argparse
|
||||
|
||||
|
||||
def rebuild_database(arguments):
|
||||
"""Re-synchronizes the database which is pretty useful for rapid development."""
|
||||
init_db(arguments.drop_tables, arguments.init_data)
|
||||
# TODO Turn this more into a mode thing than multiple arguments.
|
||||
manage_db(Base, engine, arguments.create_tables, arguments.drop_tables, arguments.init_data)
|
||||
|
||||
|
||||
def print_configuration_opt(arguments):
|
||||
|
@ -65,11 +66,19 @@ def build_argument_parser():
|
|||
help="Print out in a single line. Useful for environment variables.")
|
||||
config_parser.set_defaults(func=print_configuration_opt)
|
||||
|
||||
rebuild_db_parser = sub_parser.add_parser("rebuild_db", help="Rebuilds the database.")
|
||||
rebuild_db_parser.add_argument("--drop_tables", action="store_true", default=False,
|
||||
help="Drops the existing tables.")
|
||||
rebuild_db_parser.add_argument("--init_data", action="store_true", default=False, help="Initializes the database.")
|
||||
rebuild_db_parser.set_defaults(func=rebuild_database)
|
||||
# rebuild_db_parser = sub_parser.add_parser("rebuild_db", help="Rebuilds the database.")
|
||||
# rebuild_db_parser.add_argument("--drop_tables", action="store_true", default=False,
|
||||
# help="Drops the existing tables.")
|
||||
# rebuild_db_parser.add_argument("--init_data", action="store_true", default=False, help="Initializes the database.")
|
||||
# rebuild_db_parser.set_defaults(func=rebuild_database)
|
||||
|
||||
# TODO Clean this up into commands.
|
||||
manage_db_parser = sub_parser.add_parser("manage_db", help="Manages the database.")
|
||||
manage_db_parser.add_argument("--create_tables", action="store_true", default=False, help="Creates the tables.")
|
||||
manage_db_parser.add_argument("--drop_tables", action="store_true", default=False,
|
||||
help="Drops the existing tables.")
|
||||
manage_db_parser.add_argument("--init_data", action="store_true", default=False, help="Initializes the database.")
|
||||
manage_db_parser.set_defaults(func=rebuild_database)
|
||||
|
||||
return parser
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
Things To-Do
|
||||
============
|
||||
|
||||
* Build out user account management and registration. {Started}
|
||||
* Build out user account management and registration. {In-progress}
|
||||
* Make new logo based on APS' Mr. Penguin. {Started}
|
||||
* Build out simple to-do/project creation and management setup.
|
||||
* Setup a nice clutter-free deployment option for rookeri.es itself. {In-progress}
|
||||
|
@ -13,10 +13,12 @@ Things To-Do
|
|||
* Build out a simple CMS/journal based off core database.
|
||||
* Fix up navigation with dynamic elements for various apps...
|
||||
|
||||
* Consider using enums for some parts: https://pypi.python.org/pypi/enum/0.4.4
|
||||
* Add in translation strings.
|
||||
* Add in special JSON string responses for Flask: http://flask.pocoo.org/snippets/83/
|
||||
|
||||
Things Done
|
||||
-----------
|
||||
|
||||
* *2013 May 09* --- Transitioned COPYING to reStructured text.
|
||||
* *2013 June 11* --- Build out setup.py and make it easy to distribute on PyPI.
|
||||
* *2013 June 28* --- Using enums for some parts. See enum34 and SQLAlchemy's Enums.
|
||||
|
|
|
@ -78,10 +78,16 @@ class Config(object):
|
|||
web_app_config_in_json = os.environ.get(CONFIG_ENV)
|
||||
if web_app_config_in_json is not None:
|
||||
self.load_config_from_json(web_app_config_in_json)
|
||||
|
||||
else:
|
||||
json_config_filename = CONFIG_FILENAME
|
||||
|
||||
if os.path.exists(json_config_filename):
|
||||
self.load_config_from_json(json_config_filename)
|
||||
|
||||
with codecs.open(json_config_filename, "rb", encoding="utf-8") as f:
|
||||
json_config_str = f.read()
|
||||
|
||||
self.load_config_from_json(json_config_str)
|
||||
|
||||
def __dict__(self):
|
||||
"""A nicer dict representation of the configuration options."""
|
||||
|
|
|
@ -29,6 +29,9 @@ from sqlalchemy.ext.declarative import declarative_base
|
|||
|
||||
from rookeries.core.config import Config
|
||||
|
||||
|
||||
# TODO Organize everything nicely here.
|
||||
|
||||
engine = create_engine(Config().DATABASE_URI, convert_unicode=True)
|
||||
db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine))
|
||||
|
||||
|
@ -36,17 +39,19 @@ Base = declarative_base()
|
|||
Base.query = db_session.query_property()
|
||||
|
||||
|
||||
# TODO Organize everything nicely here.
|
||||
|
||||
def init_db(drop_tables=False, populate_with_data=False):
|
||||
"""Initializes the database and bindings to the models. Also populates the models with initial data."""
|
||||
def manage_db(Base, engine, create_tables=False, drop_tables=False, populate_with_data=False):
|
||||
"""Manages the database and bindings to the models. Also populates the models with initial data."""
|
||||
# TODO Comment.
|
||||
|
||||
if drop_tables:
|
||||
Base.metadata.drop_all(bind=engine)
|
||||
|
||||
Base.metadata.create_all(bind=engine)
|
||||
if create_tables:
|
||||
import rookeries.core.models
|
||||
Base.metadata.create_all(bind=engine)
|
||||
|
||||
if drop_tables and populate_with_data:
|
||||
# TODO Add in build out of initial models and groups.
|
||||
pass
|
||||
|
||||
pass
|
||||
|
|
|
@ -23,17 +23,27 @@
|
|||
|
||||
"""
|
||||
|
||||
# TODO Add in translation string lookups...
|
||||
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import Column, Integer, String, DateTime, ForeignKey
|
||||
from sqlalchemy import Column, Integer, Enum, String, DateTime, ForeignKey
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from enum import Enum
|
||||
|
||||
import enum
|
||||
from rookeries.core.database import Base
|
||||
|
||||
|
||||
# --- Statuses ---
|
||||
# Considered adding enums in a manner as detailed here: http://techspot.zzzeek.org/2011/01/14/the-enum-recipe/
|
||||
# Unless someone comes up with a nicer form of enums that work nicely outside of this array, two object setup.
|
||||
__POSSIBLE_USER_STATUS__ = ["Unknown", "Registered", "Active", "Disabled", "Banned"]
|
||||
UserStatus = enum.Enum("UserStatus", __POSSIBLE_USER_STATUS__)
|
||||
__POSSIBLE_USER_PROFILE_DETAIL_TYPES__ = ["Email", "Address", "City", "Region", "Country", "CellPhone", "Phone",
|
||||
"Microblog", "Url"]
|
||||
UserProfileDetailType = enum.Enum("UserProfileDetailType", __POSSIBLE_USER_PROFILE_DETAIL_TYPES__)
|
||||
|
||||
|
||||
# --- Models ---
|
||||
|
||||
|
||||
class User(Base):
|
||||
"""User of the Rookeries application."""
|
||||
|
||||
|
@ -47,9 +57,6 @@ class User(Base):
|
|||
user_auth_id = Column(Integer, ForeignKey("user_authentication.id"))
|
||||
user_authentication = relationship("UserAuthentication", backref="user", cascade="all, delete")
|
||||
|
||||
user_type_id = Column(Integer, ForeignKey('user_type.id'))
|
||||
user_type = relationship("UserType", backref=backref('users', order_by=id))
|
||||
|
||||
def __init__(self, username=None, full_name=None, email=None):
|
||||
self.username = username
|
||||
self.full_name = full_name
|
||||
|
@ -68,59 +75,38 @@ class UserAuthentication(Base):
|
|||
|
||||
password = Column(String(512))
|
||||
security_update_date = Column(DateTime)
|
||||
status = Column(String(16), ForeignKey("status.id"))
|
||||
status = Column(Enum(__POSSIBLE_USER_STATUS__, name="user_status"))
|
||||
|
||||
def __init__(self):
|
||||
self.status = UserStatus.Registered
|
||||
self.status = UserStatus.Registered.name
|
||||
self.security_update_date = datetime.now()
|
||||
|
||||
def __repr__(self):
|
||||
return "<UserAuthentication('%s', '%s', '%s')>" % (self.id, self.status, self.security_update_date)
|
||||
|
||||
|
||||
# TODO Considering to add in enums in a sane manner. Looking at: http://techspot.zzzeek.org/2011/01/14/the-enum-recipe/
|
||||
|
||||
class UserStatus(Enum):
|
||||
"""Possible user statuses."""
|
||||
|
||||
__order__ = "Unknown Registered Active Disabled Banned"
|
||||
Unknown = 0
|
||||
Registered = 1
|
||||
Active = 2
|
||||
Disabled = 3
|
||||
Banned = 4
|
||||
|
||||
|
||||
class UserProfileDetailType(Enum):
|
||||
"""Supports user profile details."""
|
||||
|
||||
# TODO Consider about wanting to limit types... and still being fairly generic
|
||||
__order__ = ""
|
||||
AlternativeEmail = 1
|
||||
AddressStreet = 2
|
||||
AddressCity = 3
|
||||
AddressLocalRegion = 4
|
||||
AddressRegion = 5
|
||||
AddressCountry = 6
|
||||
CellPhone = 7
|
||||
Phone = 8
|
||||
Microblog = 9
|
||||
Url = 10
|
||||
|
||||
|
||||
# TODO Add in user contact / profile info?
|
||||
class UserProfileDetail(Base):
|
||||
"""Flexible elements for storing elements of a user profile."""
|
||||
|
||||
___tablename__ = "user_profile_details"
|
||||
__tablename__ = "user_profile_details"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
user_id = Column(Integer, ForeignKey("user.id"))
|
||||
user = relationship("User")
|
||||
detail_type = Column(Enum(__POSSIBLE_USER_PROFILE_DETAIL_TYPES__, name="user_profile_detail_type"))
|
||||
detail_value = Column(String(512))
|
||||
|
||||
# TODO Add __init__ and __repr__
|
||||
|
||||
|
||||
# TODO Add more methods controlling users in groups, etc.
|
||||
# TODO Add in permissions for content items, etc. rather than global admin.
|
||||
class Group(Base):
|
||||
"""Group of users that allows for controlling user interactions and permissions in a granular manner."""
|
||||
|
||||
___tablename___ = "group"
|
||||
__tablename__ = "group"
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(512))
|
||||
|
||||
# TODO Add in user membership
|
||||
# TODO Add in group-with-group
|
||||
# TODO Add __init__ and __repr__
|
|
@ -0,0 +1,27 @@
|
|||
#
|
||||
# Copyright (c) 2013 Dorian Pula <dorian.pula@amber-penguin-software.ca>
|
||||
#
|
||||
# Rookeries is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
# published by the Free Software Foundation, either version 3 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# Rookeries is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Affero General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public
|
||||
# License along with Rookeries. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Please share and enjoy!
|
||||
#
|
||||
|
||||
"""Handles translations for the Rookeries platform.
|
||||
|
||||
@author: Dorian Pula <dorian.pula@amber-penguin-software.ca>
|
||||
|
||||
"""
|
||||
|
||||
# TODO Add in translation string lookups...
|
||||
# TODO Look at http://docs.python.org/2/library/gettext.html
|
|
@ -24,7 +24,6 @@
|
|||
"""
|
||||
|
||||
import warnings
|
||||
from enum import Enum
|
||||
|
||||
|
||||
def deprecated(func):
|
||||
|
@ -43,16 +42,3 @@ def deprecated(func):
|
|||
new_func.__doc__ = func.__doc__
|
||||
new_func.__dict__.update(func.__dict__)
|
||||
return new_func
|
||||
|
||||
|
||||
def create_enum_from_value(value, cls):
|
||||
pass
|
||||
|
||||
|
||||
def create_db_enum_value_list(enum):
|
||||
if not isinstance(enum, Enum):
|
||||
raise TypeError("enum must be a Enum instance")
|
||||
|
||||
value_list = []
|
||||
for key in Enum:
|
||||
value_list.append(key.name)
|
||||
|
|
|
@ -189,6 +189,7 @@ def register_user():
|
|||
# TODO Make this more robust and secure...
|
||||
# Check if there is a closed invite restriction...
|
||||
config = Config()
|
||||
|
||||
if config.USER_REGISTRATION_INVITE_KEY is not None:
|
||||
invite_key = request.form["invite_key"]
|
||||
if invite_key == unicode(config.USER_REGISTRATION_INVITE_KEY):
|
||||
|
@ -231,6 +232,7 @@ def display_user_profile(username=None):
|
|||
# TODO Make some checks...
|
||||
user.email = request.form["email"]
|
||||
user.full_name = request.form["user_full_name"]
|
||||
|
||||
db_session.commit()
|
||||
return redirect(url_for("display_user_profile", username=user.username))
|
||||
|
||||
|
|
Loading…
Reference in New Issue