FORMAT_US_DATE = "%x"
FORMAT_US_DATE_TIME = '%x %X'
FORMAT_US_DATE_TIME_ZONE = '%x %X %Z%z'
FORMAT_DATABASE_DATE_TIME = "%Y-%m-%d %H:%M:%S"
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'tiff',
                          'zip', 'tar', 'tgz', 'bz2'])
FLASH_CATEGORY_ERROR = 'error'
FLASH_CATEGORY_INFO = 'info'
def _get_remote_addr():
def _get_user_agent():
def _create_salt():
def _generate_sha512_hmac(pepper, salt, data):
def generate_auth(pepper, password):
def is_valid_auth(pepper, salt, candidate_password, correct_hash):
def clean_str(dangerous):
def clean_int(dangerous):
def get_safe_int(unsafe, default=1, min_allowed=1, max_allowed=None):
def flash_error(msg):
def flash_info(msg):
def pack(data):
def pack_error(msg):
def jsonify_error(data):
def jsonify_success(data):
def get_db_friendly_date_time():
def localize_datetime(value, zone_name='US/Eastern'):
def localize_est_date(value):
def localize_est_datetime(value):
def get_expiration_date(offset_days):
def compute_text_md5(text):
def get_email_token(email, salt, secret):
def get_email_from_token(token, salt, secret, max_age=86400):
def redcap_api_call(url, token, content, fields, max_time):
def retrieve_redcap_subjects(url, token, fields, max_time=30):
def retrieve_redcap_events(url, token, max_time=30): class CRUDMixin(object):
    """ Helper class flask-sqlalchemy entities """
    __table_args__ = {'extend_existing': True}

    id = db.Column(db.Integer, primary_key=True)

    @classmethod
    def get_by_id(cls, id):
        if any(
            (isinstance(id, basestring) and id.isdigit(),
             isinstance(id, (int, float))),
        ):
            return cls.query.get(int(id))
        return None


    @classmethod
    def create(cls, **kwargs):
        """ Helper for session.add() + session.commit() """
        instance = cls(**kwargs)
        return instance.save()


    def update(self, commit=True, **kwargs):
        for attr, value in kwargs.iteritems():
            setattr(self, attr, value)
        return commit and self.save() or self


    def save(self, commit=True):
        db.session.add(self)
        if commit:
            db.session.commit()
        return self


    def delete(self, commit=True):
        db.session.delete(self)
        return commit and db.session.commit() class LogTypeEntity(db.Model, CRUDMixin):

    """ Stores types of logs """
    __tablename__ = 'LogType'

    id = db.Column('logtID', db.Integer, primary_key=True)
    type = db.Column('logtType', db.String(255), nullable=False)
    description = db.Column('logtDescription', db.Text, nullable=False)

    def __repr__(self):
        """ Return a friendly object representation """
        return ("<LogTypeEntity(id: {0.id}, "
                "logtType: {0.type}, "
                "logtDescription: {0.description})>"
                .format(self)) class WebSessionEntity(db.Model, CRUDMixin):
    """Store web session details"""
    __tablename__ = 'WebSession'

    id = db.Column('webID', db.Integer, primary_key=True)
    session_id = db.Column('webSessID', db.String(255), nullable=False,
                           default='')
    user_id = db.Column('usrID', db.Integer,
                        db.ForeignKey('User.usrID'),
                        nullable=False,
                        default=0)
    ip = db.Column('webIP', db.String(15), nullable=False, default='')
    date_time = db.Column('webDateTime', db.DateTime, nullable=False,
                          default=datetime.datetime(datetime.MINYEAR, 1, 1))
    user_agent_id = db.Column('uaID', db.Integer,
                              db.ForeignKey('UserAgent.uaID'),
                              nullable=False)
    # @OneToMany
    user_agent = db.relationship(UserAgentEntity, lazy='joined')
    user = db.relationship(UserEntity, lazy='joined')

    @staticmethod
    def get_by_session_id(session_id):
        """ Search helper: WHERE webSessID = ???"""
        return WebSessionEntity.query.filter_by(session_id=session_id).first()

    def __repr__(self):
        """ Return a friendly object representation """
        return "<WebSessionEntity (webID: '{0.id}', webSessID: {0.session_id},"\
               " usrID: {0.user_id}, webIP: {0.ip})>".format(self) LOG_TYPE_ACCOUNT_CREATED = 'account_created' LOG_TYPE_LOGIN = 'login' LOG_TYPE_LOGOUT = 'logout' LOG_TYPE_LOGIN_ERROR = 'login_error' LOG_TYPE_ACCOUNT_MODIFIED = 'account_modified'
import datetime
from app import utils
from app.crud_mixin import CRUDMixin
from app.main import app, db
from app.models.log_type_entity import LogTypeEntity
from app.models.web_session_entity import WebSessionEntity
from app.models.log_type_entity import \
    LOG_TYPE_ACCOUNT_CREATED, \
    LOG_TYPE_LOGIN, \
    LOG_TYPE_LOGOUT, \
    LOG_TYPE_LOGIN_ERROR, \
    LOG_TYPE_ACCOUNT_MODIFIED
"""
ORM for app.Log table

@authors:
  Andrei Sura             <sura.andrei@gmail.com>
  Ruchi Vivek Desai       <ruchivdesai@gmail.com>
  Sanath Pasumarthy       <sanath@ufl.edu>
  Taeber Rapczak          <taeber@ufl.edu>
"""



class LogEntity(db.Model, CRUDMixin):

    """ Keep track of important user actions """
    __tablename__ = 'Log'

    id = db.Column('logID', db.Integer, primary_key=True)
    type_id = db.Column('logtID', db.Integer,
                        db.ForeignKey('LogType.logtID'),
                        nullable=False)
    web_session_id = db.Column('webID', db.Integer,
                               db.ForeignKey('WebSession.webID'),
                               nullable=False)
    date_time = db.Column('logDateTime', db.DateTime, nullable=False,
                          server_default='0000-00-00 00:00:00')
    details = db.Column('logDetails', db.Text, nullable=False)

    # @OneToOne
    log_type = db.relationship(LogTypeEntity, uselist=False, lazy='joined')
    web_session = db.relationship(WebSessionEntity, uselist=False,
                                  lazy='joined')

    @staticmethod
    def get_logs(per_page=25, page_num=1):
        """
        Helper for formating the event details
        """
        def item_from_entity(entity):
            return {
                'id': entity.id,
                'user_email': entity.web_session.user.email
                if entity.web_session.user is not None else '',
                'type': entity.log_type.type,
                'details': entity.details,
                'web_session_ip': entity.web_session.ip,
                'date_time': utils.localize_est_datetime(entity.date_time),
            }

        pagination = LogEntity.query.paginate(page_num, per_page, False)
        items = map(item_from_entity, pagination.items)
        return items, pagination.pages

    @staticmethod
    def _log(log_type, session_id, details=''):
        """ Helper for logging """
        logt = LogTypeEntity.query.filter_by(type=log_type).first()
        if logt is None:
            app.logger.error("Developer error. Invalid log type: {}"
                             .format(log_type))
            return

        web_session = WebSessionEntity.get_by_session_id(session_id)
        if web_session is None:
            app.logger.error("Developer error. Invalid session id: {}"
                             .format(session_id))
            return

        LogEntity.create(log_type=logt,
                         date_time=datetime.datetime.now(),
                         details=details,
                         web_session=web_session)

    @staticmethod
    def account_created(session_id, details=''):
        """ Log account creation """
        LogEntity._log(LOG_TYPE_ACCOUNT_CREATED, session_id, details)

    @staticmethod
    def login(session_id, details=''):
        """ Log successful login """

        LogEntity._log(LOG_TYPE_LOGIN, session_id, details)