diff --git a/.gitignore b/.gitignore index dc3ed05..109d183 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /venv /tmp -/production.cfg +/lenticular_cloud/production.cfg /pki signing_key.pem node_modules diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..a95d7d4 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +recursive-include lenticular_cloud/template * +recursive-include lenticular_cloud/static ** +include lenticular_cloud/*.cfg + diff --git a/README.md b/README.md index 502f22c..f68e0c8 100644 --- a/README.md +++ b/README.md @@ -32,3 +32,9 @@ Tested Services * ~~Postfix~~/Dovecot (~~OIDC~~/client cert/password) * prosody (client cert/~~password~~) + + +Oauth2 Settings: +---------------- + +callback url: `${domain}/ diff --git a/cli.py b/cli.py new file mode 100644 index 0000000..7073b12 --- /dev/null +++ b/cli.py @@ -0,0 +1,8 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +from lenticular_cloud.cli import entry_point + + + +entry_point() diff --git a/hydra_client.json b/hydra_client.json new file mode 100644 index 0000000..3c2fb98 --- /dev/null +++ b/hydra_client.json @@ -0,0 +1,13 @@ +{ + "client_id": "identiy_provider", + "client_secret": "", + "redirect_uris": [ + "{domain}/oauth/authorized" + ], + "response_types": [ + "code", "id_token" + ], + "scope": "openid profile manage", + "grant_types": ["authorization_code", "refresh_token"], + "token_endpoint_auth_method": "client_secret_basic" +} diff --git a/lenticular_cloud/app.py b/lenticular_cloud/app.py index 7301e93..7f3dacb 100644 --- a/lenticular_cloud/app.py +++ b/lenticular_cloud/app.py @@ -7,6 +7,7 @@ import time import subprocess import ory_hydra_client as hydra import ory_hydra_client.api.admin_api as hydra_admin_api +import os from ldap3 import Connection, Server, ALL @@ -26,11 +27,12 @@ def init_oauth2(app): -def init_app(name=None): - name = name or __name__ - app = Flask(name) +def create_app(): + name = "lenticular_cloud" + app = Flask(name, template_folder='template') app.config.from_pyfile('application.cfg') - app.config.from_pyfile('production.cfg') + active_cfg = os.getenv('CONFIG_FILE', 'production.cfg') + app.config.from_pyfile(active_cfg) app.jinja_env.globals['GIT_HASH'] = get_git_hash() diff --git a/application.cfg b/lenticular_cloud/application.cfg similarity index 97% rename from application.cfg rename to lenticular_cloud/application.cfg index 95df450..2303459 100644 --- a/application.cfg +++ b/lenticular_cloud/application.cfg @@ -3,7 +3,7 @@ SESSION_COOKIE_NAME='lc_session' SUBJECT_ID_HASH_SALT = 'salt' PREFERRED_URL_SCHEME = 'https' -DATA_FOLDER = "./data" +DATA_FOLDER = "../data" SQLALCHEMY_DATABASE_URI = f'sqlite:///{DATA_FOLDER}/db.sqlite' SQLALCHEMY_TRACK_MODIFICATIONS=False diff --git a/lenticular_cloud/auth_providers.py b/lenticular_cloud/auth_providers.py index 9e5accc..a662d83 100644 --- a/lenticular_cloud/auth_providers.py +++ b/lenticular_cloud/auth_providers.py @@ -70,7 +70,7 @@ class TotpAuthProvider(AuthProvider): def check_auth(user, form): data = form.data['totp'] if data is not None: - print(f'data totp: {data}') + #print(f'data totp: {data}') if len(user.totps) == 0: # migration, TODO remove return True for totp in user.totps: @@ -84,5 +84,5 @@ AUTH_PROVIDER_LIST = [ TotpAuthProvider ] -print(LdapAuthProvider.get_name()) +#print(LdapAuthProvider.get_name()) diff --git a/lenticular_cloud/cli.py b/lenticular_cloud/cli.py new file mode 100644 index 0000000..aa3dfc1 --- /dev/null +++ b/lenticular_cloud/cli.py @@ -0,0 +1,61 @@ +import argparse +from .model import db, User, UserSignUp +from .app import create_app + + +def entry_point(): + parser = argparse.ArgumentParser(description='lenticular_cloud cli') + subparsers = parser.add_subparsers() + + parser_user = subparsers.add_parser('user') + parser_user.set_defaults(func=cli_user) + + parser_signup = subparsers.add_parser('signup') + parser_signup.add_argument('--signup_id', type=int) + parser_signup.set_defaults(func=cli_signup) + + ''' + parser_upcoming = subparsers.add_parser('upcoming') + parser_upcoming.set_defaults(func=cli_upcoming) + parser_upcoming.add_argument('-a', '--all', help='shows all single order`', nargs='?', default=False, const=True, + type=bool, + required=False) + parser_upcoming.add_argument('-n', '--no-import', dest='noimport', help='do not a automatic import', nargs='?', + default=False, type=bool, required=False) + parser_upcoming.add_argument('-F', '--format', help='format can be `d`|`m`|`y`', default='d', required=False) + + # parser_select.add_argument('-F', '--format', help='format can be `d`|`m`|`y`', default='d', required=False) + # parser_select.add_argument('-f', '--from', help='from date in the format `yyyy-mm-dd`', required=False) + # parser_select.add_argument('-t', '--to', help='to date in the format `yyyy-mm-dd`', required=False) + ''' + args = parser.parse_args() + if 'func' not in args: + parser.print_help() + return + app = create_app() + with app.app_context(): + args.func(args) + + +def cli_user(args): + print(User.query.all()) + pass + +def cli_signup(args): + + print(args.signup_id) + if args.signup_id is not None: + user_data = UserSignUp.query.get(args.signup_id) + user = User.new(user_data) + + db.session.add(user) + db.session.delete(user_data) + db.session.commit() + else: + # list + print(UserSignUp.query.all()) + + +if __name__ == "__main__": + entry_point() + diff --git a/lenticular_cloud/model.py b/lenticular_cloud/model.py index 3f8eb5a..43d8e56 100644 --- a/lenticular_cloud/model.py +++ b/lenticular_cloud/model.py @@ -1,7 +1,7 @@ from flask import current_app from ldap3_orm import AttrDef, EntryBase as _EntryBase, ObjectDef, EntryType from ldap3_orm import Reader -from ldap3 import Entry, HASHED_SALTED_SHA256 +from ldap3 import Connection, Entry, HASHED_SALTED_SHA256 from ldap3.utils.conv import escape_filter_chars from ldap3.utils.hashed import hashed from flask_login import UserMixin @@ -19,6 +19,7 @@ from flask_sqlalchemy import SQLAlchemy, orm from datetime import datetime import uuid import pyotp +from typing import Optional logger = logging.getLogger(__name__) @@ -226,6 +227,8 @@ class User(EntryBase): db.String(length=36), primary_key=True, default=generate_uuid) username = db.Column( db.String, unique=True, nullable=False) + alternative_email = db.Column( + db.String, nullable=True) created_at = db.Column(db.DateTime, nullable=False, default=datetime.now) modified_at = db.Column(db.DateTime, nullable=False, @@ -236,7 +239,7 @@ class User(EntryBase): dn = "uid={uid},{base_dn}" base_dn = "ou=users,{_base_dn}" - object_classes = ["top", "inetOrgPerson", "LenticularUser"] + object_classes = ["inetOrgPerson"] #, "LenticularUser"] def __init__(self, **kwargs): self._ldap_object = None @@ -247,57 +250,34 @@ class User(EntryBase): return True # TODO def get(self, key): - print(f'getitem: {key}') + print(f'getitem: {key}') # TODO def make_writeable(self): self._ldap_object = self._ldap_object.entry_writable() @property - def groups(self): + def groups(self) -> list[str]: if self.username == 'tuxcoder': return [Group(name='admin')] else: return [] @property - def entry_dn(self): + def entry_dn(self) -> str: return self._ldap_object.entry_dn @property - def fullname(self): - return self._ldap_object.fullname - - @property - def givenname(self): - return self._ldap_object.givenname - - @property - def surname(self): - return self._ldap_object.surname - - @property - def email(self): + def email(self) -> str: domain = current_app.config['DOMAIN'] return f'{self.username}@{domain}' return self._ldap_object.mail - @property - def alternative_email(self): - return self._ldap_object.altMail - - @property - def auth_role(self): - return self._ldap_object.authRole - - @property - def gpg_public_key(self): - return self._ldap_object.gpgPublicKey - - def change_password(self, password_new: str): + def change_password(self, password_new: str) -> bool: self.make_writeable() password_hashed = crypt.crypt(password_new) self._ldap_object.userPassword = ('{CRYPT}' + password_hashed).encode() self.ldap_commit() + return True class _query(EntryBase._query): @@ -312,7 +292,7 @@ class User(EntryBase): user._ldap_object = ldap_object return user - def by_username(self, username) -> 'User': + def by_username(self, username) -> Optional['User']: result = self._query('(uid={username:s})'.format(username=escape_filter_chars(username))) if len(result) > 0: return result[0] diff --git a/static/0747be4cba2f8600544f4f09645d971a.eot b/lenticular_cloud/static/0747be4cba2f8600544f4f09645d971a.eot similarity index 100% rename from static/0747be4cba2f8600544f4f09645d971a.eot rename to lenticular_cloud/static/0747be4cba2f8600544f4f09645d971a.eot diff --git a/static/0e3a1d21d686f575466c.woff b/lenticular_cloud/static/0e3a1d21d686f575466c.woff similarity index 100% rename from static/0e3a1d21d686f575466c.woff rename to lenticular_cloud/static/0e3a1d21d686f575466c.woff diff --git a/static/11f8f4390108e2dbbecc.eot b/lenticular_cloud/static/11f8f4390108e2dbbecc.eot similarity index 100% rename from static/11f8f4390108e2dbbecc.eot rename to lenticular_cloud/static/11f8f4390108e2dbbecc.eot diff --git a/static/18df003f90a7f1313b98b23384ec4f1b.svg b/lenticular_cloud/static/18df003f90a7f1313b98b23384ec4f1b.svg similarity index 100% rename from static/18df003f90a7f1313b98b23384ec4f1b.svg rename to lenticular_cloud/static/18df003f90a7f1313b98b23384ec4f1b.svg diff --git a/static/1bd1c50561e60e950243.woff2 b/lenticular_cloud/static/1bd1c50561e60e950243.woff2 similarity index 100% rename from static/1bd1c50561e60e950243.woff2 rename to lenticular_cloud/static/1bd1c50561e60e950243.woff2 diff --git a/static/1e8dd192f6a341566fed.svg b/lenticular_cloud/static/1e8dd192f6a341566fed.svg similarity index 100% rename from static/1e8dd192f6a341566fed.svg rename to lenticular_cloud/static/1e8dd192f6a341566fed.svg diff --git a/static/23f19bb08961f37aaf692ff943823453.eot b/lenticular_cloud/static/23f19bb08961f37aaf692ff943823453.eot similarity index 100% rename from static/23f19bb08961f37aaf692ff943823453.eot rename to lenticular_cloud/static/23f19bb08961f37aaf692ff943823453.eot diff --git a/static/2f517e09eb2ca6650ff5bec5a95157ab.svg b/lenticular_cloud/static/2f517e09eb2ca6650ff5bec5a95157ab.svg similarity index 100% rename from static/2f517e09eb2ca6650ff5bec5a95157ab.svg rename to lenticular_cloud/static/2f517e09eb2ca6650ff5bec5a95157ab.svg diff --git a/static/32267f3b4db33a7c85ee31d9b317c9e4.ttf b/lenticular_cloud/static/32267f3b4db33a7c85ee31d9b317c9e4.ttf similarity index 100% rename from static/32267f3b4db33a7c85ee31d9b317c9e4.ttf rename to lenticular_cloud/static/32267f3b4db33a7c85ee31d9b317c9e4.ttf diff --git a/static/325cc4de7e028236fc3a.woff b/lenticular_cloud/static/325cc4de7e028236fc3a.woff similarity index 100% rename from static/325cc4de7e028236fc3a.woff rename to lenticular_cloud/static/325cc4de7e028236fc3a.woff diff --git a/static/35de2c9037c7da064e7b.eot b/lenticular_cloud/static/35de2c9037c7da064e7b.eot similarity index 100% rename from static/35de2c9037c7da064e7b.eot rename to lenticular_cloud/static/35de2c9037c7da064e7b.eot diff --git a/static/3c45c98f6f6c1b009c082510d0255ef4.svg b/lenticular_cloud/static/3c45c98f6f6c1b009c082510d0255ef4.svg similarity index 100% rename from static/3c45c98f6f6c1b009c082510d0255ef4.svg rename to lenticular_cloud/static/3c45c98f6f6c1b009c082510d0255ef4.svg diff --git a/static/4689f52cc96215721344e51e5831eec1.svg b/lenticular_cloud/static/4689f52cc96215721344e51e5831eec1.svg similarity index 100% rename from static/4689f52cc96215721344e51e5831eec1.svg rename to lenticular_cloud/static/4689f52cc96215721344e51e5831eec1.svg diff --git a/static/483f64f5a997c40908d9.ttf b/lenticular_cloud/static/483f64f5a997c40908d9.ttf similarity index 100% rename from static/483f64f5a997c40908d9.ttf rename to lenticular_cloud/static/483f64f5a997c40908d9.ttf diff --git a/static/491974d108fe4002b2aaf7ffc48249a0.ttf b/lenticular_cloud/static/491974d108fe4002b2aaf7ffc48249a0.ttf similarity index 100% rename from static/491974d108fe4002b2aaf7ffc48249a0.ttf rename to lenticular_cloud/static/491974d108fe4002b2aaf7ffc48249a0.ttf diff --git a/static/4e09b22eab5a6ed18106.ttf b/lenticular_cloud/static/4e09b22eab5a6ed18106.ttf similarity index 100% rename from static/4e09b22eab5a6ed18106.ttf rename to lenticular_cloud/static/4e09b22eab5a6ed18106.ttf diff --git a/static/527940b104eb2ea366c8630f3f038603.ttf b/lenticular_cloud/static/527940b104eb2ea366c8630f3f038603.ttf similarity index 100% rename from static/527940b104eb2ea366c8630f3f038603.ttf rename to lenticular_cloud/static/527940b104eb2ea366c8630f3f038603.ttf diff --git a/static/5579179abfd0e766dcc4.woff2 b/lenticular_cloud/static/5579179abfd0e766dcc4.woff2 similarity index 100% rename from static/5579179abfd0e766dcc4.woff2 rename to lenticular_cloud/static/5579179abfd0e766dcc4.woff2 diff --git a/static/5818bbd07dfd7095920a592049f5d9bd.ttf b/lenticular_cloud/static/5818bbd07dfd7095920a592049f5d9bd.ttf similarity index 100% rename from static/5818bbd07dfd7095920a592049f5d9bd.ttf rename to lenticular_cloud/static/5818bbd07dfd7095920a592049f5d9bd.ttf diff --git a/static/607a77859353c0cc1882b51e1e269d38.eot b/lenticular_cloud/static/607a77859353c0cc1882b51e1e269d38.eot similarity index 100% rename from static/607a77859353c0cc1882b51e1e269d38.eot rename to lenticular_cloud/static/607a77859353c0cc1882b51e1e269d38.eot diff --git a/static/743ca6ddfd9a36a8d2a9.woff2 b/lenticular_cloud/static/743ca6ddfd9a36a8d2a9.woff2 similarity index 100% rename from static/743ca6ddfd9a36a8d2a9.woff2 rename to lenticular_cloud/static/743ca6ddfd9a36a8d2a9.woff2 diff --git a/static/77206a6bb316fa0aded5083cc57f92b9.eot b/lenticular_cloud/static/77206a6bb316fa0aded5083cc57f92b9.eot similarity index 100% rename from static/77206a6bb316fa0aded5083cc57f92b9.eot rename to lenticular_cloud/static/77206a6bb316fa0aded5083cc57f92b9.eot diff --git a/static/7a8b4f130182d19a2d7c67d80c090397.svg b/lenticular_cloud/static/7a8b4f130182d19a2d7c67d80c090397.svg similarity index 100% rename from static/7a8b4f130182d19a2d7c67d80c090397.svg rename to lenticular_cloud/static/7a8b4f130182d19a2d7c67d80c090397.svg diff --git a/static/7eefe04dc985dd4ad38bd7f4ec0c20a0.eot b/lenticular_cloud/static/7eefe04dc985dd4ad38bd7f4ec0c20a0.eot similarity index 100% rename from static/7eefe04dc985dd4ad38bd7f4ec0c20a0.eot rename to lenticular_cloud/static/7eefe04dc985dd4ad38bd7f4ec0c20a0.eot diff --git a/static/9bbb245e67a133f6e486d8d2545e14a5.eot b/lenticular_cloud/static/9bbb245e67a133f6e486d8d2545e14a5.eot similarity index 100% rename from static/9bbb245e67a133f6e486d8d2545e14a5.eot rename to lenticular_cloud/static/9bbb245e67a133f6e486d8d2545e14a5.eot diff --git a/static/9ee3167f5dbdeaa1d0ac.ttf b/lenticular_cloud/static/9ee3167f5dbdeaa1d0ac.ttf similarity index 100% rename from static/9ee3167f5dbdeaa1d0ac.ttf rename to lenticular_cloud/static/9ee3167f5dbdeaa1d0ac.ttf diff --git a/static/ab47faeab8ddc5f809ec2a5377c1fbe4.svg b/lenticular_cloud/static/ab47faeab8ddc5f809ec2a5377c1fbe4.svg similarity index 100% rename from static/ab47faeab8ddc5f809ec2a5377c1fbe4.svg rename to lenticular_cloud/static/ab47faeab8ddc5f809ec2a5377c1fbe4.svg diff --git a/static/bd35285fb9ba36fffede.svg b/lenticular_cloud/static/bd35285fb9ba36fffede.svg similarity index 100% rename from static/bd35285fb9ba36fffede.svg rename to lenticular_cloud/static/bd35285fb9ba36fffede.svg diff --git a/static/be9ee23c0c6390141475d519c2c5fb8f.ttf b/lenticular_cloud/static/be9ee23c0c6390141475d519c2c5fb8f.ttf similarity index 100% rename from static/be9ee23c0c6390141475d519c2c5fb8f.ttf rename to lenticular_cloud/static/be9ee23c0c6390141475d519c2c5fb8f.ttf diff --git a/static/c3146b3524e97475c094343e848a7370.ttf b/lenticular_cloud/static/c3146b3524e97475c094343e848a7370.ttf similarity index 100% rename from static/c3146b3524e97475c094343e848a7370.ttf rename to lenticular_cloud/static/c3146b3524e97475c094343e848a7370.ttf diff --git a/static/c66020adf2c225335d44.eot b/lenticular_cloud/static/c66020adf2c225335d44.eot similarity index 100% rename from static/c66020adf2c225335d44.eot rename to lenticular_cloud/static/c66020adf2c225335d44.eot diff --git a/static/c995ad8b60ffa36d9db8.woff b/lenticular_cloud/static/c995ad8b60ffa36d9db8.woff similarity index 100% rename from static/c995ad8b60ffa36d9db8.woff rename to lenticular_cloud/static/c995ad8b60ffa36d9db8.woff diff --git a/static/d30895b927a0eb92ca19.svg b/lenticular_cloud/static/d30895b927a0eb92ca19.svg similarity index 100% rename from static/d30895b927a0eb92ca19.svg rename to lenticular_cloud/static/d30895b927a0eb92ca19.svg diff --git a/static/main.css b/lenticular_cloud/static/main.css similarity index 100% rename from static/main.css rename to lenticular_cloud/static/main.css diff --git a/static/main.css.map b/lenticular_cloud/static/main.css.map similarity index 100% rename from static/main.css.map rename to lenticular_cloud/static/main.css.map diff --git a/static/main.js b/lenticular_cloud/static/main.js similarity index 100% rename from static/main.js rename to lenticular_cloud/static/main.js diff --git a/static/main.js.LICENSE.txt b/lenticular_cloud/static/main.js.LICENSE.txt similarity index 100% rename from static/main.js.LICENSE.txt rename to lenticular_cloud/static/main.js.LICENSE.txt diff --git a/static/main.js.map b/lenticular_cloud/static/main.js.map similarity index 100% rename from static/main.js.map rename to lenticular_cloud/static/main.js.map diff --git a/templates/admin/base.html.j2 b/lenticular_cloud/template/admin/base.html.j2 similarity index 100% rename from templates/admin/base.html.j2 rename to lenticular_cloud/template/admin/base.html.j2 diff --git a/templates/admin/index.html.j2 b/lenticular_cloud/template/admin/index.html.j2 similarity index 100% rename from templates/admin/index.html.j2 rename to lenticular_cloud/template/admin/index.html.j2 diff --git a/templates/admin/registrations.html.j2 b/lenticular_cloud/template/admin/registrations.html.j2 similarity index 100% rename from templates/admin/registrations.html.j2 rename to lenticular_cloud/template/admin/registrations.html.j2 diff --git a/templates/admin/users.html.j2 b/lenticular_cloud/template/admin/users.html.j2 similarity index 100% rename from templates/admin/users.html.j2 rename to lenticular_cloud/template/admin/users.html.j2 diff --git a/templates/auth/base.html.j2 b/lenticular_cloud/template/auth/base.html.j2 similarity index 100% rename from templates/auth/base.html.j2 rename to lenticular_cloud/template/auth/base.html.j2 diff --git a/templates/auth/consent.html.j2 b/lenticular_cloud/template/auth/consent.html.j2 similarity index 100% rename from templates/auth/consent.html.j2 rename to lenticular_cloud/template/auth/consent.html.j2 diff --git a/templates/auth/login.html.j2 b/lenticular_cloud/template/auth/login.html.j2 similarity index 100% rename from templates/auth/login.html.j2 rename to lenticular_cloud/template/auth/login.html.j2 diff --git a/templates/auth/login_auth.html.j2 b/lenticular_cloud/template/auth/login_auth.html.j2 similarity index 100% rename from templates/auth/login_auth.html.j2 rename to lenticular_cloud/template/auth/login_auth.html.j2 diff --git a/templates/auth/sign_up.html.j2 b/lenticular_cloud/template/auth/sign_up.html.j2 similarity index 100% rename from templates/auth/sign_up.html.j2 rename to lenticular_cloud/template/auth/sign_up.html.j2 diff --git a/templates/base.html.j2 b/lenticular_cloud/template/base.html.j2 similarity index 100% rename from templates/base.html.j2 rename to lenticular_cloud/template/base.html.j2 diff --git a/templates/frontend/base.html.j2 b/lenticular_cloud/template/frontend/base.html.j2 similarity index 100% rename from templates/frontend/base.html.j2 rename to lenticular_cloud/template/frontend/base.html.j2 diff --git a/templates/frontend/client_cert.html.j2 b/lenticular_cloud/template/frontend/client_cert.html.j2 similarity index 100% rename from templates/frontend/client_cert.html.j2 rename to lenticular_cloud/template/frontend/client_cert.html.j2 diff --git a/templates/frontend/client_cert_new.html.j2 b/lenticular_cloud/template/frontend/client_cert_new.html.j2 similarity index 100% rename from templates/frontend/client_cert_new.html.j2 rename to lenticular_cloud/template/frontend/client_cert_new.html.j2 diff --git a/templates/frontend/fido2.html.j2 b/lenticular_cloud/template/frontend/fido2.html.j2 similarity index 100% rename from templates/frontend/fido2.html.j2 rename to lenticular_cloud/template/frontend/fido2.html.j2 diff --git a/templates/frontend/index.html.j2 b/lenticular_cloud/template/frontend/index.html.j2 similarity index 100% rename from templates/frontend/index.html.j2 rename to lenticular_cloud/template/frontend/index.html.j2 diff --git a/templates/frontend/oauth2_tokens.html.j2 b/lenticular_cloud/template/frontend/oauth2_tokens.html.j2 similarity index 100% rename from templates/frontend/oauth2_tokens.html.j2 rename to lenticular_cloud/template/frontend/oauth2_tokens.html.j2 diff --git a/templates/frontend/oidc_authentication.html.j2 b/lenticular_cloud/template/frontend/oidc_authentication.html.j2 similarity index 100% rename from templates/frontend/oidc_authentication.html.j2 rename to lenticular_cloud/template/frontend/oidc_authentication.html.j2 diff --git a/templates/frontend/password_change.html.j2 b/lenticular_cloud/template/frontend/password_change.html.j2 similarity index 100% rename from templates/frontend/password_change.html.j2 rename to lenticular_cloud/template/frontend/password_change.html.j2 diff --git a/templates/frontend/totp.html.j2 b/lenticular_cloud/template/frontend/totp.html.j2 similarity index 100% rename from templates/frontend/totp.html.j2 rename to lenticular_cloud/template/frontend/totp.html.j2 diff --git a/templates/frontend/totp_new.html.j2 b/lenticular_cloud/template/frontend/totp_new.html.j2 similarity index 100% rename from templates/frontend/totp_new.html.j2 rename to lenticular_cloud/template/frontend/totp_new.html.j2 diff --git a/templates/logout.jinja2 b/lenticular_cloud/template/logout.jinja2 similarity index 100% rename from templates/logout.jinja2 rename to lenticular_cloud/template/logout.jinja2 diff --git a/templates/skelet.html.j2 b/lenticular_cloud/template/skelet.html.j2 similarity index 100% rename from templates/skelet.html.j2 rename to lenticular_cloud/template/skelet.html.j2 diff --git a/lenticular_cloud/translations/__init__.py b/lenticular_cloud/translations/__init__.py index 3796158..28ba73c 100644 --- a/lenticular_cloud/translations/__init__.py +++ b/lenticular_cloud/translations/__init__.py @@ -1,6 +1,7 @@ from flask import g, request, Flask from flask_login import current_user from typing import Optional +from lenticular_cloud.model import db, User LANGUAGES = { 'en': 'English', diff --git a/lenticular_cloud/views/admin.py b/lenticular_cloud/views/admin.py index ef5997d..098d42a 100644 --- a/lenticular_cloud/views/admin.py +++ b/lenticular_cloud/views/admin.py @@ -15,9 +15,9 @@ def before_request(): try: resp = current_app.oauth.session.get('/userinfo') data = resp.json() - if not current_user.is_authenticated or resp.status_code is not 200: + if not current_user.is_authenticated or resp.status_code != 200: return redirect_login() - if 'admin' not in data['groups']: + if 'groups' not in data or 'admin' not in data['groups']: return 'Not an admin', 403 except TokenExpiredError: return redirect_login() diff --git a/lenticular_cloud/views/auth.py b/lenticular_cloud/views/auth.py index 3340e41..194d455 100644 --- a/lenticular_cloud/views/auth.py +++ b/lenticular_cloud/views/auth.py @@ -86,7 +86,8 @@ def login(): login_challenge = request.args.get('login_challenge') try: login_request = current_app.hydra_api.get_login_request(login_challenge) - except ory_hydra_client.exceptions.ApiException: + except ory_hydra_client.exceptions.ApiException as e: + logger.exception("could not fetch login request") return redirect(url_for('frontend.index')) if login_request.skip: diff --git a/lenticular_cloud/views/frontend.py b/lenticular_cloud/views/frontend.py index 4538fb1..bade548 100644 --- a/lenticular_cloud/views/frontend.py +++ b/lenticular_cloud/views/frontend.py @@ -31,7 +31,7 @@ def redirect_login(): def before_request(): try: resp = current_app.oauth.session.get('/userinfo') - if not current_user.is_authenticated or resp.status_code is not 200: + if not current_user.is_authenticated or resp.status_code != 200: logger.info('user not logged in redirect') return redirect_login() except TokenExpiredError: @@ -72,7 +72,7 @@ def init_login_manager(app): if not token: flash("Failed to log in.", category="error") return False - print(f'debug ---------------{token}') + #print(f'debug ---------------{token}') resp = blueprint.session.get("/userinfo") if not resp.ok: diff --git a/lenticular_cloud/wsgi.py b/lenticular_cloud/wsgi.py new file mode 100644 index 0000000..af8ef56 --- /dev/null +++ b/lenticular_cloud/wsgi.py @@ -0,0 +1,4 @@ +from .app import create_app + +application = create_app() + diff --git a/requirements-dev.txt b/requirements-dev.txt new file mode 100644 index 0000000..c47de40 --- /dev/null +++ b/requirements-dev.txt @@ -0,0 +1 @@ +flask-debug diff --git a/requirements.txt b/requirements.txt index 13d56d7..3cf88a7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,5 +17,4 @@ requests_oauthlib blinker ory-hydra-client -flask-debug diff --git a/schema/lenticular.ldif b/schema/lenticular.ldif new file mode 100644 index 0000000..fd8a0c1 --- /dev/null +++ b/schema/lenticular.ldif @@ -0,0 +1,60 @@ +dn: cn=lenticular,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: lenticular +olcAttributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.1 + NAME 'masterPasswordEnable' + DESC 'is the master password enabled' + EQUALITY booleanMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 + SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.2 + NAME 'authRole' + DESC 'is the master password enabled' + EQUALITY caseIgnoreMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 ) +olcAttributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.3 + NAME ( 'altMail' ) + DESC 'RFC1274: RFC822 Mailbox' + EQUALITY caseIgnoreIA5Match + SUBSTR caseIgnoreIA5SubstringsMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} ) +olcAttributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.4 + NAME 'gpgPublicKey' + DESC 'pgpPublicKey as ascii text' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcAttributeTypes: ( 1.3.6.1.4.1.18060.0.4.3.2.5 + NAME 'totpSecret' + DESC 'TOTP secret as base32' + EQUALITY octetStringMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 ) +olcObjectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.1 + NAME 'service' + DESC 'schema for a service' + SUP top STRUCTURAL + MUST uid + MAY ( masterPasswordEnable $ mail ) ) +olcObjectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.2 + NAME 'LenticularUser' + DESC 'a Lenticular user' + SUP top AUXILIARY + MUST uid + MAY ( authRole $ altMail $ gpgPublicKey ) ) +olcObjectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.3 + NAME 'LenticularGroup' + DESC 'a Lenticular group' + SUP top AUXILIARY + MUST cn + MAY ( authRole ) ) +#olcObjectClasses: ( 1.3.6.1.4.1.18060.0.4.3.3.4 +# NAME 'posixAccountAux' +# DESC 'Abstraction of an account with POSIX attributes' +# SUP top AUXILIARY +# MUST ( cn $ uid $ uidNumber $ gidNumber $ homeDirectory ) +# MAY ( userPassword $ loginShell $ gecos $ description ) ) +#olcObjectClasses: ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' SUP top AUXILIARY +# DESC 'Abstraction of a group of accounts' +# MUST gidNumber +# MAY ( userPassword $ memberUid $ +# description ) ) + diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 171c67f..0000000 --- a/setup.cfg +++ /dev/null @@ -1,25 +0,0 @@ -[metadata] -name = lenticular_cloud -version = 0.0.1 -description = user management portal - -[options] -packages = lenticular_cloud -install_requires = - Flask - gunicorn - flask_babel - flask_wtf - flask_login - flask_sqlalchemy - Flask-Dance - ldap3 - ldap3_orm - python-u2flib-server - pyotp - cryptography - requests - requests_oauthlib - blinker - ory-hydra-client - flask-debug diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..391db36 --- /dev/null +++ b/setup.py @@ -0,0 +1,26 @@ +from setuptools import setup, find_packages +from pathlib import Path + + +TESTS_DIRECTORY = 'test' + +def get_requirements(): + return [] + with Path("./requirements.txt").open('r') as fd: + return fd.readlines() + + +setup( + name='lenticular_cloud', + version='0.0.1', + description='A useful module', + author='tuxcoder', + author_email='git@o-g.at', + packages=find_packages(exclude=(TESTS_DIRECTORY,)), + include_package_data=True, + install_requires=get_requirements(), # external packages as dependencies + entry_points = { + 'console_scripts': ['lenticular_cloud-cli=lenticular_cloud.cli:entry_point'] + } +) + diff --git a/tox.ini b/tox.ini index 2cca759..6e4ebd0 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ -[tox] -isolated_build = true +#[tox] +#isolated_build = true [testenv] deps = diff --git a/wsgi.py b/wsgi.py index 9a3dd38..3ad7955 100644 --- a/wsgi.py +++ b/wsgi.py @@ -1,9 +1,8 @@ import logging -from lenticular_cloud.app import init_app +from lenticular_cloud.app import create_app -name = 'oidc_provider' -app = init_app(name) +app = create_app() logging.basicConfig(level=logging.DEBUG)