From 26dfc8fb6cf7228e7ce0f15b3f66d37f3101dcc8 Mon Sep 17 00:00:00 2001 From: dave Date: Sun, 23 Sep 2018 16:39:46 -0700 Subject: [PATCH] real backend for auth --- photoapp/common.py | 7 ++++++ photoapp/daemon.py | 9 +++++--- photoapp/types.py | 16 +++++++++++++ photoapp/users.py | 56 ++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 1 + 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 photoapp/common.py create mode 100644 photoapp/users.py diff --git a/photoapp/common.py b/photoapp/common.py new file mode 100644 index 0000000..208917f --- /dev/null +++ b/photoapp/common.py @@ -0,0 +1,7 @@ +import hashlib + + +def pwhash(password): + h = hashlib.sha256() + h.update(password.encode("UTF-8")) + return h.hexdigest() diff --git a/photoapp/daemon.py b/photoapp/daemon.py index a0ed540..b0a8e51 100644 --- a/photoapp/daemon.py +++ b/photoapp/daemon.py @@ -3,10 +3,11 @@ import cherrypy import logging from datetime import datetime, timedelta from photoapp.library import PhotoLibrary -from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus +from photoapp.types import Photo, PhotoSet, Tag, TagItem, PhotoStatus, User from jinja2 import Environment, FileSystemLoader, select_autoescape from sqlalchemy import desc from sqlalchemy import func, and_, or_ +from photoapp.common import pwhash import math from urllib.parse import urlparse @@ -486,8 +487,10 @@ def main(): 'error_page.404': web.error} def validate_password(realm, username, password): - print("I JUST VALIDATED {}:{} ({})".format(username, password, realm)) - return True + s = library.session() + if s.query(User).filter(User.name == username, User.password == pwhash(password)).first(): + return True + return False cherrypy.tree.mount(web, '/', {'/': web_config, '/static': {"tools.staticdir.on": True, diff --git a/photoapp/types.py b/photoapp/types.py index dfa9b2d..b8e0fa9 100644 --- a/photoapp/types.py +++ b/photoapp/types.py @@ -87,3 +87,19 @@ class TagItem(Base): set = relationship("PhotoSet", back_populates="tags", foreign_keys=[set_id]) UniqueConstraint(tag_id, set_id) + + +class UserStatus(enum.Enum): + banned = -1 + guest = 0 + normal = 1 + admin = 2 + + +class User(Base): + __tablename__ = 'users' + + id = Column(Integer, primary_key=True) + name = Column(String(length=64), unique=True) + password = Column(String(length=64)) # sha256 + status = Column(Enum(UserStatus), default=UserStatus.normal) diff --git a/photoapp/users.py b/photoapp/users.py new file mode 100644 index 0000000..cb3c654 --- /dev/null +++ b/photoapp/users.py @@ -0,0 +1,56 @@ +import argparse +from photoapp.library import PhotoLibrary +from photoapp.types import User +from photoapp.common import pwhash + + +def create_user(library, username, password): + s = library.session() + s.add(User(name=username, password=pwhash(password))) + s.commit() + + +def list_users(library): + s = library.session() + print("id\tname") + for user in s.query(User).order_by(User.name).all(): + print("{}\t{}".format(user.id, user.name)) + + +def delete_user(library, username): + s = library.session() + u = s.query(User).filter(User.name == username).first() + s.delete(u) + s.commit() + print("Deleted user {}".format(u.id)) + + +def main(): + parser = argparse.ArgumentParser(description="User manipulation tool") + p_mode = parser.add_subparsers(dest='action', help='action to take') + + p_create = p_mode.add_parser('create', help='create user') + p_create.add_argument("-u", "--username", help="username", required=True) + p_create.add_argument("-p", "--password", help="password", required=True) + + p_list = p_mode.add_parser('list', help='list users') + + p_delete = p_mode.add_parser('delete', help='delete users') + p_delete.add_argument("-u", "--username", help="username", required=True) + + args = parser.parse_args() + + library = PhotoLibrary("photos.db", "./library/", "./cache/") + + if args.action == "create": + create_user(library, args.username, args.password) + elif args.action == "list": + list_users(library) + elif args.action == "delete": + delete_user(library, args.username) + else: + parser.print_help() + + +if __name__ == '__main__': + main() diff --git a/setup.py b/setup.py index 1707d71..9afa1df 100644 --- a/setup.py +++ b/setup.py @@ -21,6 +21,7 @@ setup(name='photoapp', "photovalidate = photoapp.validate:main", "photoinfo = photoapp.image:main", "photooffset = photoapp.dateoffset:main", + "photousers = photoapp.users:main", ] }, include_package_data=True,