# Path: src/logcfg.py
# DEBUG_TEMPL = '  %(levelname)-7.7s %(funcName)s: %(message)s'
# PROD_TEMPL  = '%(asctime)s %(levelname)-7.7s %(funcName)s: %(message)s'
# DEBUG = logging.DEBUG
# class ColorFmtr(Formatter):
#     def __init__(self, *args, **kwargs):
#     def format(self, record):
# def makefunc(level):
#         def tb_func(msg, *args, **kwargs):
#     def thefunc(msg, *args, **kwargs):
# 
# Path: src/main.py
# def on_shutdown():
# 
# Path: src/models.py
# class Orgs(BaseMixin, db.Model):
#     ''' Organization, aka multi-tenant model. '''
#     # don't want duplicate names in this table:
#     name = Column(String(64), index=True, nullable=False, unique=True)
#     users = db.relationship('Users', lazy='dynamic')
# 
#     def __init__(self, name, desc=''):  # needs to have defaults for admin
#         self.name = name
#         self.desc = desc
# 
# class Roles(MultiTenantBase, RoleMixin, db.Model):
#     name = Column(String(64), nullable=False, unique=True)  # don't want dups
# 
#     def __init__(self, name='', org=None, desc=''):
#         self.name = name
#         self.org = org
#         self.desc = desc
# 
# class Users(MultiTenantBase, UserMixin, db.Model):
#     name = Column(String(127), nullable=True)               # optional
#     active = Column(Boolean, nullable=False, default=True)  # req security
#     admin = Column(Boolean, nullable=False, default=False)
#     email = Column(String(64), index=True, unique=True, nullable=False)
#     password = Column(String(72), nullable=False)  # bcrypt.length = 60
#     timezone = Column(TimezoneType(backend='pytz'))
# 
#     confirmed_at = Column(DateTime)
#     last_login_at = Column(DateTime)
#     current_login_at = Column(DateTime)
#     login_count = Column(Integer, default=0)
#     last_login_ip = Column(IPAddressType)
#     current_login_ip = Column(IPAddressType)
# 
#     roles = db.relationship('Roles', secondary=roles_users,
#                             backref='users', lazy='dynamic')
# 
#     def __init__(self, name='', email='', desc='', password=None,
#                  active=True, admin=False, org=None, roles=None, timezone=None):
#         self.active = active
#         self.admin = admin
#         self.desc = desc
#         self.email = email
#         self.name = name
#         self.timezone = timezone
# 
#         if password:
#             self.set_password(password)
#         if roles is not None:
#             if type(roles) is not list:
#                 roles = [roles]
#             self.roles = roles
# 
#         if type(org) is str:
#             orgobj = Orgs.query.filter_by(name=org).first()
#             if orgobj:
#                 org = orgobj
#             else:
#                 org = Orgs(name=org)
#                 db.session.add(org)
#                 db.session.commit()
#         self.org = org
# 
#     def set_password(self, password):
#         try:
#             self.password = encrypt_password(password)
#         except RuntimeError:  # :-/
#             with app.app_context():
#                 self.password = encrypt_password(password)
# 
#     def check_password(self, password):
#         return verify_password(password, self.password)
# 
#     def __repr__(self):
#         return '<%s %r>' % (self.__class__.__name__, self.email)
# 
# Path: src/timezones.py

# 
# Path: src/utils.py
# def first_of(*paths, root='src/templates'):
#     ''' return first existing path. '''
#     for path in paths:
#         test_path = join(root, path)
#         log.debug('looking for template at: %r', test_path)
#         if exists(test_path):
#             return path


import sys
    import inspect
from collections import defaultdict
from flask_admin.base import AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView
from flask_admin.form import SecureForm
from flask_admin.form.fields import Select2Field
from flask_login import current_user
from wtforms.fields import PasswordField
from .logcfg import log
from .main import db
from .models import Orgs, Roles, Users  # noqa: F401  # they are used
from .timezones import all_tz
from .utils import first_of
        from .main import adm
    from .main import adm
    from flask_admin.menu import MenuLink
    from .config import APP_MENU_LINKS

# menu icons
category_icon_classes = dict(
    People='glyphicon glyphicon-briefcase',  # group n/a :-(
    App='glyphicon glyphicon-list',
    Network='glyphicon glyphicon-cloud',
)


# admin home page view
class HomeView(AdminIndexView):
    @expose('/')
    def index(self):

        # divide into buckets
        cats = defaultdict(list)  # each category holds a list
        for view in adm._views:
            catname = getattr(view, '_category', '')
            cats[catname].append(view)
        # sort
        sortedcats = []
        sortedcats.append( ('', cats.pop('', [])) )               # first, home
        sortedcats.append( ('People', cats.pop('People', [])) )   # then peeps
        for catname in sorted(cats):            # add remaining app categories
            sortedcats.append( (catname, cats[catname]) )
        log.debug('admin home view categories:\n%s', sortedcats)

        countstats = (
            ('Orgs', Orgs.query.filter_by(deleted=None).count()),
            ('Users', Users.query.filter_by(deleted=None).count()),

# Path: src/logcfg.py
# DEBUG_TEMPL = '  %(levelname)-7.7s %(funcName)s: %(message)s'
# PROD_TEMPL  = '%(asctime)s %(levelname)-7.7s %(funcName)s: %(message)s'
# DEBUG = logging.DEBUG
# class ColorFmtr(Formatter):
#     def __init__(self, *args, **kwargs):
#     def format(self, record):
# def makefunc(level):
#         def tb_func(msg, *args, **kwargs):
#     def thefunc(msg, *args, **kwargs):
# 
# Path: src/main.py
# def on_shutdown():
# 
# Path: src/models.py
# class Orgs(BaseMixin, db.Model):
#     ''' Organization, aka multi-tenant model. '''
#     # don't want duplicate names in this table:
#     name = Column(String(64), index=True, nullable=False, unique=True)
#     users = db.relationship('Users', lazy='dynamic')
# 
#     def __init__(self, name, desc=''):  # needs to have defaults for admin
#         self.name = name
#         self.desc = desc
# 
# class Roles(MultiTenantBase, RoleMixin, db.Model):
#     name = Column(String(64), nullable=False, unique=True)  # don't want dups
# 
#     def __init__(self, name='', org=None, desc=''):
#         self.name = name
#         self.org = org
#         self.desc = desc
# 
# class Users(MultiTenantBase, UserMixin, db.Model):
#     name = Column(String(127), nullable=True)               # optional
#     active = Column(Boolean, nullable=False, default=True)  # req security
#     admin = Column(Boolean, nullable=False, default=False)
#     email = Column(String(64), index=True, unique=True, nullable=False)
#     password = Column(String(72), nullable=False)  # bcrypt.length = 60
#     timezone = Column(TimezoneType(backend='pytz'))
# 
#     confirmed_at = Column(DateTime)
#     last_login_at = Column(DateTime)
#     current_login_at = Column(DateTime)
#     login_count = Column(Integer, default=0)
#     last_login_ip = Column(IPAddressType)
#     current_login_ip = Column(IPAddressType)
# 
#     roles = db.relationship('Roles', secondary=roles_users,
#                             backref='users', lazy='dynamic')
# 
#     def __init__(self, name='', email='', desc='', password=None,
#                  active=True, admin=False, org=None, roles=None, timezone=None):
#         self.active = active
#         self.admin = admin
#         self.desc = desc
#         self.email = email
#         self.name = name
#         self.timezone = timezone
# 
#         if password:
#             self.set_password(password)
#         if roles is not None:
#             if type(roles) is not list:
#                 roles = [roles]
#             self.roles = roles
# 
#         if type(org) is str:
#             orgobj = Orgs.query.filter_by(name=org).first()
#             if orgobj:
#                 org = orgobj
#             else:
#                 org = Orgs(name=org)
#                 db.session.add(org)
#                 db.session.commit()
#         self.org = org
# 
#     def set_password(self, password):
#         try:
#             self.password = encrypt_password(password)
#         except RuntimeError:  # :-/
#             with app.app_context():
#                 self.password = encrypt_password(password)
# 
#     def check_password(self, password):
#         return verify_password(password, self.password)
# 
#     def __repr__(self):
#         return '<%s %r>' % (self.__class__.__name__, self.email)
# 
# Path: src/timezones.py

# 
# Path: src/utils.py
# def first_of(*paths, root='src/templates'):
#     ''' return first existing path. '''
#     for path in paths:
#         test_path = join(root, path)
#         log.debug('looking for template at: %r', test_path)
#         if exists(test_path):
#             return path


# Path: src/admin.py
import sys
    import inspect
from collections import defaultdict
from flask_admin.base import AdminIndexView, expose
from flask_admin.contrib.sqla import ModelView
from flask_admin.form import SecureForm
from flask_admin.form.fields import Select2Field
from flask_login import current_user
from wtforms.fields import PasswordField
from .logcfg import log
from .main import db
from .models import Orgs, Roles, Users  # noqa: F401  # they are used
from .timezones import all_tz
from .utils import first_of
        from .main import adm
    from .main import adm
    from flask_admin.menu import MenuLink
    from .config import APP_MENU_LINKS


# menu icons
category_icon_classes = dict(
    People='glyphicon glyphicon-briefcase',  # group n/a :-(
    App='glyphicon glyphicon-list',
    Network='glyphicon glyphicon-cloud',
)


# admin home page view
class HomeView(AdminIndexView):
    @expose('/')
    def index(self):

        # divide into buckets
        cats = defaultdict(list)  # each category holds a list
        for view in adm._views:
            catname = getattr(view, '_category', '')
            cats[catname].append(view)
        # sort
        sortedcats = []
        sortedcats.append( ('', cats.pop('', [])) )               # first, home
        sortedcats.append( ('People', cats.pop('People', [])) )   # then peeps
        for catname in sorted(cats):            # add remaining app categories
            sortedcats.append( (catname, cats[catname]) )
        log.debug('admin home view categories:\n%s', sortedcats)

        countstats = (
            ('Orgs', Orgs.query.filter_by(deleted=None).count()),
            ('Users', Users.query.filter_by(deleted=None).count()),

            ('Roles', Roles.query.filter_by(deleted=None).count()),