2017-03-25 05:55:49 +00:00
# include <string.h>
# include <Poco/RegularExpression.h>
# include <Poco/Util/AbstractConfiguration.h>
2017-04-01 09:19:00 +00:00
# include <Common/Exception.h>
# include <IO/ReadHelpers.h>
# include <Interpreters/Users.h>
2017-03-25 05:55:49 +00:00
# include <common/logger_useful.h>
namespace DB
{
namespace ErrorCodes
{
2017-04-01 07:20:54 +00:00
extern const int UNKNOWN_ADDRESS_PATTERN_TYPE ;
extern const int UNKNOWN_USER ;
2017-04-08 01:32:05 +00:00
extern const int BAD_ARGUMENTS ;
2017-03-25 05:55:49 +00:00
}
2018-07-08 04:54:37 +00:00
User : : User ( const String & name_ , const String & config_elem , const Poco : : Util : : AbstractConfiguration & config )
2017-04-01 07:20:54 +00:00
: name ( name_ )
2017-03-25 05:55:49 +00:00
{
2017-04-01 07:20:54 +00:00
bool has_password = config . has ( config_elem + " .password " ) ;
bool has_password_sha256_hex = config . has ( config_elem + " .password_sha256_hex " ) ;
2019-07-28 13:12:26 +00:00
bool has_password_double_sha1_hex = config . has ( config_elem + " .password_double_sha1_hex " ) ;
2017-03-25 05:55:49 +00:00
2019-07-28 13:12:26 +00:00
if ( has_password + has_password_sha256_hex + has_password_double_sha1_hex > 1 )
throw Exception ( " More than one field of 'password', 'password_sha256_hex', 'password_double_sha1_hex' is used to specify password for user " + name + " . Must be only one of them. " ,
ErrorCodes : : BAD_ARGUMENTS ) ;
2017-03-25 05:55:49 +00:00
2019-07-28 13:12:26 +00:00
if ( ! has_password & & ! has_password_sha256_hex & & ! has_password_double_sha1_hex )
throw Exception ( " Either 'password' or 'password_sha256_hex' or 'password_double_sha1_hex' must be specified for user " + name + " . " , ErrorCodes : : BAD_ARGUMENTS ) ;
2017-03-25 05:55:49 +00:00
2017-04-01 07:20:54 +00:00
if ( has_password )
2019-10-08 13:44:44 +00:00
{
2019-10-10 21:48:36 +00:00
authentication = Authentication { Authentication : : PLAINTEXT_PASSWORD } ;
2019-10-08 13:44:44 +00:00
authentication . setPassword ( config . getString ( config_elem + " .password " ) ) ;
}
2019-10-10 21:48:36 +00:00
else if ( has_password_sha256_hex )
2017-04-01 07:20:54 +00:00
{
2019-10-10 21:48:36 +00:00
authentication = Authentication { Authentication : : SHA256_PASSWORD } ;
2019-10-08 13:44:44 +00:00
authentication . setPasswordHashHex ( config . getString ( config_elem + " .password_sha256_hex " ) ) ;
2017-04-01 07:20:54 +00:00
}
2019-10-10 21:48:36 +00:00
else if ( has_password_double_sha1_hex )
2019-07-28 13:12:26 +00:00
{
2019-10-10 21:48:36 +00:00
authentication = Authentication { Authentication : : DOUBLE_SHA1_PASSWORD } ;
2019-10-08 13:44:44 +00:00
authentication . setPasswordHashHex ( config . getString ( config_elem + " .password_double_sha1_hex " ) ) ;
2019-07-28 13:12:26 +00:00
}
2017-09-08 16:46:56 +00:00
profile = config . getString ( config_elem + " .profile " ) ;
quota = config . getString ( config_elem + " .quota " ) ;
2017-03-25 05:55:49 +00:00
2019-10-08 14:40:24 +00:00
/// Fill list of allowed hosts.
const auto config_networks = config_elem + " .networks " ;
if ( config . has ( config_networks ) )
{
Poco : : Util : : AbstractConfiguration : : Keys config_keys ;
config . keys ( config_networks , config_keys ) ;
for ( Poco : : Util : : AbstractConfiguration : : Keys : : const_iterator it = config_keys . begin ( ) ; it ! = config_keys . end ( ) ; + + it )
{
String value = config . getString ( config_networks + " . " + * it ) ;
if ( startsWith ( * it , " ip " ) )
allowed_client_hosts . addSubnet ( value ) ;
else if ( startsWith ( * it , " host_regexp " ) )
allowed_client_hosts . addHostRegexp ( value ) ;
else if ( startsWith ( * it , " host " ) )
allowed_client_hosts . addHostName ( value ) ;
else
throw Exception ( " Unknown address pattern type: " + * it , ErrorCodes : : UNKNOWN_ADDRESS_PATTERN_TYPE ) ;
}
}
2017-03-25 05:55:49 +00:00
2017-04-01 07:20:54 +00:00
/// Fill list of allowed databases.
const auto config_sub_elem = config_elem + " .allow_databases " ;
if ( config . has ( config_sub_elem ) )
{
Poco : : Util : : AbstractConfiguration : : Keys config_keys ;
config . keys ( config_sub_elem , config_keys ) ;
2017-03-25 05:55:49 +00:00
2017-04-01 07:20:54 +00:00
databases . reserve ( config_keys . size ( ) ) ;
for ( const auto & key : config_keys )
{
const auto database_name = config . getString ( config_sub_elem + " . " + key ) ;
databases . insert ( database_name ) ;
}
}
2019-03-29 20:31:06 +00:00
2019-09-14 22:56:37 +00:00
/// Fill list of allowed dictionaries.
2019-09-13 08:22:34 +00:00
const auto config_dictionary_sub_elem = config_elem + " .allow_dictionaries " ;
if ( config . has ( config_dictionary_sub_elem ) )
{
Poco : : Util : : AbstractConfiguration : : Keys config_keys ;
config . keys ( config_dictionary_sub_elem , config_keys ) ;
dictionaries . reserve ( config_keys . size ( ) ) ;
for ( const auto & key : config_keys )
{
const auto dictionary_name = config . getString ( config_dictionary_sub_elem + " . " + key ) ;
dictionaries . insert ( dictionary_name ) ;
}
}
2019-03-29 20:31:06 +00:00
/// Read properties per "database.table"
/// Only tables are expected to have properties, so that all the keys inside "database" are table names.
const auto config_databases = config_elem + " .databases " ;
if ( config . has ( config_databases ) )
{
Poco : : Util : : AbstractConfiguration : : Keys database_names ;
config . keys ( config_databases , database_names ) ;
/// Read tables within databases
for ( const auto & database : database_names )
{
const auto config_database = config_databases + " . " + database ;
Poco : : Util : : AbstractConfiguration : : Keys table_names ;
config . keys ( config_database , table_names ) ;
/// Read table properties
for ( const auto & table : table_names )
{
const auto config_filter = config_database + " . " + table + " .filter " ;
if ( config . has ( config_filter ) )
{
const auto filter_query = config . getString ( config_filter ) ;
table_props [ database ] [ table ] [ " filter " ] = filter_query ;
}
}
}
}
2017-03-25 05:55:49 +00:00
}
}