Example #1
0
 def testconnection(self, param):
     """
     This function lets you test the to be saved SQL connection.
           
     :param param: A dictionary with all necessary parameter
                     to test the connection.
     :type param: dict
     
     :return: Tuple of success and a description
     :rtype: (bool, string)
     
     Parameters are: Server, Driver, Database, User, Password, Port,
                     Limit, Table, Map
                     Where, Encoding, conParams
         
     """
     num = -1
     desc = None
     
     connect_string = self._create_connect_string(param)
     log.info("using the connect string %s" % connect_string)
     engine = create_engine(connect_string)
     # create a configured "Session" class
     session = sessionmaker(bind=engine)()
     db = SQLSoup(engine)
     try:
         TABLE = db.entity(param.get("Table"))
         result = session.query(TABLE).count()
         num = result
         desc = "Found %i users." % num
     except Exception as exx:
         desc = "failed to retrieve users: %s" % exx
         
     return num, desc
Example #2
0
    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        usermap = config.get('Map', {})
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)

        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)
        log.info("using the connect string {0!s}".format(self.connect_string))
        try:
            log.debug("using pool_size={0!s} and pool_timeout={1!s}".format(
                      self.pool_size, self.pool_timeout))
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False,
                                        pool_size=self.pool_size,
                                        pool_timeout=self.pool_timeout)
        except TypeError:
            # The DB Engine/Poolclass might not support the pool_size.
            log.debug("connecting without pool_size.")
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False)
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)

        return self
Example #3
0
    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        self.password_hash_type = config.get("Password_Hash_Type", "SSHA256")
        usermap = config.get('Map', {})
        self.map = yaml.safe_load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)
        # recycle SQL connections after 2 hours by default
        # (necessary for MySQL servers, which terminate idle connections after some hours)
        self.pool_recycle = int(config.get('poolRecycle') or 7200)

        # create the connectstring like
        params = {
            'Port': self.port,
            'Password': self.password,
            'conParams': self.conParams,
            'Driver': self.driver,
            'User': self.user,
            'Server': self.server,
            'Database': self.database
        }
        self.connect_string = self._create_connect_string(params)

        # get an engine from the engine registry, using self.getResolverId() as the key,
        # which involves the connect string and the pool settings.
        self.engine = get_engine(self.getResolverId(), self._create_engine)
        # We use ``scoped_session`` to be sure that the SQLSoup object
        # also uses ``self.session``.
        Session = scoped_session(sessionmaker(bind=self.engine))
        # Session should be closed on teardown
        self.session = Session()
        register_finalizer(self.session.close)
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine, session=Session)
        self.db.session._model_changes = {}
        self.TABLE = self.db.entity(self.table)

        return self
Example #4
0
    def get_table(self, tablename):
        db = SQLSoup(
            "mysql+pymysql://cic_admin:159357a@{}:{}/cic_finance".format(
                '192.168.10.11', 3306))
        table = db.entity(tablename)
        records = table.all()
        res = [{
            key: val
            for key, val in record.__dict__.items() if not key.startswith('_')
        } for record in records]

        return res
Example #5
0
 def testconnection(self, param):
     '''
     This function lets you test the to be saved SQL connection.
           
     :param param: A dictionary with all necessary parameter to test the connection.
     :type param: dict
     
     :return: Tuple of success and a description
     :rtype: (bool, string)  
     
     Parameters are: Server, Driver, Database, User, Password, Port, Limit, Table, Map
                     Where, Encoding, conParams
         
     '''
     
     num=-1
     desc=None
     
     port = ""
     password = ""
     conParams = ""
     if param.get("Port"):
         port = ":%s" % param.get("Port")
     if param.get("Password"):
         password = "******" % param.get("Password")
     if param.get("conParams"):
         conParams = "?%s" % param.get("conParams")
     connect_string = "%s://%s%s%s%s%s/%s%s" % (param.get("Driver"),
                                                 param.get("User"),
                                                 password,
                                                 "@" if (param.get("User") or password) else "",
                                                 param.get("Server"),
                                                 port,
                                                 param.get("Database"),
                                                 conParams)
     log.info("using the connect string %s" % connect_string)
     engine = create_engine(connect_string)
     # create a configured "Session" class
     session = sessionmaker(bind=engine)()
     db = SQLSoup(engine)
     TABLE = db.entity(param.get("Table"))
         
     try:    
         result = session.query(TABLE).count()
         num = result
         desc = "Found %i users." % num
     except Exception as exx:
         desc = "failed to retrieve users: %s" % exx
         
     return (num, desc)
Example #6
0
 def check_email(self, email):
     db = SQLSoup(engine)
     try:
         result = db.accounts.filter(db.accounts.email == email).one()
         return "found"
     except:
         return "not found"
Example #7
0
 def check_username(self, username):
     db = SQLSoup(engine)
     try:
         result = db.accounts.filter(db.accounts.username == username).one()
         return "found"
     except:
         return "not found"
Example #8
0
 def get_account(self, username):
     db = SQLSoup(engine)
     try:
         result = db.accounts.filter(db.accounts.username == username).one()
         return result
     except:
         return -1
Example #9
0
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict

        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info(u"using the connect string {0!s}".format(
            censor_connect_string(connect_string)))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        Session = scoped_session(sessionmaker(bind=engine))
        session = Session()
        db = SQLSoup(engine, session=Session)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)
        finally:
            # We do not want any leftover DB connection, so we first need to close
            # the session such that the DB connection gets returned to the pool (it
            # is still open at that point!) and then dispose the engine such that the
            # checked-in connection gets closed.
            session.close()
            engine.dispose()

        return num, desc
Example #10
0
    def loadConfig(self, config):
        """
        Load the config from conf.
        
        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        usermap = config.get('Map', {})
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)
        
        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)
        log.info("using the connect string {0!s}".format(self.connect_string))
        try:
            log.debug("using pool_size={0!s} and pool_timeout={1!s}".format(
                      self.pool_size, self.pool_timeout))
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False,
                                        pool_size=self.pool_size,
                                        pool_timeout=self.pool_timeout)
        except TypeError:
            # The DB Engine/Poolclass might not support the pool_size.
            log.debug("connecting without pool_size.")
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False)
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)
        
        return self
Example #11
0
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict

        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info(u"using the connect string {0!s}".format(censor_connect_string(connect_string)))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        Session = scoped_session(sessionmaker(bind=engine))
        session = Session()
        db = SQLSoup(engine, session=Session)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)
        finally:
            # We do not want any leftover DB connection, so we first need to close
            # the session such that the DB connection gets returned to the pool (it
            # is still open at that point!) and then dispose the engine such that the
            # checked-in connection gets closed.
            session.close()
            engine.dispose()

        return num, desc
Example #12
0
    def create_account(self, params):
        db = SQLSoup(engine)

        # Generate a random 32 character number and get it's md5 hash
        random_num = randrange(100000000000000000000000000000000,
                               999999999999999999999999999999999, 2)
        salt = hashlib.md5(str(random_num).encode())

        # Concatenate the users password and salt, then hash it with sha256
        concat = str(params['password']) + str(salt.hexdigest())
        pass_hash = hashlib.sha256(concat.encode())

        db.accounts.insert(project_name=params['project_name'],
                           email=params['email'],
                           username=params['username'],
                           password=pass_hash.hexdigest(),
                           salt=salt.hexdigest())
        db.commit()
Example #13
0
	def __init__ (self, band, ip, db, update_interval=30, ttl=60*3):
		self.interval = update_interval
		self.ttl = ttl
		self.band = band 
		self.name = "log"
		#self.db = SqlSoup('mysql://*****:*****@192.168.3.99/ukac20130226')
		self.db = SqlSoup('mysql://*****:*****@%s/%s' % (ip, db))
		#self.db = SqlSoup('mysql://*****:*****@192.168.0.104/%s' %db)
		SpotSource.__init__(self)
Example #14
0
    def loadConfig(self, config, conf):
        '''
        Load the config from conf.
        
        :param config: The configuration from the Config Table
        :type config: dict
        :param conf: the instance of the configuration
        :type conf: string 
        
        The information which config entries we need to load is taken from
            manage.js: function save_sql_config
                    
        '''
        self.resolverId = conf
        self.server = self.getConfigEntry(config, 'privacyidea.sqlresolver.Server', conf)
        self.driver = self.getConfigEntry(config, 'privacyidea.sqlresolver.Driver', conf)
        self.database = self.getConfigEntry(config, 'privacyidea.sqlresolver.Database', conf)
        self.port = self.getConfigEntry(config, 'privacyidea.sqlresolver.Port', conf, required=False)
        self.limit = self.getConfigEntry(config, 'privacyidea.sqlresolver.Limit', conf, required=False, default=100)
        self.user = self.getConfigEntry(config, 'privacyidea.sqlresolver.User', conf)
        self.password = self.getConfigEntry(config, 'privacyidea.sqlresolver.Password', conf, required=False)
        self.table = self.getConfigEntry(config, 'privacyidea.sqlresolver.Table', conf)
        usermap = self.getConfigEntry(config, 'privacyidea.sqlresolver.Map', conf)
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v,k] for k,v in self.map.items()])
        self.where = self.getConfigEntry(config, 'privacyidea.sqlresolver.Where', conf, required=False)
        self.encoding = self.getConfigEntry(config, 'privacyidea.sqlresolver.Encoding', conf, required=False, default="latin1")
        self.conParams = self.getConfigEntry(config, 'privacyidea.sqlresolver.conParams', conf, required=False)      
        
        
        # create the connectstring like
        # driver://user:passwd@seerver/database?conParams
        port = ""
        password = ""
        if self.port:
            port = ":%s" % self.port
        if self.password:
            password = "******" % self.password
        self.connect_string = "%s://%s%s@%s%s/%s?%s" % (self.driver,
                                                        self.user,
                                                        password,
                                                        self.server,
                                                        port,
                                                        self.database,
                                                        self.conParams)
        log.info("using the connect string %s" % self.connect_string)
        self.engine = create_engine(self.connect_string, encoding=str(self.encoding))
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)
        
        return self
Example #15
0
 def __init__(self):
     if not self.singleton:
         self.__class__.singleton = True
     else:
         raise SystemError, 'SQLite3Vocab is singleton.'
     path = os.path.dirname(os.path.realpath(__file__))
     self.engine = SQLSoup('sqlite:////%s/sqlite3.db' % path)
     self.comune_id = self.engine.comuni.codice_istat
     self.provincia_id = self.engine.province.sigla
     self.regione_id = self.engine.regioni.codice_istat
Example #16
0
    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        self.password_hash_type = config.get("Password_Hash_Type", "SSHA256")
        usermap = config.get('Map', {})
        self.map = yaml.safe_load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)
        # recycle SQL connections after 2 hours by default
        # (necessary for MySQL servers, which terminate idle connections after some hours)
        self.pool_recycle = int(config.get('poolRecycle') or 7200)

        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)

        # get an engine from the engine registry, using self.getResolverId() as the key,
        # which involves the connect string and the pool settings.
        self.engine = get_engine(self.getResolverId(), self._create_engine)
        # We use ``scoped_session`` to be sure that the SQLSoup object
        # also uses ``self.session``.
        Session = scoped_session(sessionmaker(bind=self.engine))
        # Session should be closed on teardown
        self.session = Session()
        register_finalizer(self.session.close)
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine, session=Session)
        self.db.session._model_changes = {}
        self.TABLE = self.db.entity(self.table)

        return self
Example #17
0
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.
              
        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict
        
        :return: Tuple of success and a description
        :rtype: (bool, string)
        
        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams
            
        """
        num = -1
        desc = None
        
        connect_string = cls._create_connect_string(param)
        log.info("using the connect string {0!s}".format(connect_string))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        session = sessionmaker(bind=engine)()
        db = SQLSoup(engine)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)
            
        return num, desc
Example #18
0
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict

        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info("using the connect string {0!s}".format(connect_string))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        session = sessionmaker(bind=engine)()
        db = SQLSoup(engine)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)

        return num, desc
Example #19
0
def main(config_path):
    cfg = ConfigParser()
    cfg.read(config_path)

    # Start Twisted logging to console.
    log.startLogging(stderr)

    # Read database configuration options.
    db_url = cfg.get('database', 'url')

    # Read website configuration options.
    http_debug = cfg.getboolean('http', 'debug', fallback=False)
    http_host = cfg.get('http', 'host', fallback='localhost')
    http_port = cfg.getint('http', 'port', fallback=5000)
    http_pool = cfg.getint('http', 'pool_size', fallback=4)

    # Default to much saner database query defaults and always
    # commit and/or flush statements explicitly.
    # factory = sessionmaker(autocommit=False, autoflush=False)

    # Prepare database connection with table reflection.
    engine = create_engine(db_url)
    session = scoped_session(sessionmaker(autocommit=False, autoflush=False))
    db = SQLSoup(engine, session=session)

    # Extract manager options, sans the pool_size we handle here.
    # pool_size = int(manager_opts.pop('pool_size', 2))
    pool_size = 2

    # Set the correct thread pool size for the manager.
    reactor.suggestThreadPoolSize(pool_size)

    # Prepare the website that will get exposed to the users.
    site = make_site(db, debug=http_debug)

    # Prepare WSGI site with a separate thread pool.
    pool = ThreadPool(http_pool, http_pool, 'http')
    site = Site(WSGIResource(reactor, pool, site))
    pool.start()

    # Bind the website to it's address.
    reactor.listenTCP(http_port, site, interface=http_host)

    # Run the Twisted reactor until the user terminates us.
    reactor.run()

    # Kill the HTTP ThreadPool.
    pool.stop()
Example #20
0
    def loadConfig(self, config):
        """
        Load the config from conf.
        
        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        usermap = config.get('Map', {})
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        
        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)
        log.info("using the connect string %s" % self.connect_string)
        self.engine = create_engine(self.connect_string,
                                    encoding=self.encoding,
                                    convert_unicode=False)
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)
        
        return self
def connect_db(config):
    """
    :param ConfigParser config
    """

    factory = sessionmaker(autocommit=False, autoflush=False)

    db_engine = config.get('database', 'engine')
    username = config.get('database', 'username')
    password = config.get('database', 'password')
    host = config.get('database', 'hostname')
    port = config.get('database', 'port')
    db_name = config.get('database', 'db_name')
    db_url = str(db_engine) + '://' + str(username) + ':' + str(
        password) + '@' + str(host) + ':' + str(port) + '/' + str(db_name)

    engine = create_engine(db_url)
    session = scoped_session(factory)
    db_meta = reflect(engine)
    db = SQLSoup(db_meta, session=session)

    return db
Example #22
0
class Log (SpotSource):
	def __init__ (self, band, ip, db, update_interval=30, ttl=60*3):
		self.interval = update_interval
		self.ttl = ttl
		self.band = band 
		self.name = "log"
		#self.db = SqlSoup('mysql://*****:*****@192.168.3.99/ukac20130226')
		self.db = SqlSoup('mysql://*****:*****@%s/%s' % (ip, db))
		#self.db = SqlSoup('mysql://*****:*****@192.168.0.104/%s' %db)
		SpotSource.__init__(self)

	def update (self):
		logger.debug('%s: updating.', self.name)

		if datetime.now() < self.last + timedelta(seconds=self.interval):
			logger.debug('%s: aborting update - before update interval', self.name)
			return None

		rp = self.db.execute('select callsign from log')
		for callsign, in rp.fetchall():
			self.add_spot(frequency=None,
					time=datetime.now(),
					call=callsign)
Example #23
0
def main(url, crawl_id):
    G = nx.DiGraph()
    soup = SQLSoup(url)

    peers_with_ip = 0
    reachable_peers = 0

    peers = dict(
        (p.id, p) for p in soup.peers.filter_by(crawl_id=crawl_id).all())
    edges = soup.edges.filter_by(crawl_id=crawl_id).all()

    for p in peers.values():
        if p.reachable: reachable_peers += 1
        if p.ip: peers_with_ip += 1
        G.add_node(
            p.id,
            color=('blue' if p.ip else 'red' if not p.reachable else 'orange'))
    for e in edges:
        G.add_edge(getattr(e, 'from'),
                   e.to,
                   directed=e.directed,
                   color=('black' if e.directed else 'red'))

    degrees = find_degrees(G)
    export_to_dot(G, peers, degrees, 'crawl-%d.dot' % crawl_id)
    UG = nx.Graph(G)

    print('vertices with ip: ', peers_with_ip)
    print('vertices with reachable ip: ', reachable_peers)
    print('vertices: ', len(G))
    print('edges: ', G.size())
    print('average degree: ', degree_avg(G.degree()))
    print('average in degree: ', degrees['in_degree_avg'])
    print('average out degree: ', degrees['out_degree_avg'])
    print('average unknown degree: ', degrees['unknown_degree_avg'])
    print('graph edges (as undirected graph): ', UG.size())
    print('graph diameter (as undirected graph): ', nx.diameter(UG))
Example #24
0
debug=1
"""
exec(_var_defaults)
from pyfusion.utils import process_cmd_line_args
exec(process_cmd_line_args())

if db_url != 'None':
    from sqlsoup import SQLSoup

    def write_to_summary(shot, valdic):
        if not isinstance(shot, (tuple, list, np.ndarray)):
            shot = [shot]
        for s in shot:
            SUMM.filter(h1db.summary_h1.shot == s).update(valdic)

    h1db = SQLSoup(db_url)
    cols = h1db.summary_h1.c.keys()
    SUMM = h1db.summary_h1
else:
    h1db = None

bads, simple, best, IPs = [], [], [], []

for i, shot in enumerate(shots):
    dev = pyfusion.getDevice(dev_name)
    try:
        dat = dev.acq.getdata(shot, diag_name)
    except:
        bads.append(shot)
        continue
Example #25
0
 def __init__(self, dsn):
     self.soup = SQLSoup(dsn)
Example #26
0
class IdResolver (UserIdResolver):

    searchFields = {"username": "******",
                    "userid": "numeric",
                    "phone": "text",
                    "mobile": "text",
                    "surname": "text",
                    "givenname": "text",
                    "email": "text",
                    "description": "text",
                    }

    updateable = True

    @classmethod
    def setup(cls, config=None, cache_dir=None):
        """
        this setup hook is triggered, when the server
        starts to serve the first request

        :param config: the privacyidea config
        :type  config: the privacyidea config dict
        """
        log.info("Setting up the SQLResolver")
    
    def __init__(self):
        self.resolverId = ""
        self.server = ""
        self.driver = ""
        self.database = ""
        self.port = 0
        self.limit = 100
        self.user = ""
        self.password = ""
        self.table = ""
        self.map = {}
        self.reverse_map = {}
        self.where = ""
        self.encoding = ""
        self.conParams = ""
        self.connect_string = ""
        self.session = None
        return

    def getSearchFields(self):
        return self.searchFields

    @classmethod
    def _append_where_filter(cls, conditions, table, where):
        """
        Append contents of WHERE statement to the list of filter conditions
        :param conditions: filter conditions
        :type conditions: list
        :return: list of filter conditions
        """
        if where:
            # this might result in errors if the
            # administrator enters nonsense
            (w_column, w_cond, w_value) = where.split()
            if w_cond.lower() == "like":
                conditions.append(getattr(table, w_column).like(w_value))
            elif w_cond == "==":
                conditions.append(getattr(table, w_column) == w_value)
            elif w_cond == ">":
                conditions.append(getattr(table, w_column) > w_value)
            elif w_cond == "<":
                conditions.append(getattr(table, w_column) < w_value)

        return conditions

    def checkPass(self, uid, password):
        """
        This function checks the password for a given uid.
        - returns true in case of success
        -         false if password does not match
        
        """
        def _check_ssha(pw_hash, password, hashfunc, length):
            pw_hash_bin = b64decode(pw_hash.split("}")[1])
            digest = pw_hash_bin[:length]
            salt = pw_hash_bin[length:]
            hr = hashfunc(password)
            hr.update(salt)
            return digest == hr.digest()
        
        def _check_sha(pw_hash, password):
            b64_db_password = pw_hash[5:]
            hr = hashlib.sha1(password).digest()
            b64_password = b64encode(hr)
            return b64_password == b64_db_password
        
        def _otrs_sha256(pw_hash, password):
            hr = hashlib.sha256(password)
            digest = binascii.hexlify(hr.digest())
            return pw_hash == digest
       
        res = False
        userinfo = self.getUserInfo(uid)
        
        database_pw = userinfo.get("password", "XXXXXXX")
        if database_pw[:2] == "$P":
            # We have a phpass (wordpress) password
            PH = PasswordHash()
            res = PH.check_password(password, userinfo.get("password"))
        # check salted hashed passwords
        elif database_pw[:6].upper() == "{SSHA}":
            res = _check_ssha(database_pw, password, hashlib.sha1, 20)
        elif database_pw[:9].upper() == "{SSHA256}":
            res = _check_ssha(database_pw, password, hashlib.sha256, 32)
        elif database_pw[:9].upper() == "{SSHA512}":
            res = _check_ssha(database_pw, password, hashlib.sha512, 64)
        # check for hashed password.
        elif userinfo.get("password", "XXXXX")[:5].upper() == "{SHA}":
            res = _check_sha(database_pw, password)
        elif len(userinfo.get("password")) == 64:
            # OTRS sha256 password
            res = _otrs_sha256(database_pw, password)
        
        return res
    
    def getUserInfo(self, userId):
        """
        This function returns all user info for a given userid/object.
        
        :param userId: The userid of the object
        :type userId: string
        :return: A dictionary with the keys defined in self.map
        :rtype: dict
        """
        userinfo = {}
        
        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(userId))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)
                                                      
            for r in result:
                if len(userinfo.keys()) > 0:  # pragma: no cover
                    raise Exception("More than one user with userid %s found!"
                                    % userId)
                userinfo = self._get_user_from_mapped_object(r)
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: %r" % exx)
        
        return userinfo
    
    def getUsername(self, userId):
        """
        Returns the username/loginname for a given userid
        :param userid: The userid in this resolver
        :type userid: string
        :return: username
        :rtype: string
        """
        info = self.getUserInfo(userId)
        return info.get('username', "")
   
    def getUserId(self, LoginName):
        """
        resolve the loginname to the userid.
        
        :param LoginName: The login name from the credentials
        :type LoginName: string
        :return: UserId as found for the LoginName
        """
        userid = ""
        
        try:
            conditions = []
            column = self.map.get("username")
            conditions.append(getattr(self.TABLE, column).like(LoginName))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)
                                                      
            for r in result:
                if userid != "":    # pragma: no cover
                    raise Exception("More than one user with loginname"
                                    " %s found!" % LoginName)
                user = self._get_user_from_mapped_object(r)
                userid = user["id"]
        except Exception as exx:    # pragma: no cover
            log.error("Could not get the userinformation: %r" % exx)
        
        return userid
    
    def _get_user_from_mapped_object(self, ro):
        """
        :param ro: row
        :type ro: Mapped Object
        :return: User
        :rtype: dict
        """
        r = ro.__dict__
        user = {}
        try:
            if self.map.get("userid") in r:
                user["id"] = r[self.map.get("userid")]
        except UnicodeEncodeError:  # pragma: no cover
            log.error("Failed to convert user: %r" % r)
            log.error(traceback.format_exc())
        
        for key in ["username",
                    "surname",
                    "givenname",
                    "email",
                    "mobile",
                    "description",
                    "phone",
                    "password"]:
            try:
                raw_value = r.get(self.map.get(key))
                if raw_value:
                    if type(raw_value) == str:
                        val = raw_value.decode(self.encoding)
                    else:
                        val = raw_value
                    user[key] = val

            except UnicodeDecodeError:  # pragma: no cover
                user[key] = "decoding_error"
                log.error("Failed to convert user: %r" % r)
                log.error(traceback.format_exc())
        
        return user

    def getUserList(self, searchDict=None):
        """
        :param searchDict: A dictionary with search parameters
        :type searchDict: dict
        :return: list of users, where each user is a dictionary
        """
        users = []
        conditions = []
        if searchDict is None:
            searchDict = {}
        for key in searchDict.keys():
            column = self.map.get(key)
            value = searchDict.get(key)
            value = value.replace("*", "%")
            conditions.append(getattr(self.TABLE, column).like(value))

        conditions = self._append_where_filter(conditions, self.TABLE,
                                               self.where)
        filter_condition = and_(*conditions)

        result = self.session.query(self.TABLE).\
            filter(filter_condition).\
            limit(self.limit)
                                                      
        for r in result:
            user = self._get_user_from_mapped_object(r)
            if "id" in user:
                users.append(user)

        return users
    
    def getResolverId(self):
        """
        Returns the resolver Id
        This should be an Identifier of the resolver, preferable the type
        and the name of the resolver.
        """
        return "sql." + self.resolverId

    @classmethod
    def getResolverClassType(cls):
        return 'sqlresolver'

    @classmethod
    def getResolverType(cls):
        return IdResolver.getResolverClassType()
    
    def loadConfig(self, config):
        """
        Load the config from conf.
        
        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        usermap = config.get('Map', {})
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        
        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)
        log.info("using the connect string %s" % self.connect_string)
        self.engine = create_engine(self.connect_string,
                                    encoding=self.encoding,
                                    convert_unicode=False)
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)
        
        return self

    @classmethod
    def getResolverClassDescriptor(cls):
        descriptor = {}
        typ = cls.getResolverType()
        descriptor['clazz'] = "useridresolver.SQLIdResolver.IdResolver"
        descriptor['config'] = {'Server': 'string',
                                'Driver': 'string',
                                'Database': 'string',
                                'User': '******',
                                'Password': '******',
                                'Port': 'int',
                                'Limit': 'int',
                                'Table': 'string',
                                'Map': 'string',
                                'Where': 'string',
                                'Editable': 'int',
                                'Encoding': 'string',
                                'conParams': 'string'}
        return {typ: descriptor}

    def getResolverDescriptor(self):
        return IdResolver.getResolverClassDescriptor()

    @classmethod
    def _create_connect_string(self, param):
        """
        create the connectstring
        
        Port, Password, conParams, Driver, User,
        Server, Database
        """
        port = ""
        password = ""
        conParams = ""
        if param.get("Port"):
            port = ":%s" % param.get("Port")
        if param.get("Password"):
            password = "******" % param.get("Password")
        if param.get("conParams"):
            conParams = "?%s" % param.get("conParams")
        connect_string = "%s://%s%s%s%s%s/%s%s" % (param.get("Driver", ""),
                                                   param.get("User", ""),
                                                   password,
                                                   "@" if (param.get("User")
                                                           or
                                                           password) else "",
                                                   param.get("Server", ""),
                                                   port,
                                                   param.get("Database", ""),
                                                   conParams)
        # SQLAlchemy does not like a unicode connect string!
        if param.get("Driver").lower() == "sqlite":
            connect_string = str(connect_string)
        log.debug("SQL connectstring: %r" % connect_string)
        return connect_string
            
    @classmethod
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.
              
        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict
        
        :return: Tuple of success and a description
        :rtype: (bool, string)
        
        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams
            
        """
        num = -1
        desc = None
        
        connect_string = cls._create_connect_string(param)
        log.info("using the connect string %s" % connect_string)
        engine = create_engine(connect_string)
        # create a configured "Session" class
        session = sessionmaker(bind=engine)()
        db = SQLSoup(engine)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found %i users." % num
        except Exception as exx:
            desc = "failed to retrieve users: %s" % exx
            
        return num, desc

    def add_user(self, attributes=None):
        """
        Add a new user to the SQL database.

        attributes are these
        "username", "surname", "givenname", "email",
        "mobile", "phone", "password"

        :param attributes: Attributes according to the attribute mapping
        :return: The new UID of the user. The UserIdResolver needs to
        determine the way how to create the UID.
        """
        attributes = attributes or {}
        kwargs = self._attributes_to_db_columns(attributes)
        log.debug("Insert new user with attributes %s" % kwargs)
        r = self.TABLE.insert(**kwargs)
        self.db.commit()
        # Return the UID of the new object
        return getattr(r, self.map.get("userid"))

    def _attributes_to_db_columns(self, attributes):
        """
        takes the attributes and maps them to the DB columns
        :param attributes:
        :return: dict with column name as keys and values
        """
        columns = {}
        for fieldname in attributes.keys():
            if self.map.get(fieldname):
                if fieldname == "password":
                    password = attributes.get(fieldname)
                    # Create a {SSHA256} password
                    salt = geturandom(16)
                    hr = hashlib.sha256(password)
                    hr.update(salt)
                    hash_bin = hr.digest()
                    hash_b64 = b64encode(hash_bin + salt)
                    columns[self.map.get(fieldname)] = "{SSHA256}" + hash_b64
                else:
                    columns[self.map.get(fieldname)] = attributes.get(fieldname)
        return columns

    def delete_user(self, uid):
        """
        Delete a user from the SQL database.

        The user is referenced by the user id.
        :param uid: The uid of the user object, that should be deleted.
        :type uid: basestring
        :return: Returns True in case of success
        :rtype: bool
        """
        res = True
        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(uid))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            user_obj = self.session.query(self.TABLE).filter(
                filter_condition).first()
            self.session.delete(user_obj)
            self.session.commit()
        except Exception as exx:
            log.error("Error deleting user: %s" % exx)
            res = False
        return res

    def update_user(self, uid, attributes=None):
        """
        Update an existing user.
        This function is also used to update the password. Since the
        attribute mapping know, which field contains the password,
        this function can also take care for password changing.

        Attributes that are not contained in the dict attributes are not
        modified.

        :param uid: The uid of the user object in the resolver.
        :type uid: basestring
        :param attributes: Attributes to be updated.
        :type attributes: dict
        :return: True in case of success
        """
        attributes = attributes or {}
        params = self._attributes_to_db_columns(attributes)
        kwargs = {self.map.get("userid"): uid}
        r = self.TABLE.filter_by(**kwargs).update(params)
        self.db.commit()
        return r
Example #27
0
class IdResolver(UserIdResolver):

    searchFields = {
        "username": "******",
        "userid": "numeric",
        "phone": "text",
        "mobile": "text",
        "surname": "text",
        "givenname": "text",
        "email": "text",
        "description": "text",
    }

    # If the resolver could be configured editable
    updateable = True

    @staticmethod
    def setup(config=None, cache_dir=None):
        """
        this setup hook is triggered, when the server
        starts to serve the first request

        :param config: the privacyidea config
        :type  config: the privacyidea config dict
        """
        log.info("Setting up the SQLResolver")

    def __init__(self):
        self.resolverId = ""
        self.server = ""
        self.driver = ""
        self.database = ""
        self.port = 0
        self.limit = 100
        self.user = ""
        self.password = ""
        self.table = ""
        self.map = {}
        self.reverse_map = {}
        self.where = ""
        self.encoding = ""
        self.conParams = ""
        self.connect_string = ""
        self.session = None
        self.pool_size = 10
        self.pool_timeout = 120
        self.engine = None
        self._editable = False
        self.password_hash_type = None
        return

    def getSearchFields(self):
        return self.searchFields

    @staticmethod
    def _append_where_filter(conditions, table, where):
        """
        Append contents of WHERE statement to the list of filter conditions
        :param conditions: filter conditions
        :type conditions: list
        :return: list of filter conditions
        """
        if where:
            parts = re.split(' and ', where, flags=re.IGNORECASE)
            for part in parts:
                # this might result in errors if the
                # administrator enters nonsense
                (w_column, w_cond, w_value) = part.split()
                if w_cond.lower() == "like":
                    conditions.append(getattr(table, w_column).like(w_value))
                elif w_cond == "==":
                    conditions.append(getattr(table, w_column) == w_value)
                elif w_cond == ">":
                    conditions.append(getattr(table, w_column) > w_value)
                elif w_cond == "<":
                    conditions.append(getattr(table, w_column) < w_value)

        return conditions

    def checkPass(self, uid, password):
        """
        This function checks the password for a given uid.

        :param uid: uid of the user for which the password should be checked
        :type uid: str
        :param password: the password to check
        :type password: str
        :return: True if password matches the saved password hash, False otherwise
        :rtype: bool
        """

        res = False
        userinfo = self.getUserInfo(uid)

        database_pw = userinfo.get("password", "XXXXXXX")

        # remove owncloud hash format identifier (currently only version 1)
        database_pw = re.sub(r'^1\|', '', database_pw)

        # translate lower case hash identifier to uppercase
        database_pw = re.sub(
            r'^{([a-z0-9]+)}',
            lambda match: '{{{}}}'.format(match.group(1).upper()), database_pw)

        try:
            res = pw_ctx.verify(password, database_pw)
        except ValueError as _e:
            # if the hash could not be identified / verified, just return False
            pass

        return res

    def getUserInfo(self, userId):
        """
        This function returns all user info for a given userid/object.

        :param userId: The userid of the object
        :type userId: string
        :return: A dictionary with the keys defined in self.map
        :rtype: dict
        """
        userinfo = {}

        try:
            conditions = []
            conditions.append(self._get_userid_filter(userId))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userinfo:  # pragma: no cover
                    raise Exception(
                        "More than one user with userid {0!s} found!".format(
                            userId))
                userinfo = self._get_user_from_mapped_object(r)
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userinfo

    def _get_userid_filter(self, userId):
        column = getattr(self.TABLE, self.map.get("userid"))
        if isinstance(column.type, Integer):
            # since our user ID is usually a string we need to cast
            return column == int(userId)
        else:
            # otherwise we cast the column to string (in case of postgres UUIDs)
            return cast(column, String).like(userId)

    def getUsername(self, userId):
        """
        Returns the username/loginname for a given userid
        :param userid: The userid in this resolver
        :type userid: string
        :return: username
        :rtype: string
        """
        info = self.getUserInfo(userId)
        return info.get('username', "")

    def getUserId(self, LoginName):
        """
        resolve the loginname to the userid.

        :param LoginName: The login name from the credentials
        :type LoginName: string
        :return: UserId as found for the LoginName
        :rtype: str
        """
        userid = ""

        try:
            conditions = []
            column = self.map.get("username")
            conditions.append(getattr(self.TABLE, column).like(LoginName))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userid != "":  # pragma: no cover
                    raise Exception("More than one user with loginname"
                                    " %s found!" % LoginName)
                user = self._get_user_from_mapped_object(r)
                userid = convert_column_to_unicode(user["id"])
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userid

    def _get_user_from_mapped_object(self, ro):
        """
        :param ro: row
        :type ro: Mapped Object
        :return: User
        :rtype: dict
        """
        r = ro.__dict__
        user = {}
        try:
            if self.map.get("userid") in r:
                user["id"] = r[self.map.get("userid")]
        except UnicodeEncodeError:  # pragma: no cover
            log.error("Failed to convert user: {0!r}".format(r))
            log.debug("{0!s}".format(traceback.format_exc()))

        for key in self.map.keys():
            try:
                raw_value = r.get(self.map.get(key))
                if raw_value:
                    if isinstance(raw_value, bytes):
                        val = raw_value.decode(self.encoding)
                    else:
                        val = raw_value
                    user[key] = val

            except UnicodeDecodeError:  # pragma: no cover
                user[key] = "decoding_error"
                log.error("Failed to convert user: {0!r}".format(r))
                log.debug("{0!s}".format(traceback.format_exc()))

        return user

    def getUserList(self, searchDict=None):
        """
        :param searchDict: A dictionary with search parameters
        :type searchDict: dict
        :return: list of users, where each user is a dictionary
        """
        users = []
        conditions = []
        if searchDict is None:
            searchDict = {}
        for key in searchDict.keys():
            column = self.map.get(key)
            value = searchDict.get(key)
            value = value.replace("*", "%")
            conditions.append(getattr(self.TABLE, column).like(value))

        conditions = self._append_where_filter(conditions, self.TABLE,
                                               self.where)
        filter_condition = and_(*conditions)

        result = self.session.query(self.TABLE).\
            filter(filter_condition).\
            limit(self.limit)

        for r in result:
            user = self._get_user_from_mapped_object(r)
            if "id" in user:
                users.append(user)

        return users

    def getResolverId(self):
        """
        Returns the resolver Id
        This should be an Identifier of the resolver, preferable the type
        and the name of the resolver.

        :return: identifier of the resolver
        :rtype: str
        """
        # Take the following parts, join them with the NULL byte and return
        # the hexlified SHA-1 digest
        id_parts = (self.connect_string, str(self.pool_size),
                    str(self.pool_recycle), str(self.pool_timeout))
        id_str = "\x00".join(id_parts)
        resolver_id = binascii.hexlify(
            hashlib.sha1(id_str.encode('utf8')).digest())
        return "sql." + resolver_id.decode('utf8')

    @staticmethod
    def getResolverClassType():
        return 'sqlresolver'

    @staticmethod
    def getResolverType():
        return IdResolver.getResolverClassType()

    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        self.password_hash_type = config.get("Password_Hash_Type", "SSHA256")
        usermap = config.get('Map', {})
        self.map = yaml.safe_load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)
        # recycle SQL connections after 2 hours by default
        # (necessary for MySQL servers, which terminate idle connections after some hours)
        self.pool_recycle = int(config.get('poolRecycle') or 7200)

        # create the connectstring like
        params = {
            'Port': self.port,
            'Password': self.password,
            'conParams': self.conParams,
            'Driver': self.driver,
            'User': self.user,
            'Server': self.server,
            'Database': self.database
        }
        self.connect_string = self._create_connect_string(params)

        # get an engine from the engine registry, using self.getResolverId() as the key,
        # which involves the connect string and the pool settings.
        self.engine = get_engine(self.getResolverId(), self._create_engine)
        # We use ``scoped_session`` to be sure that the SQLSoup object
        # also uses ``self.session``.
        Session = scoped_session(sessionmaker(bind=self.engine))
        # Session should be closed on teardown
        self.session = Session()
        register_finalizer(self.session.close)
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine, session=Session)
        self.db.session._model_changes = {}
        self.TABLE = self.db.entity(self.table)

        return self

    def _create_engine(self):
        log.info(u"using the connect string "
                 u"{0!s}".format(censor_connect_string(self.connect_string)))
        try:
            log.debug(
                "using pool_size={0!s}, pool_timeout={1!s}, pool_recycle={2!s}"
                .format(self.pool_size, self.pool_timeout, self.pool_recycle))
            engine = create_engine(self.connect_string,
                                   encoding=self.encoding,
                                   convert_unicode=False,
                                   pool_size=self.pool_size,
                                   pool_recycle=self.pool_recycle,
                                   pool_timeout=self.pool_timeout)
        except TypeError:
            # The DB Engine/Poolclass might not support the pool_size.
            log.debug("connecting without pool_size.")
            engine = create_engine(self.connect_string,
                                   encoding=self.encoding,
                                   convert_unicode=False)
        return engine

    @classmethod
    def getResolverClassDescriptor(cls):
        descriptor = {}
        typ = cls.getResolverType()
        descriptor['clazz'] = "useridresolver.SQLIdResolver.IdResolver"
        descriptor['config'] = {
            'Server': 'string',
            'Driver': 'string',
            'Database': 'string',
            'User': '******',
            'Password': '******',
            'Password_Hash_Type': 'string',
            'Port': 'int',
            'Limit': 'int',
            'Table': 'string',
            'Map': 'string',
            'Where': 'string',
            'Editable': 'int',
            'poolTimeout': 'int',
            'poolSize': 'int',
            'poolRecycle': 'int',
            'Encoding': 'string',
            'conParams': 'string'
        }
        return {typ: descriptor}

    @staticmethod
    def getResolverDescriptor():
        return IdResolver.getResolverClassDescriptor()

    @staticmethod
    def _create_connect_string(param):
        """
        create the connectstring

        Port, Password, conParams, Driver, User,
        Server, Database
        """
        port = ""
        password = ""
        conParams = ""
        if param.get("Port"):
            port = u":{0!s}".format(param.get("Port"))
        if param.get("Password"):
            password = u":{0!s}".format(param.get("Password"))
        if param.get("conParams"):
            conParams = u"?{0!s}".format(param.get("conParams"))
        connect_string = u"{0!s}://{1!s}{2!s}{3!s}{4!s}{5!s}/{6!s}{7!s}".format(
            param.get("Driver", ""), param.get("User", ""), password,
            "@" if (param.get("User") or password) else "",
            param.get("Server", ""), port, param.get("Database",
                                                     ""), conParams)
        # SQLAlchemy does not like a unicode connect string!
        #        if param.get("Driver").lower() == "sqlite":
        #            connect_string = str(connect_string)
        return connect_string

    @classmethod
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict
        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info(u"using the connect string {0!s}".format(
            censor_connect_string(connect_string)))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        Session = scoped_session(sessionmaker(bind=engine))
        session = Session()
        db = SQLSoup(engine, session=Session)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)
        finally:
            # We do not want any leftover DB connection, so we first need to close
            # the session such that the DB connection gets returned to the pool (it
            # is still open at that point!) and then dispose the engine such that the
            # checked-in connection gets closed.
            session.close()
            engine.dispose()

        return num, desc

    def add_user(self, attributes=None):
        """
        Add a new user to the SQL database.

        attributes are these
        "username", "surname", "givenname", "email",
        "mobile", "phone", "password"

        :param attributes: Attributes according to the attribute mapping
        :return: The new UID of the user. The UserIdResolver needs to
        determine the way how to create the UID.
        """
        attributes = attributes or {}
        kwargs = self.prepare_attributes_for_db(attributes)
        log.debug("Insert new user with attributes {0!s}".format(kwargs))
        r = self.TABLE.insert(**kwargs)
        self.db.commit()
        # Return the UID of the new object
        return getattr(r, self.map.get("userid"))

    def prepare_attributes_for_db(self, attributes):
        """
        Given a dictionary of attributes, return a dictionary
        mapping columns to values.
        If the attributes contain a password, hash the password according to the
        configured password hash type.

        :param attributes: attributes dictionary
        :return: dictionary with column name as keys
        """
        attributes = attributes.copy()
        if "password" in attributes:
            attributes["password"] = hash_password(attributes["password"],
                                                   self.password_hash_type)
        columns = {}
        for fieldname in attributes:
            if fieldname in self.map:
                columns[self.map[fieldname]] = attributes[fieldname]
        return columns

    def delete_user(self, uid):
        """
        Delete a user from the SQL database.

        The user is referenced by the user id.
        :param uid: The uid of the user object, that should be deleted.
        :type uid: basestring
        :return: Returns True in case of success
        :rtype: bool
        """
        res = True
        try:
            conditions = []
            conditions.append(self._get_userid_filter(uid))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            user_obj = self.session.query(
                self.TABLE).filter(filter_condition).first()
            self.session.delete(user_obj)
            self.session.commit()
        except Exception as exx:
            log.error("Error deleting user: {0!s}".format(exx))
            res = False
        return res

    def update_user(self, uid, attributes=None):
        """
        Update an existing user.
        This function is also used to update the password. Since the
        attribute mapping know, which field contains the password,
        this function can also take care for password changing.

        Attributes that are not contained in the dict attributes are not
        modified.

        :param uid: The uid of the user object in the resolver.
        :type uid: basestring
        :param attributes: Attributes to be updated.
        :type attributes: dict
        :return: True in case of success
        """
        attributes = attributes or {}
        params = self.prepare_attributes_for_db(attributes)
        kwargs = {self.map.get("userid"): uid}
        r = self.TABLE.filter_by(**kwargs).update(params)
        self.db.commit()
        return r

    @property
    def editable(self):
        """
        Return true, if the instance of the resolver is configured editable
        :return:
        """
        # Depending on the database this might look different
        # Usually this is "1"
        return is_true(self._editable)
Example #28
0
class IdResolver(UserIdResolver):

    searchFields = {
        "username": "******",
        "userid": "numeric",
        "phone": "text",
        "mobile": "text",
        "surname": "text",
        "givenname": "text",
        "email": "text",
        "description": "text",
    }

    # If the resolver could be configured editable
    updateable = True

    @staticmethod
    def setup(config=None, cache_dir=None):
        """
        this setup hook is triggered, when the server
        starts to serve the first request

        :param config: the privacyidea config
        :type  config: the privacyidea config dict
        """
        log.info("Setting up the SQLResolver")

    def __init__(self):
        self.resolverId = ""
        self.server = ""
        self.driver = ""
        self.database = ""
        self.port = 0
        self.limit = 100
        self.user = ""
        self.password = ""
        self.table = ""
        self.map = {}
        self.reverse_map = {}
        self.where = ""
        self.encoding = ""
        self.conParams = ""
        self.connect_string = ""
        self.session = None
        self.pool_size = 10
        self.pool_timeout = 120
        self.engine = None
        self._editable = False
        self.password_hash_type = None
        return

    def getSearchFields(self):
        return self.searchFields

    @staticmethod
    def _append_where_filter(conditions, table, where):
        """
        Append contents of WHERE statement to the list of filter conditions
        :param conditions: filter conditions
        :type conditions: list
        :return: list of filter conditions
        """
        if where:
            parts = re.split(' and ', where, flags=re.IGNORECASE)
            for part in parts:
                # this might result in errors if the
                # administrator enters nonsense
                (w_column, w_cond, w_value) = part.split()
                if w_cond.lower() == "like":
                    conditions.append(getattr(table, w_column).like(w_value))
                elif w_cond == "==":
                    conditions.append(getattr(table, w_column) == w_value)
                elif w_cond == ">":
                    conditions.append(getattr(table, w_column) > w_value)
                elif w_cond == "<":
                    conditions.append(getattr(table, w_column) < w_value)

        return conditions

    def checkPass(self, uid, password):
        """
        This function checks the password for a given uid.
        If ``password`` is a unicode object, it is converted to the database encoding first.
        - returns true in case of success
        -         false if password does not match

        """
        res = False
        userinfo = self.getUserInfo(uid)
        if isinstance(password, unicode):
            password = password.encode(self.encoding)

        database_pw = userinfo.get("password", "XXXXXXX")
        if database_pw[:2] in ["$P", "$S"]:
            # We have a phpass (wordpress) password
            PH = PasswordHash()
            res = PH.check_password(password, userinfo.get("password"))
        # check salted hashed passwords
#        elif database_pw[:2] == "$6":
#            res = sha512_crypt.verify(password, userinfo.get("password"))
        elif database_pw[:6].upper() == "{SSHA}":
            res = check_ssha(database_pw, password, hashlib.sha1, 20)
        elif database_pw[:9].upper() == "{SSHA256}":
            res = check_ssha(database_pw, password, hashlib.sha256, 32)
        elif database_pw[:9].upper() == "{SSHA512}":
            res = check_ssha(database_pw, password, hashlib.sha512, 64)
        # check for hashed password.
        elif userinfo.get("password", "XXXXX")[:5].upper() == "{SHA}":
            res = check_sha(database_pw, password)
        elif len(userinfo.get("password")) == 64:
            # OTRS sha256 password
            res = otrs_sha256(database_pw, password)
        elif database_pw[:3] in ["$1$", "$6$"]:
            res = check_crypt(database_pw, password)

        return res

    def getUserInfo(self, userId):
        """
        This function returns all user info for a given userid/object.

        :param userId: The userid of the object
        :type userId: string
        :return: A dictionary with the keys defined in self.map
        :rtype: dict
        """
        userinfo = {}

        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(userId))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userinfo.keys():  # pragma: no cover
                    raise Exception(
                        "More than one user with userid {0!s} found!".format(
                            userId))
                userinfo = self._get_user_from_mapped_object(r)
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userinfo

    def getUsername(self, userId):
        """
        Returns the username/loginname for a given userid
        :param userid: The userid in this resolver
        :type userid: string
        :return: username
        :rtype: string
        """
        info = self.getUserInfo(userId)
        return info.get('username', "")

    def getUserId(self, LoginName):
        """
        resolve the loginname to the userid.

        :param LoginName: The login name from the credentials
        :type LoginName: string
        :return: UserId as found for the LoginName
        """
        userid = ""

        try:
            conditions = []
            column = self.map.get("username")
            conditions.append(getattr(self.TABLE, column).like(LoginName))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userid != "":  # pragma: no cover
                    raise Exception("More than one user with loginname"
                                    " %s found!" % LoginName)
                user = self._get_user_from_mapped_object(r)
                userid = user["id"]
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userid

    def _get_user_from_mapped_object(self, ro):
        """
        :param ro: row
        :type ro: Mapped Object
        :return: User
        :rtype: dict
        """
        r = ro.__dict__
        user = {}
        try:
            if self.map.get("userid") in r:
                user["id"] = r[self.map.get("userid")]
        except UnicodeEncodeError:  # pragma: no cover
            log.error("Failed to convert user: {0!r}".format(r))
            log.debug("{0!s}".format(traceback.format_exc()))

        for key in self.map.keys():
            try:
                raw_value = r.get(self.map.get(key))
                if raw_value:
                    if type(raw_value) == str:
                        val = raw_value.decode(self.encoding)
                    else:
                        val = raw_value
                    user[key] = val

            except UnicodeDecodeError:  # pragma: no cover
                user[key] = "decoding_error"
                log.error("Failed to convert user: {0!r}".format(r))
                log.debug("{0!s}".format(traceback.format_exc()))

        return user

    def getUserList(self, searchDict=None):
        """
        :param searchDict: A dictionary with search parameters
        :type searchDict: dict
        :return: list of users, where each user is a dictionary
        """
        users = []
        conditions = []
        if searchDict is None:
            searchDict = {}
        for key in searchDict.keys():
            column = self.map.get(key)
            value = searchDict.get(key)
            value = value.replace("*", "%")
            conditions.append(getattr(self.TABLE, column).like(value))

        conditions = self._append_where_filter(conditions, self.TABLE,
                                               self.where)
        filter_condition = and_(*conditions)

        result = self.session.query(self.TABLE).\
            filter(filter_condition).\
            limit(self.limit)

        for r in result:
            user = self._get_user_from_mapped_object(r)
            if "id" in user:
                users.append(user)

        return users

    def getResolverId(self):
        """
        Returns the resolver Id
        This should be an Identifier of the resolver, preferable the type
        and the name of the resolver.
        """
        return "sql." + self.resolverId

    @staticmethod
    def getResolverClassType():
        return 'sqlresolver'

    @staticmethod
    def getResolverType():
        return IdResolver.getResolverClassType()

    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        self.password_hash_type = config.get("Password_Hash_Type")
        usermap = config.get('Map', {})
        self.map = yaml.safe_load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)

        # create the connectstring like
        params = {
            'Port': self.port,
            'Password': self.password,
            'conParams': self.conParams,
            'Driver': self.driver,
            'User': self.user,
            'Server': self.server,
            'Database': self.database
        }
        self.connect_string = self._create_connect_string(params)
        log.info("using the connect string {0!s}".format(self.connect_string))
        try:
            log.debug("using pool_size={0!s} and pool_timeout={1!s}".format(
                self.pool_size, self.pool_timeout))
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False,
                                        pool_size=self.pool_size,
                                        pool_timeout=self.pool_timeout)
        except TypeError:
            # The DB Engine/Poolclass might not support the pool_size.
            log.debug("connecting without pool_size.")
            self.engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False)
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine)
        self.db.session._model_changes = {}
        self.TABLE = self.db.entity(self.table)

        return self

    @classmethod
    def getResolverClassDescriptor(cls):
        descriptor = {}
        typ = cls.getResolverType()
        descriptor['clazz'] = "useridresolver.SQLIdResolver.IdResolver"
        descriptor['config'] = {
            'Server': 'string',
            'Driver': 'string',
            'Database': 'string',
            'User': '******',
            'Password': '******',
            'Password_Hash_Type': 'string',
            'Port': 'int',
            'Limit': 'int',
            'Table': 'string',
            'Map': 'string',
            'Where': 'string',
            'Editable': 'int',
            'Encoding': 'string',
            'conParams': 'string'
        }
        return {typ: descriptor}

    @staticmethod
    def getResolverDescriptor():
        return IdResolver.getResolverClassDescriptor()

    @staticmethod
    def _create_connect_string(param):
        """
        create the connectstring

        Port, Password, conParams, Driver, User,
        Server, Database
        """
        port = ""
        password = ""
        conParams = ""
        if param.get("Port"):
            port = ":{0!s}".format(param.get("Port"))
        if param.get("Password"):
            password = "******".format(param.get("Password"))
        if param.get("conParams"):
            conParams = "?{0!s}".format(param.get("conParams"))
        connect_string = "{0!s}://{1!s}{2!s}{3!s}{4!s}{5!s}/{6!s}{7!s}".format(
            param.get("Driver", ""), param.get("User", ""), password,
            "@" if (param.get("User") or password) else "",
            param.get("Server", ""), port, param.get("Database",
                                                     ""), conParams)
        # SQLAlchemy does not like a unicode connect string!
        if param.get("Driver").lower() == "sqlite":
            connect_string = str(connect_string)
        log.debug("SQL connectstring: {0!r}".format(connect_string))
        return connect_string

    @classmethod
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict

        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info("using the connect string {0!s}".format(connect_string))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        session = sessionmaker(bind=engine)()
        db = SQLSoup(engine)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)

        return num, desc

    def add_user(self, attributes=None):
        """
        Add a new user to the SQL database.

        attributes are these
        "username", "surname", "givenname", "email",
        "mobile", "phone", "password"

        :param attributes: Attributes according to the attribute mapping
        :return: The new UID of the user. The UserIdResolver needs to
        determine the way how to create the UID.
        """
        attributes = attributes or {}
        if "password" in attributes and self.password_hash_type:
            attributes["password"] = hash_password(attributes["password"],
                                                   self.password_hash_type)

        kwargs = self._attributes_to_db_columns(attributes)
        log.debug("Insert new user with attributes {0!s}".format(kwargs))
        r = self.TABLE.insert(**kwargs)
        self.db.commit()
        # Return the UID of the new object
        return getattr(r, self.map.get("userid"))

    def _attributes_to_db_columns(self, attributes):
        """
        takes the attributes and maps them to the DB columns
        :param attributes:
        :return: dict with column name as keys and values
        """
        columns = {}
        for fieldname in attributes.keys():
            if self.map.get(fieldname):
                if fieldname == "password":
                    password = attributes.get(fieldname)
                    # Create a {SSHA256} password
                    salt = geturandom(16)
                    hr = hashlib.sha256(password)
                    hr.update(salt)
                    hash_bin = hr.digest()
                    hash_b64 = b64encode(hash_bin + salt)
                    columns[self.map.get(fieldname)] = "{SSHA256}" + hash_b64
                else:
                    columns[self.map.get(fieldname)] = attributes.get(
                        fieldname)
        return columns

    def delete_user(self, uid):
        """
        Delete a user from the SQL database.

        The user is referenced by the user id.
        :param uid: The uid of the user object, that should be deleted.
        :type uid: basestring
        :return: Returns True in case of success
        :rtype: bool
        """
        res = True
        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(uid))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            user_obj = self.session.query(
                self.TABLE).filter(filter_condition).first()
            self.session.delete(user_obj)
            self.session.commit()
        except Exception as exx:
            log.error("Error deleting user: {0!s}".format(exx))
            res = False
        return res

    def update_user(self, uid, attributes=None):
        """
        Update an existing user.
        This function is also used to update the password. Since the
        attribute mapping know, which field contains the password,
        this function can also take care for password changing.

        Attributes that are not contained in the dict attributes are not
        modified.

        :param uid: The uid of the user object in the resolver.
        :type uid: basestring
        :param attributes: Attributes to be updated.
        :type attributes: dict
        :return: True in case of success
        """
        attributes = attributes or {}
        params = self._attributes_to_db_columns(attributes)
        kwargs = {self.map.get("userid"): uid}
        r = self.TABLE.filter_by(**kwargs).update(params)
        self.db.commit()
        return r

    @property
    def editable(self):
        """
        Return true, if the instance of the resolver is configured editable
        :return:
        """
        # Depending on the database this might look different
        # Usually this is "1"
        return is_true(self._editable)
Example #29
0
class IdResolver (UserIdResolver):

    searchFields = {"username": "******",
                    "userid": "numeric",
                    "phone": "text",
                    "mobile": "text",
                    "surname": "text",
                    "givenname": "text",
                    "email": "text",
                    "description": "text",
                    }

    # If the resolver could be configured editable
    updateable = True

    @staticmethod
    def setup(config=None, cache_dir=None):
        """
        this setup hook is triggered, when the server
        starts to serve the first request

        :param config: the privacyidea config
        :type  config: the privacyidea config dict
        """
        log.info("Setting up the SQLResolver")

    def __init__(self):
        self.resolverId = ""
        self.server = ""
        self.driver = ""
        self.database = ""
        self.port = 0
        self.limit = 100
        self.user = ""
        self.password = ""
        self.table = ""
        self.map = {}
        self.reverse_map = {}
        self.where = ""
        self.encoding = ""
        self.conParams = ""
        self.connect_string = ""
        self.session = None
        self.pool_size = 10
        self.pool_timeout = 120
        self.engine = None
        self._editable = False
        self.password_hash_type = None
        return

    def getSearchFields(self):
        return self.searchFields

    @staticmethod
    def _append_where_filter(conditions, table, where):
        """
        Append contents of WHERE statement to the list of filter conditions
        :param conditions: filter conditions
        :type conditions: list
        :return: list of filter conditions
        """
        if where:
            parts = re.split(' and ', where, flags=re.IGNORECASE)
            for part in parts:
                # this might result in errors if the
                # administrator enters nonsense
                (w_column, w_cond, w_value) = part.split()
                if w_cond.lower() == "like":
                    conditions.append(getattr(table, w_column).like(w_value))
                elif w_cond == "==":
                    conditions.append(getattr(table, w_column) == w_value)
                elif w_cond == ">":
                    conditions.append(getattr(table, w_column) > w_value)
                elif w_cond == "<":
                    conditions.append(getattr(table, w_column) < w_value)

        return conditions

    def checkPass(self, uid, password):
        """
        This function checks the password for a given uid.
        If ``password`` is a unicode object, it is converted to the database encoding first.
        - returns true in case of success
        -         false if password does not match

        """

        res = False
        userinfo = self.getUserInfo(uid)
        if isinstance(password, unicode):
            password = password.encode(self.encoding)

        database_pw = userinfo.get("password", "XXXXXXX")
        if database_pw[:2] in ["$P", "$S"]:
            # We have a phpass (wordpress) password
            PH = PasswordHash()
            res = PH.check_password(password, userinfo.get("password"))
        # check salted hashed passwords
#        elif database_pw[:2] == "$6":
#            res = sha512_crypt.verify(password, userinfo.get("password"))
        elif database_pw[:6].upper() == "{SSHA}":
            res = check_ssha(database_pw, password, hashlib.sha1, 20)
        elif database_pw[:9].upper() == "{SSHA256}":
            res = check_ssha(database_pw, password, hashlib.sha256, 32)
        elif database_pw[:9].upper() == "{SSHA512}":
            res = check_ssha(database_pw, password, hashlib.sha512, 64)
        # check for hashed password.
        elif userinfo.get("password", "XXXXX")[:5].upper() == "{SHA}":
            res = check_sha(database_pw, password)
        elif len(userinfo.get("password")) == 64:
            # OTRS sha256 password
            res = otrs_sha256(database_pw, password)
        elif database_pw[:3] in ["$1$", "$6$"]:
            res = check_crypt(database_pw, password)
        elif database_pw[:4] in ["$2a$", "$2b$", "$2y$"]:
            # Do bcrypt hashing
            res = bcrypt.verify(password, database_pw)
        elif database_pw[:6] in ["1|$2a$", "1|$2b$", "1|$2y$"]:
            # Do bcrypt hashing with some owncloud format
            res = bcrypt.verify(password, database_pw[2:])

        return res

    def getUserInfo(self, userId):
        """
        This function returns all user info for a given userid/object.

        :param userId: The userid of the object
        :type userId: string
        :return: A dictionary with the keys defined in self.map
        :rtype: dict
        """
        userinfo = {}

        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(userId))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userinfo:  # pragma: no cover
                    raise Exception("More than one user with userid {0!s} found!".format(userId))
                userinfo = self._get_user_from_mapped_object(r)
        except Exception as exx:  # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userinfo

    def getUsername(self, userId):
        """
        Returns the username/loginname for a given userid
        :param userid: The userid in this resolver
        :type userid: string
        :return: username
        :rtype: string
        """
        info = self.getUserInfo(userId)
        return info.get('username', "")

    def getUserId(self, LoginName):
        """
        resolve the loginname to the userid.

        :param LoginName: The login name from the credentials
        :type LoginName: string
        :return: UserId as found for the LoginName
        """
        userid = ""

        try:
            conditions = []
            column = self.map.get("username")
            conditions.append(getattr(self.TABLE, column).like(LoginName))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)

            for r in result:
                if userid != "":    # pragma: no cover
                    raise Exception("More than one user with loginname"
                                    " %s found!" % LoginName)
                user = self._get_user_from_mapped_object(r)
                userid = user["id"]
        except Exception as exx:    # pragma: no cover
            log.error("Could not get the userinformation: {0!r}".format(exx))

        return userid

    def _get_user_from_mapped_object(self, ro):
        """
        :param ro: row
        :type ro: Mapped Object
        :return: User
        :rtype: dict
        """
        r = ro.__dict__
        user = {}
        try:
            if self.map.get("userid") in r:
                user["id"] = r[self.map.get("userid")]
        except UnicodeEncodeError:  # pragma: no cover
            log.error("Failed to convert user: {0!r}".format(r))
            log.debug("{0!s}".format(traceback.format_exc()))

        for key in self.map.keys():
            try:
                raw_value = r.get(self.map.get(key))
                if raw_value:
                    if type(raw_value) == str:
                        val = raw_value.decode(self.encoding)
                    else:
                        val = raw_value
                    user[key] = val

            except UnicodeDecodeError:  # pragma: no cover
                user[key] = "decoding_error"
                log.error("Failed to convert user: {0!r}".format(r))
                log.debug("{0!s}".format(traceback.format_exc()))

        return user

    def getUserList(self, searchDict=None):
        """
        :param searchDict: A dictionary with search parameters
        :type searchDict: dict
        :return: list of users, where each user is a dictionary
        """
        users = []
        conditions = []
        if searchDict is None:
            searchDict = {}
        for key in searchDict.keys():
            column = self.map.get(key)
            value = searchDict.get(key)
            value = value.replace("*", "%")
            conditions.append(getattr(self.TABLE, column).like(value))

        conditions = self._append_where_filter(conditions, self.TABLE,
                                               self.where)
        filter_condition = and_(*conditions)

        result = self.session.query(self.TABLE).\
            filter(filter_condition).\
            limit(self.limit)

        for r in result:
            user = self._get_user_from_mapped_object(r)
            if "id" in user:
                users.append(user)

        return users

    def getResolverId(self):
        """
        Returns the resolver Id
        This should be an Identifier of the resolver, preferable the type
        and the name of the resolver.
        """
        # Take the following parts, join them with the NULL byte and return
        # the hexlified SHA-1 digest
        id_parts = (to_utf8(self.connect_string),
                    str(self.pool_size),
                    str(self.pool_recycle),
                    str(self.pool_timeout))
        resolver_id = binascii.hexlify(hashlib.sha1("\x00".join(id_parts)).digest())
        return "sql." + resolver_id

    @staticmethod
    def getResolverClassType():
        return 'sqlresolver'

    @staticmethod
    def getResolverType():
        return IdResolver.getResolverClassType()

    def loadConfig(self, config):
        """
        Load the config from conf.

        :param config: The configuration from the Config Table
        :type config: dict
        """
        self.server = config.get('Server', "")
        self.driver = config.get('Driver', "")
        self.database = config.get('Database', "")
        self.resolverId = self.database
        self.port = config.get('Port', "")
        self.limit = config.get('Limit', 100)
        self.user = config.get('User', "")
        self.password = config.get('Password', "")
        self.table = config.get('Table', "")
        self._editable = config.get("Editable", False)
        self.password_hash_type = config.get("Password_Hash_Type", "SSHA256")
        usermap = config.get('Map', {})
        self.map = yaml.safe_load(usermap)
        self.reverse_map = dict([[v, k] for k, v in self.map.items()])
        self.where = config.get('Where', "")
        self.encoding = str(config.get('Encoding') or "latin1")
        self.conParams = config.get('conParams', "")
        self.pool_size = int(config.get('poolSize') or 5)
        self.pool_timeout = int(config.get('poolTimeout') or 10)
        # recycle SQL connections after 2 hours by default
        # (necessary for MySQL servers, which terminate idle connections after some hours)
        self.pool_recycle = int(config.get('poolRecycle') or 7200)

        # create the connectstring like
        params = {'Port': self.port,
                  'Password': self.password,
                  'conParams': self.conParams,
                  'Driver': self.driver,
                  'User': self.user,
                  'Server': self.server,
                  'Database': self.database}
        self.connect_string = self._create_connect_string(params)

        # get an engine from the engine registry, using self.getResolverId() as the key,
        # which involves the connect string and the pool settings.
        self.engine = get_engine(self.getResolverId(), self._create_engine)
        # We use ``scoped_session`` to be sure that the SQLSoup object
        # also uses ``self.session``.
        Session = scoped_session(sessionmaker(bind=self.engine))
        # Session should be closed on teardown
        self.session = Session()
        register_finalizer(self.session.close)
        self.session._model_changes = {}
        self.db = SQLSoup(self.engine, session=Session)
        self.db.session._model_changes = {}
        self.TABLE = self.db.entity(self.table)

        return self

    def _create_engine(self):
        log.info(u"using the connect string {0!s}".format(censor_connect_string(self.connect_string)))
        try:
            log.debug("using pool_size={0!s}, pool_timeout={1!s}, pool_recycle={2!s}".format(
                self.pool_size, self.pool_timeout, self.pool_recycle))
            engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False,
                                        pool_size=self.pool_size,
                                        pool_recycle=self.pool_recycle,
                                        pool_timeout=self.pool_timeout)
        except TypeError:
            # The DB Engine/Poolclass might not support the pool_size.
            log.debug("connecting without pool_size.")
            engine = create_engine(self.connect_string,
                                        encoding=self.encoding,
                                        convert_unicode=False)
        return engine

    @classmethod
    def getResolverClassDescriptor(cls):
        descriptor = {}
        typ = cls.getResolverType()
        descriptor['clazz'] = "useridresolver.SQLIdResolver.IdResolver"
        descriptor['config'] = {'Server': 'string',
                                'Driver': 'string',
                                'Database': 'string',
                                'User': '******',
                                'Password': '******',
                                'Password_Hash_Type': 'string',
                                'Port': 'int',
                                'Limit': 'int',
                                'Table': 'string',
                                'Map': 'string',
                                'Where': 'string',
                                'Editable': 'int',
                                'poolTimeout': 'int',
                                'poolSize': 'int',
                                'poolRecycle': 'int',
                                'Encoding': 'string',
                                'conParams': 'string'}
        return {typ: descriptor}

    @staticmethod
    def getResolverDescriptor():
        return IdResolver.getResolverClassDescriptor()

    @staticmethod
    def _create_connect_string(param):
        """
        create the connectstring

        Port, Password, conParams, Driver, User,
        Server, Database
        """
        port = ""
        password = ""
        conParams = ""
        if param.get("Port"):
            port = u":{0!s}".format(param.get("Port"))
        if param.get("Password"):
            password = u":{0!s}".format(param.get("Password"))
        if param.get("conParams"):
            conParams = u"?{0!s}".format(param.get("conParams"))
        connect_string = u"{0!s}://{1!s}{2!s}{3!s}{4!s}{5!s}/{6!s}{7!s}".format(param.get("Driver", ""),
                                                   param.get("User", ""),
                                                   password,
                                                   "@" if (param.get("User")
                                                           or
                                                           password) else "",
                                                   param.get("Server", ""),
                                                   port,
                                                   param.get("Database", ""),
                                                   conParams)
        # SQLAlchemy does not like a unicode connect string!
        if param.get("Driver").lower() == "sqlite":
            connect_string = str(connect_string)
        return connect_string

    @classmethod
    def testconnection(cls, param):
        """
        This function lets you test the to be saved SQL connection.

        :param param: A dictionary with all necessary parameter
                        to test the connection.
        :type param: dict

        :return: Tuple of success and a description
        :rtype: (bool, string)

        Parameters are: Server, Driver, Database, User, Password, Port,
                        Limit, Table, Map
                        Where, Encoding, conParams

        """
        num = -1
        desc = None

        connect_string = cls._create_connect_string(param)
        log.info(u"using the connect string {0!s}".format(censor_connect_string(connect_string)))
        engine = create_engine(connect_string)
        # create a configured "Session" class
        Session = scoped_session(sessionmaker(bind=engine))
        session = Session()
        db = SQLSoup(engine, session=Session)
        try:
            TABLE = db.entity(param.get("Table"))
            conditions = cls._append_where_filter([], TABLE,
                                                  param.get("Where"))
            filter_condition = and_(*conditions)
            result = session.query(TABLE).filter(filter_condition).count()

            num = result
            desc = "Found {0:d} users.".format(num)
        except Exception as exx:
            desc = "failed to retrieve users: {0!s}".format(exx)
        finally:
            # We do not want any leftover DB connection, so we first need to close
            # the session such that the DB connection gets returned to the pool (it
            # is still open at that point!) and then dispose the engine such that the
            # checked-in connection gets closed.
            session.close()
            engine.dispose()

        return num, desc

    def add_user(self, attributes=None):
        """
        Add a new user to the SQL database.

        attributes are these
        "username", "surname", "givenname", "email",
        "mobile", "phone", "password"

        :param attributes: Attributes according to the attribute mapping
        :return: The new UID of the user. The UserIdResolver needs to
        determine the way how to create the UID.
        """
        attributes = attributes or {}
        kwargs = self.prepare_attributes_for_db(attributes)
        log.debug("Insert new user with attributes {0!s}".format(kwargs))
        r = self.TABLE.insert(**kwargs)
        self.db.commit()
        # Return the UID of the new object
        return getattr(r, self.map.get("userid"))

    def prepare_attributes_for_db(self, attributes):
        """
        Given a dictionary of attributes, return a dictionary
        mapping columns to values.
        If the attributes contain a password, hash the password according to the
        configured password hash type.

        :param attributes: attributes dictionary
        :return: dictionary with column name as keys
        """
        attributes = attributes.copy()
        if "password" in attributes:
            attributes["password"] = hash_password(attributes["password"],
                                                   self.password_hash_type)
        columns = {}
        for fieldname in attributes:
            if fieldname in self.map:
                columns[self.map[fieldname]] = attributes[fieldname]
        return columns

    def delete_user(self, uid):
        """
        Delete a user from the SQL database.

        The user is referenced by the user id.
        :param uid: The uid of the user object, that should be deleted.
        :type uid: basestring
        :return: Returns True in case of success
        :rtype: bool
        """
        res = True
        try:
            conditions = []
            column = self.map.get("userid")
            conditions.append(getattr(self.TABLE, column).like(uid))
            conditions = self._append_where_filter(conditions, self.TABLE,
                                                   self.where)
            filter_condition = and_(*conditions)
            user_obj = self.session.query(self.TABLE).filter(
                filter_condition).first()
            self.session.delete(user_obj)
            self.session.commit()
        except Exception as exx:
            log.error("Error deleting user: {0!s}".format(exx))
            res = False
        return res

    def update_user(self, uid, attributes=None):
        """
        Update an existing user.
        This function is also used to update the password. Since the
        attribute mapping know, which field contains the password,
        this function can also take care for password changing.

        Attributes that are not contained in the dict attributes are not
        modified.

        :param uid: The uid of the user object in the resolver.
        :type uid: basestring
        :param attributes: Attributes to be updated.
        :type attributes: dict
        :return: True in case of success
        """
        attributes = attributes or {}
        params = self.prepare_attributes_for_db(attributes)
        kwargs = {self.map.get("userid"): uid}
        r = self.TABLE.filter_by(**kwargs).update(params)
        self.db.commit()
        return r

    @property
    def editable(self):
        """
        Return true, if the instance of the resolver is configured editable
        :return:
        """
        # Depending on the database this might look different
        # Usually this is "1"
        return is_true(self._editable)
Example #30
0

@site.after_request
def insert_lang_cookie(response):
    """
    Make user locale selection persistent using a cookie.
    """

    if 'lang' in request.args:
        response.set_cookie('lang', request.args['lang'])

    return response


# Use SQLSoup for database access.
db = SQLSoup(site.config['SQLSOUP_DATABASE_URI'])

# Specify primary keys for SQLSoup to allow us to work with views.
map_view(db, 'my_subscriptions', ['id'])
map_view(db, 'my_channels', ['id'])
map_view(db, 'my_campaigns', ['id'])
map_view(db, 'recipients', ['user', 'channel'])

# Specify automatic row relations.
db.campaign.relate('Channel', db.channel)

db.my_campaigns.relate('Channel', db.channel,
                       primaryjoin=(db.channel.c.id == db.my_campaigns.c.channel),
                       foreign_keys=[db.my_campaigns.c.channel])

db.channel.relate('Template', db.template)
Example #31
0
class IdResolver (UserIdResolver):

    searchFields = {
          "username": "******",
          "userid": "numeric",
          "phone": "text",
          "mobile": "text",
          "surname": "text",
          "givenname": "text",
          "email": "text"
    }


    @classmethod
    def setup(cls, config=None, cache_dir=None):
        '''
        this setup hook is triggered, when the server 
        starts to serve the first request

        :param config: the privacyidea config
        :type  config: the privacyidea config dict
        '''
        log.info("Setting up the SQLResolver")
        return    
    
    def __init__(self):
        self.resolverId = ""
        self.server = ""
        self.driver = ""
        self.database = ""
        self.port = 0
        self.limit = 100
        self.user = ""
        self.password = ""
        self.table = ""
        self.map = {}
        self.reverse_map = {}
        self.where = ""
        self.encoding = ""
        self.conParams = ""      
        self.connect_string = ""
        self.session = None
        return

    def getSearchFields(self):
        return self.searchFields


    def checkPass(self, uid, password):
        """
        This function checks the password for a given uid.
        - returns true in case of success
        -         false if password does not match
        
        """
        def _check_ssha(pw_hash, password, hashfunc, length):
            pw_hash_bin = b64decode(pw_hash.split("}")[1])
            digest = pw_hash_bin[:length]
            salt = pw_hash_bin[length:]
            hr = hashfunc(password)
            hr.update(salt)
            return digest == hr.digest()
        
        def _check_sha(pw_hash, password):
            pw_hash_bin = b64decode(pw_hash[6:])
            digest = pw_hash_bin[:20]
            hr = hashlib.sha1(password)
            return digest == hr.digest()
        
        def _otrs_sha256(pw_hash, password):
            hr = hashlib.sha256(password)
            digest = binascii.hexlify(hr.digest())
            return pw_hash == digest

        
        res = False
        userinfo = self.getUserInfo(uid)
        
        database_pw = userinfo.get("password", "XXXXXXX")
        if database_pw[:2] == "$P":
            # We have a phpass (wordpress) password
            PH = PasswordHash()
            res = PH.check_password(password, userinfo.get("password"))
        # check salted hashed passwords
        elif database_pw[:6].upper() == "{SSHA}":
            res = _check_ssha(database_pw, password, hashlib.sha1, 20)
        elif database_pw[:6].upper() == "{SSHA256}":
            res = _check_ssha(database_pw, password, hashlib.sha256, 32)
        elif database_pw[:6].upper() == "{SSHA512}":
            res = _check_ssha(database_pw, password, hashlib.sha512, 64)
        # check for hashed password.
        elif userinfo.get("password", "XXXXX")[:5].upper() == "{SHA}":
            res = _check_sha(database_pw, password)
        elif len(userinfo.get("password"))==64:
            # OTRS sha256 password
            res = _otrs_sha256(database_pw, password)
        
        return res
        
    
    def getUserInfo(self,userId):
        '''
        This function returns all user info for a given userid/object.
        
        :param userId: The userid of the object
        :type userId: string
        :return: A dictionary with the keys defined in self.map
        :rtype: dict
        '''
        userinfo = {}
        
        try:
            conditions=[]
            column = self.map.get("userid")
            conditions.append( getattr(self.TABLE, column).like(userId) )
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)
                                                      
            for r in result:
                if len(userinfo.keys())>0:
                    raise Exception("More than one user with userid %s found!" % userId)
                userinfo = self._get_user_from_mapped_object(r)
        except Exception as exx:
            log.error("Could not get the userinformation: %r" % exx)
        
        return userinfo  
    

    def getUsername(self,userId):
        '''
        returns true, if a user id exists
        '''
        info = self.getUserInfo(userId)
        return info.has_key('username')
   
    
    def getUserId(self, LoginName):
        ''' 
        resolve the loginname to the userid. 
        
        :param LoginName: The login name from the credentials
        :type LoginName: string
        :return: UserId as found for the LoginName
        '''
        userid = ""
        
        try:
            conditions=[]
            column = self.map.get("username")
            conditions.append( getattr(self.TABLE, column).like(LoginName) )
            filter_condition = and_(*conditions)
            result = self.session.query(self.TABLE).filter(filter_condition)
                                                      
            for r in result:
                if userid != "":
                    raise Exception("More than one user with loginname %s found!" % LoginName)
                user = self._get_user_from_mapped_object(r)
                userid = user["id"]  
        except Exception as exx:
            log.error("Could not get the userinformation: %r" % exx)
        
        return userid
    
    def _get_user_from_mapped_object(self, ro):
        '''
        :param r: row
        :type r: Mapped Object
        :return: User
        :rtype: dict
        '''
        r = ro.__dict__
        user = {}
        try:
            if r.has_key(self.map.get("userid")):
                user["id"] = r[self.map.get("userid")]
            if r.has_key(self.map.get("username")):
                user["username"] = r[self.map.get("username")].decode(self.encoding)
            if r.has_key(self.map.get("surname")):
                user["surname"] = r[self.map.get("surname")].decode(self.encoding)
            if r.has_key(self.map.get("givenname")):
                user["givenname"] = r[self.map.get("givenname")].decode(self.encoding)
            if r.has_key(self.map.get("email")):
                user["email"] = r[self.map.get("email")].decode(self.encoding)
            if r.has_key(self.map.get("mobile")):
                user["mobile"] = r[self.map.get("mobile")].decode(self.encoding)
            if r.has_key(self.map.get("phone")):
                user["phone"] = r[self.map.get("phone")].decode(self.encoding)
            if r.has_key(self.map.get("password")):
                user["password"] = r[self.map.get("password")]
        except:
            log.error("Failed to convert user: %r" % r)
            log.error(traceback.format_exc())
        return user


    def getUserList(self, searchDict=None):
        '''
        :param searchDict: A dictionary with search parameters
        :type searchDict: dict
        :return: list of users, where each user is a dictionary
        '''
        users = []
        conditions = []
        if searchDict == None:
            searchDict = {}
        for key in searchDict.keys():
            column = self.map.get(key)
            value = searchDict.get(key)
            value = value.replace("*", "%")
            conditions.append( getattr(self.TABLE, column).like(value) )
            
        if self.where:
            # this might result in erros if the
            # administrator enters nonsense 
            (w_column, w_cond, w_value) = self.where.split()
            if w_cond.lower() == "like":
                conditions.append( getattr(self.TABLE, w_column).like(w_value))
            elif w_cond == "==":
                conditions.append(getattr(self.TABLE, w_column) == w_value)
            elif w_cond == ">":
                conditions.append(getattr(self.TABLE, w_column) > w_value)
            elif w_cond == "<":
                conditions.append(getattr(self.TABLE, w_column) < w_value)
        filter_condition = and_(*conditions)

        result = self.session.query(self.TABLE).filter(filter_condition).limit(self.limit)
                                                      
        for r in result:
            user = self._get_user_from_mapped_object(r)
            if user.has_key("id"):
                users.append(user)
        return users
    
    def getResolverId(self):
        '''
        Returns the resolver Id
        This should be an Identifier of the resolver, preferable the type and the name of the resolver.
        '''
        return "sqlresolver." + self.resolverId

    @classmethod
    def getResolverClassType(cls):
        return 'sqlresolver'

    def getResolverType(self):
        return IdResolver.getResolverClassType()    
    
    def loadConfig(self, config, conf):
        '''
        Load the config from conf.
        
        :param config: The configuration from the Config Table
        :type config: dict
        :param conf: the instance of the configuration
        :type conf: string 
        
        The information which config entries we need to load is taken from
            manage.js: function save_sql_config
                    
        '''
        self.resolverId = conf
        self.server = self.getConfigEntry(config, 'privacyidea.sqlresolver.Server', conf)
        self.driver = self.getConfigEntry(config, 'privacyidea.sqlresolver.Driver', conf)
        self.database = self.getConfigEntry(config, 'privacyidea.sqlresolver.Database', conf)
        self.port = self.getConfigEntry(config, 'privacyidea.sqlresolver.Port', conf, required=False)
        self.limit = self.getConfigEntry(config, 'privacyidea.sqlresolver.Limit', conf, required=False, default=100)
        self.user = self.getConfigEntry(config, 'privacyidea.sqlresolver.User', conf)
        self.password = self.getConfigEntry(config, 'privacyidea.sqlresolver.Password', conf, required=False)
        self.table = self.getConfigEntry(config, 'privacyidea.sqlresolver.Table', conf)
        usermap = self.getConfigEntry(config, 'privacyidea.sqlresolver.Map', conf)
        self.map = yaml.load(usermap)
        self.reverse_map = dict([[v,k] for k,v in self.map.items()])
        self.where = self.getConfigEntry(config, 'privacyidea.sqlresolver.Where', conf, required=False)
        self.encoding = self.getConfigEntry(config, 'privacyidea.sqlresolver.Encoding', conf, required=False, default="latin1")
        self.conParams = self.getConfigEntry(config, 'privacyidea.sqlresolver.conParams', conf, required=False)      
        
        
        # create the connectstring like
        # driver://user:passwd@seerver/database?conParams
        port = ""
        password = ""
        if self.port:
            port = ":%s" % self.port
        if self.password:
            password = "******" % self.password
        self.connect_string = "%s://%s%s@%s%s/%s?%s" % (self.driver,
                                                        self.user,
                                                        password,
                                                        self.server,
                                                        port,
                                                        self.database,
                                                        self.conParams)
        log.info("using the connect string %s" % self.connect_string)
        self.engine = create_engine(self.connect_string, encoding=str(self.encoding))
        # create a configured "Session" class
        Session = sessionmaker(bind=self.engine)

        # create a Session
        self.session = Session()
        self.db = SQLSoup(self.engine)
        self.TABLE = self.db.entity(self.table)
        
        return self
    
    


    def getResolverDescriptor(self):
        descriptor = {}
        typ = self.getResolverType()
        descriptor['clazz'] = "useridresolver.SQLIdResolver.IdResolver" 
        descriptor['config'] = {'Server' : 'string',
                                'Driver' : 'string',
                                'Database' : 'string',
                                'User' : 'string',
                                'Password' : 'string',
                                'Port' : 'int',
                                'Limit' : 'int',
                                'Table' : 'string',
                                'Map' : 'string',
                                'Where' : 'string',
                                'Encoding' : 'string',
                                'conParams' : 'string'}
        return {typ : descriptor}


    def getConfigEntry(self, config, key, conf, required=True, default=None):
        ckey = key
        cval = "" 
        if conf != "" or None:
            ckey = ckey + "." + conf
            if config.has_key(ckey):
                cval = config[ckey]
        if cval == "":
            if config.has_key(key):
                cval = config[key]
        if cval == "" and required == True:
            raise Exception("missing config entry: " + key)
        if cval == "" and default:
            cval = default
        return cval

            
    @classmethod
    def testconnection(self, param):
        '''
        This function lets you test the to be saved SQL connection.
              
        :param param: A dictionary with all necessary parameter to test the connection.
        :type param: dict
        
        :return: Tuple of success and a description
        :rtype: (bool, string)  
        
        Parameters are: Server, Driver, Database, User, Password, Port, Limit, Table, Map
                        Where, Encoding, conParams
            
        '''
        
        num=-1
        desc=None
        
        port = ""
        password = ""
        conParams = ""
        if param.get("Port"):
            port = ":%s" % param.get("Port")
        if param.get("Password"):
            password = "******" % param.get("Password")
        if param.get("conParams"):
            conParams = "?%s" % param.get("conParams")
        connect_string = "%s://%s%s%s%s%s/%s%s" % (param.get("Driver"),
                                                    param.get("User"),
                                                    password,
                                                    "@" if (param.get("User") or password) else "",
                                                    param.get("Server"),
                                                    port,
                                                    param.get("Database"),
                                                    conParams)
        log.info("using the connect string %s" % connect_string)
        engine = create_engine(connect_string)
        # create a configured "Session" class
        session = sessionmaker(bind=engine)()
        db = SQLSoup(engine)
        TABLE = db.entity(param.get("Table"))
            
        try:    
            result = session.query(TABLE).count()
            num = result
            desc = "Found %i users." % num
        except Exception as exx:
            desc = "failed to retrieve users: %s" % exx
            
        return (num, desc)
Example #32
0
vars = _select.lower().split('select ')[1].split(',')
if len(vars) == 1:
    _select = _select.replace('select', 'select shot,')

# default order is by shot
if _order is '':
    if len(vars) is 1:
        _order = 'order by shot'
    else:
        _order = 'order by ' + vars[0]

url_cpts = db_url.split('sqlite:///')
if not os.path.exists(url_cpts[-1]):
    input('{fn} could not be found!!\n'.format(fn=url_cpts[-1]))

h1db = SQLSoup(db_url)
# Note - this info. is here now, but disappears if there is an error - save
tables = list(h1db._cache)
print(tables if len(tables) > 0 else ' possibly no tables in ' + db_url +
      " although this doesn't mean anything sometimes")
if len(tables) == 0 and block == 1:
    input('Continue?')

try:
    h1db.SUMM = eval('h1db.' + table)
except Exception as reason:
    print(reason.__repr__(), ' table names are ', tables)
    raise

cols = h1db.SUMM.c.keys()
if plabel is not '':
Example #33
0
 def connect(self):
     """Connect to remote join backend (DB)"""
     self.db = SQLSoup(self.connect_string)
from fastapi import FastAPI, HTTPException
from sqlsoup import SQLSoup

from api_test import db, model

app = FastAPI()

engine = db.get_db_engine()
db = SQLSoup(engine)


@app.get("/")
def read_root():
    return {"hello": "world"}


@app.get("/counts")
def read_count_ids(only_latest: bool = False):
    """ Get all counts 
    
    Field `only_latest` is optional.
    If True, will only return the lastest count per device_id"""
    counts = db.counts.all()

    if only_latest:
        return_dict = {}
        for count in counts:
            if count.device_id not in return_dict or count.timestamp > return_dict[
                    count.device_id].timestamp:
                return_dict[count.device_id] = count
        return return_dict
Example #35
0
from sqlsoup import SQLSoup

# server details
SERVER = os.environ.get("SERVER", "localhost")
USERNAME = os.environ.get("DB_USERNAME", "sa")
PASSWORD = os.environ.get("DB_PASSWORD", "reallyStrongPwd123")
DATABASE = os.environ.get("DB_NAME", "DW_AccessBI")
PORT = os.environ.get("DB_PORT", 1433)

# load data from SQL Server
# db_connection = pymssql.connect(
#     server=SERVER, user=USERNAME, password=PASSWORD, database=DATABASE, port=PORT)

conn_str = "mssql+pymssql://{user}:{password}@{server}/{database}?charset=utf8".format(
    user=USERNAME, password=PASSWORD, server=SERVER, database=DATABASE)
sqlsoup_obj = SQLSoup(conn_str)
engine = sqlsoup_obj.engine


def get_data_from_sqlserver(sql_string, connection_obj=engine):
    df = pd.read_sql(sql_string, connection_obj)
    return df


def get_categorical_values(column, table_name=None):

    if table_name is None:
        table_name = "D_" + column.upper()
    table = sqlsoup_obj.entity(table_name)
    rows = table.all()
    values = set()
Example #36
0
                                        poolclass=NullPool)
elif tipodb_source == "postgresql":
    print "MIGRAZIONE DA POSTGRESQL A "
    engine_source = create_engine('postgresql+psycopg2://' +
                                    user_source + ":" +
                                    password_source + "@" +
                                    host_source + ":" +
                                    port_source + "/" +
                                    database_source,
                                convert_unicode=True,
                                encoding='utf-8',
                                poolclass=NullPool)
else:
    print "ORIGINE MIGRAZIONE NON RICONOSCIUTO"

db_source = SQLSoup(engine_source)

if tipodb_source == "postgresql":
    db_source_main = SQLSoup(engine_source)
    db_source.schema = azienda_source
    db_source_main.schema = "promogest2"

if tipodb_source == "postgresql":
    meta_source = MetaData()
    meta_source_main = MetaData()
    meta_source_main.reflect(bind=engine_source, schema="promogest2")
    meta_source.reflect(bind=engine_source, schema=azienda_source)
else:
    meta_source = MetaData()
    meta_source.reflect(bind=engine_source)