2017-09-14 19:40:11 +00:00
import * as URI from 'urijs' ;
2014-12-26 21:54:36 +00:00
angular . module ( "core-config-setup" , [ 'angularFileUpload' ] )
. directive ( 'configSetupTool' , function ( ) {
var directiveDefinitionObject = {
priority : 1 ,
templateUrl : '/static/directives/config/config-setup-tool.html' ,
replace : true ,
transclude : true ,
restrict : 'C' ,
scope : {
2015-01-23 22:19:15 +00:00
'isActive' : '=isActive' ,
'configurationSaved' : '&configurationSaved'
2014-12-26 21:54:36 +00:00
} ,
2015-01-05 18:01:32 +00:00
controller : function ( $rootScope , $scope , $element , $timeout , ApiService ) {
2016-05-23 19:08:51 +00:00
var authPassword = null ;
2015-01-15 19:36:05 +00:00
$scope . HOSTNAME _REGEX = '^[a-zA-Z-0-9\.]+(:[0-9]+)?$' ;
2015-05-03 18:50:26 +00:00
$scope . GITHOST _REGEX = '^https?://([a-zA-Z0-9]+\.?\/?)+$' ;
2015-01-15 19:36:05 +00:00
2015-01-07 21:20:51 +00:00
$scope . SERVICES = [
{ 'id' : 'redis' , 'title' : 'Redis' } ,
{ 'id' : 'registry-storage' , 'title' : 'Registry Storage' } ,
2017-04-05 18:01:55 +00:00
{ 'id' : 'time-machine' , 'title' : 'Time Machine' } ,
2017-05-24 16:57:55 +00:00
{ 'id' : 'access' , 'title' : 'Access Settings' } ,
2015-01-07 21:20:51 +00:00
{ 'id' : 'ssl' , 'title' : 'SSL certificate and key' , 'condition' : function ( config ) {
return config . PREFERRED _URL _SCHEME == 'https' ;
} } ,
{ 'id' : 'ldap' , 'title' : 'LDAP Authentication' , 'condition' : function ( config ) {
return config . AUTHENTICATION _TYPE == 'LDAP' ;
2015-06-22 22:17:37 +00:00
} , 'password' : true } ,
2015-01-07 21:20:51 +00:00
2015-06-02 22:19:22 +00:00
{ 'id' : 'jwt' , 'title' : 'JWT Authentication' , 'condition' : function ( config ) {
return config . AUTHENTICATION _TYPE == 'JWT' ;
2015-06-22 22:17:37 +00:00
} , 'password' : true } ,
2015-06-02 22:19:22 +00:00
2015-07-13 09:34:32 +00:00
{ 'id' : 'keystone' , 'title' : 'Keystone Authentication' , 'condition' : function ( config ) {
return config . AUTHENTICATION _TYPE == 'Keystone' ;
} , 'password' : true } ,
2017-12-08 22:05:59 +00:00
{ 'id' : 'apptoken-auth' , 'title' : 'App Token Authentication' , 'condition' : function ( config ) {
return config . AUTHENTICATION _TYPE == 'AppToken' ;
2017-06-09 21:12:05 +00:00
} } ,
2016-02-16 20:31:23 +00:00
{ 'id' : 'signer' , 'title' : 'ACI Signing' , 'condition' : function ( config ) {
return config . FEATURE _ACI _CONVERSION ;
} } ,
2015-01-07 21:20:51 +00:00
{ 'id' : 'mail' , 'title' : 'E-mail Support' , 'condition' : function ( config ) {
return config . FEATURE _MAILING ;
} } ,
{ 'id' : 'github-login' , 'title' : 'Github (Enterprise) Authentication' , 'condition' : function ( config ) {
return config . FEATURE _GITHUB _LOGIN ;
2015-01-08 18:26:24 +00:00
} } ,
2015-01-08 18:56:17 +00:00
{ 'id' : 'google-login' , 'title' : 'Google Authentication' , 'condition' : function ( config ) {
return config . FEATURE _GOOGLE _LOGIN ;
} } ,
2015-05-03 18:50:26 +00:00
{ 'id' : 'github-trigger' , 'title' : 'GitHub (Enterprise) Build Triggers' , 'condition' : function ( config ) {
2015-01-08 18:26:24 +00:00
return config . FEATURE _GITHUB _BUILD ;
2015-05-03 18:50:26 +00:00
} } ,
{ 'id' : 'bitbucket-trigger' , 'title' : 'BitBucket Build Triggers' , 'condition' : function ( config ) {
return config . FEATURE _BITBUCKET _BUILD ;
} } ,
{ 'id' : 'gitlab-trigger' , 'title' : 'GitLab Build Triggers' , 'condition' : function ( config ) {
return config . FEATURE _GITLAB _BUILD ;
2016-05-02 19:29:31 +00:00
} } ,
{ 'id' : 'security-scanner' , 'title' : 'Quay Security Scanner' , 'condition' : function ( config ) {
return config . FEATURE _SECURITY _SCANNER ;
2016-09-26 09:13:59 +00:00
} } ,
{ 'id' : 'bittorrent' , 'title' : 'BitTorrent downloads' , 'condition' : function ( config ) {
return config . FEATURE _BITTORRENT ;
2017-02-28 21:18:34 +00:00
} } ,
{ 'id' : 'oidc-login' , 'title' : 'OIDC Login(s)' , 'condition' : function ( config ) {
return $scope . getOIDCProviders ( config ) . length > 0 ;
} } ,
2017-07-10 10:22:29 +00:00
2017-07-10 15:35:51 +00:00
{ 'id' : 'actionlogarchiving' , 'title' : 'Action Log Rotation' , 'condition' : function ( config ) {
2017-07-10 10:22:29 +00:00
return config . FEATURE _ACTION _LOG _ROTATION ;
} } ,
2015-01-07 21:20:51 +00:00
] ;
$scope . STORAGE _CONFIG _FIELDS = {
'LocalStorage' : [
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/some/directory' , 'kind' : 'text' }
] ,
'S3Storage' : [
{ 'name' : 's3_bucket' , 'title' : 'S3 Bucket' , 'placeholder' : 'my-cool-bucket' , 'kind' : 'text' } ,
2015-11-18 22:19:33 +00:00
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/path/inside/bucket' , 'kind' : 'text' } ,
2016-08-11 21:17:36 +00:00
{ 'name' : 's3_access_key' , 'title' : 'AWS Access Key (optional if using IAM)' , 'placeholder' : 'accesskeyhere' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 's3_secret_key' , 'title' : 'AWS Secret Key (optional if using IAM)' , 'placeholder' : 'secretkeyhere' , 'kind' : 'text' , 'optional' : true } ,
2016-12-01 18:22:27 +00:00
{ 'name' : 'host' , 'title' : 'S3 Host (optional)' , 'placeholder' : 's3.amazonaws.com' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 'port' , 'title' : 'S3 Port (optional)' , 'placeholder' : '443' , 'kind' : 'text' , 'pattern' : '^[0-9]+$' , 'optional' : true }
2015-01-07 21:20:51 +00:00
] ,
2017-11-06 20:18:36 +00:00
'AzureStorage' : [
{ 'name' : 'azure_container' , 'title' : 'Azure Storage Container' , 'placeholder' : 'container' , 'kind' : 'text' } ,
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/path/inside/container' , 'kind' : 'text' } ,
{ 'name' : 'azure_account_name' , 'title' : 'Azure Account Name' , 'placeholder' : 'accountnamehere' , 'kind' : 'text' } ,
{ 'name' : 'azure_account_key' , 'title' : 'Azure Account Key' , 'placeholder' : 'accountkeyhere' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 'sas_token' , 'title' : 'Azure SAS Token' , 'placeholder' : 'sastokenhere' , 'kind' : 'text' , 'optional' : true } ,
] ,
2015-01-07 21:20:51 +00:00
'GoogleCloudStorage' : [
{ 'name' : 'access_key' , 'title' : 'Cloud Access Key' , 'placeholder' : 'accesskeyhere' , 'kind' : 'text' } ,
{ 'name' : 'secret_key' , 'title' : 'Cloud Secret Key' , 'placeholder' : 'secretkeyhere' , 'kind' : 'text' } ,
{ 'name' : 'bucket_name' , 'title' : 'GCS Bucket' , 'placeholder' : 'my-cool-bucket' , 'kind' : 'text' } ,
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/path/inside/bucket' , 'kind' : 'text' }
] ,
'RadosGWStorage' : [
{ 'name' : 'hostname' , 'title' : 'Rados Server Hostname' , 'placeholder' : 'my.rados.hostname' , 'kind' : 'text' } ,
2016-12-01 18:22:27 +00:00
{ 'name' : 'port' , 'title' : 'Custom Port (optional)' , 'placeholder' : '443' , 'kind' : 'text' , 'pattern' : '^[0-9]+$' , 'optional' : true } ,
2015-01-07 21:20:51 +00:00
{ 'name' : 'is_secure' , 'title' : 'Is Secure' , 'placeholder' : 'Require SSL' , 'kind' : 'bool' } ,
{ 'name' : 'access_key' , 'title' : 'Access Key' , 'placeholder' : 'accesskeyhere' , 'kind' : 'text' , 'help_url' : 'http://ceph.com/docs/master/radosgw/admin/' } ,
{ 'name' : 'secret_key' , 'title' : 'Secret Key' , 'placeholder' : 'secretkeyhere' , 'kind' : 'text' } ,
{ 'name' : 'bucket_name' , 'title' : 'Bucket Name' , 'placeholder' : 'my-cool-bucket' , 'kind' : 'text' } ,
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/path/inside/bucket' , 'kind' : 'text' }
2015-05-21 19:22:59 +00:00
] ,
'SwiftStorage' : [
2016-05-16 18:57:59 +00:00
{ 'name' : 'auth_version' , 'title' : 'Swift Auth Version' , 'kind' : 'option' , 'values' : [ 1 , 2 , 3 ] } ,
2015-09-14 21:49:35 +00:00
{ 'name' : 'auth_url' , 'title' : 'Swift Auth URL' , 'placeholder' : 'http://swiftdomain/auth/v1.0' , 'kind' : 'text' } ,
{ 'name' : 'swift_container' , 'title' : 'Swift Container Name' , 'placeholder' : 'mycontainer' , 'kind' : 'text' ,
'help_text' : 'The swift container for all objects. Must already exist inside Swift.' } ,
2015-05-21 19:22:59 +00:00
{ 'name' : 'storage_path' , 'title' : 'Storage Path' , 'placeholder' : '/path/inside/container' , 'kind' : 'text' } ,
2015-09-14 21:49:35 +00:00
{ 'name' : 'swift_user' , 'title' : 'Username' , 'placeholder' : 'accesskeyhere' , 'kind' : 'text' ,
'help_text' : 'Note: For Swift V1, this is "username:password" (-U on the CLI).' } ,
{ 'name' : 'swift_password' , 'title' : 'Key/Password' , 'placeholder' : 'secretkeyhere' , 'kind' : 'text' ,
'help_text' : 'Note: For Swift V1, this is the API token (-K on the CLI).' } ,
2015-05-21 19:22:59 +00:00
{ 'name' : 'ca_cert_path' , 'title' : 'CA Cert Filename' , 'placeholder' : 'conf/stack/swift.cert' , 'kind' : 'text' , 'optional' : true } ,
2015-09-14 21:49:35 +00:00
{ 'name' : 'temp_url_key' , 'title' : 'Temp URL Key (optional)' , 'placholder' : 'key-here' , 'kind' : 'text' , 'optional' : true ,
'help_url' : 'https://coreos.com/products/enterprise-registry/docs/latest/swift-temp-url.html' ,
'help_text' : 'If enabled, will allow for faster pulls directly from Swift.' } ,
2015-05-21 19:22:59 +00:00
{ 'name' : 'os_options' , 'title' : 'OS Options' , 'kind' : 'map' ,
2016-05-16 18:57:59 +00:00
'keys' : [ 'tenant_id' , 'auth_token' , 'service_type' , 'endpoint_type' , 'tenant_name' , 'object_storage_url' , 'region_name' ,
'project_id' , 'project_name' , 'project_domain_name' , 'user_domain_name' , 'user_domain_id' ] }
2018-01-10 19:46:36 +00:00
] ,
'CloudFrontedS3Storage' : [
{ 'name' : 's3_bucket' , 'title' : 'S3 Bucket' , 'placeholder' : 'my-cool-bucket' , 'kind' : 'text' } ,
{ 'name' : 'storage_path' , 'title' : 'Storage Directory' , 'placeholder' : '/path/inside/bucket' , 'kind' : 'text' } ,
{ 'name' : 's3_access_key' , 'title' : 'AWS Access Key (optional if using IAM)' , 'placeholder' : 'accesskeyhere' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 's3_secret_key' , 'title' : 'AWS Secret Key (optional if using IAM)' , 'placeholder' : 'secretkeyhere' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 'host' , 'title' : 'S3 Host (optional)' , 'placeholder' : 's3.amazonaws.com' , 'kind' : 'text' , 'optional' : true } ,
{ 'name' : 'port' , 'title' : 'S3 Port (optional)' , 'placeholder' : '443' , 'kind' : 'text' , 'pattern' : '^[0-9]+$' , 'optional' : true } ,
{ 'name' : 'cloudfront_distribution_domain' , 'title' : 'CloudFront Distribution Domain Name' , 'placeholder' : 'somesubdomain.cloudfront.net' , 'pattern' : '^([0-9a-zA-Z]+\\.)+[0-9a-zA-Z]+$' , 'kind' : 'text' } ,
{ 'name' : 'cloudfront_key_id' , 'title' : 'CloudFront Key ID' , 'placeholder' : 'APKATHISISAKEYID' , 'kind' : 'text' } ,
{ 'name' : 'cloudfront_privatekey_filename' , 'title' : 'CloudFront Private Key' , 'filesuffix' : 'cloudfront-signing-key.pem' , 'kind' : 'file' } ,
] ,
2015-01-07 21:20:51 +00:00
} ;
2017-05-24 16:57:55 +00:00
$scope . enableFeature = function ( config , feature ) {
config [ feature ] = true ;
} ;
2015-01-15 19:36:05 +00:00
$scope . validateHostname = function ( hostname ) {
if ( hostname . indexOf ( '127.0.0.1' ) == 0 || hostname . indexOf ( 'localhost' ) == 0 ) {
return 'Please specify a non-localhost hostname. "localhost" will refer to the container, not your machine.'
}
return null ;
} ;
2015-01-05 18:01:32 +00:00
$scope . config = null ;
2015-01-07 21:20:51 +00:00
$scope . mapped = {
'$hasChanges' : false
} ;
2015-12-07 20:55:55 +00:00
$scope . hasfile = { } ;
2015-01-07 21:20:51 +00:00
$scope . validating = null ;
$scope . savingConfiguration = false ;
2017-02-28 21:18:34 +00:00
$scope . removeOIDCProvider = function ( provider ) {
delete $scope . config [ provider ] ;
} ;
$scope . addOIDCProvider = function ( ) {
bootbox . prompt ( 'Enter an ID for the OIDC provider' , function ( result ) {
if ( ! result ) {
return ;
}
result = result . toUpperCase ( ) ;
if ( ! result . match ( /^[A-Z0-9]+$/ ) ) {
bootbox . alert ( 'Invalid ID for OIDC provider: must be alphanumeric' ) ;
return ;
}
if ( result == 'GITHUB' || result == 'GOOGLE' ) {
bootbox . alert ( 'Invalid ID for OIDC provider: cannot be a reserved name' ) ;
return ;
}
var key = result + '_LOGIN_CONFIG' ;
if ( $scope . config [ key ] ) {
bootbox . alert ( 'Invalid ID for OIDC provider: already exists' ) ;
return ;
}
$scope . config [ key ] = { } ;
} ) ;
} ;
$scope . getOIDCProviderId = function ( key ) {
var index = key . indexOf ( '_LOGIN_CONFIG' ) ;
if ( index <= 0 ) {
return null ;
}
2017-06-09 21:12:05 +00:00
return key . substr ( 0 , index ) . toLowerCase ( ) ;
2017-02-28 21:18:34 +00:00
} ;
$scope . getOIDCProviders = function ( config ) {
var keys = Object . keys ( config || { } ) ;
return keys . filter ( function ( key ) {
if ( key == 'GITHUB_LOGIN_CONFIG' || key == 'GOOGLE_LOGIN_CONFIG' ) {
// Has custom UI and config.
return false ;
}
return ! ! $scope . getOIDCProviderId ( key ) ;
} ) ;
} ;
2015-01-07 21:20:51 +00:00
$scope . getServices = function ( config ) {
var services = [ ] ;
if ( ! config ) { return services ; }
for ( var i = 0 ; i < $scope . SERVICES . length ; ++ i ) {
var service = $scope . SERVICES [ i ] ;
if ( ! service . condition || service . condition ( config ) ) {
services . push ( {
'service' : service ,
'status' : 'validating'
} ) ;
}
}
return services ;
} ;
$scope . validationStatus = function ( serviceInfos ) {
if ( ! serviceInfos ) { return 'validating' ; }
var hasError = false ;
for ( var i = 0 ; i < serviceInfos . length ; ++ i ) {
if ( serviceInfos [ i ] . status == 'validating' ) {
return 'validating' ;
}
if ( serviceInfos [ i ] . status == 'error' ) {
hasError = true ;
}
}
return hasError ? 'failed' : 'success' ;
} ;
2015-01-08 20:27:49 +00:00
$scope . cancelValidation = function ( ) {
$ ( '#validateAndSaveModal' ) . modal ( 'hide' ) ;
$scope . validating = null ;
$scope . savingConfiguration = false ;
} ;
2015-06-22 22:17:37 +00:00
$scope . validateService = function ( serviceInfo , opt _password ) {
2015-01-07 21:20:51 +00:00
var params = {
'service' : serviceInfo . service . id
} ;
2015-06-22 22:17:37 +00:00
var data = {
'config' : $scope . config ,
'password' : opt _password || ''
} ;
2016-05-23 19:08:51 +00:00
var errorDisplay = ApiService . errorDisplay (
'Could not validate configuration. Please report this error.' ,
function ( ) {
authPassword = null ;
} ) ;
2015-06-22 22:17:37 +00:00
ApiService . scValidateConfig ( data , params ) . then ( function ( resp ) {
2015-01-07 21:20:51 +00:00
serviceInfo . status = resp . status ? 'success' : 'error' ;
serviceInfo . errorMessage = $ . trim ( resp . reason || '' ) ;
2016-05-23 19:08:51 +00:00
if ( ! resp . status ) {
authPassword = null ;
}
} , errorDisplay ) ;
2015-01-07 21:20:51 +00:00
} ;
2015-01-08 20:58:35 +00:00
$scope . checkValidateAndSave = function ( ) {
if ( $scope . configform . $valid ) {
2015-10-26 23:06:05 +00:00
saveStorageConfig ( ) ;
2015-01-08 20:58:35 +00:00
$scope . validateAndSave ( ) ;
return ;
}
2015-10-26 23:06:05 +00:00
var query = $element . find ( "input.ng-invalid:first" ) ;
if ( query && query . length ) {
query [ 0 ] . scrollIntoView ( ) ;
query . focus ( ) ;
}
2015-01-08 20:58:35 +00:00
} ;
2015-01-07 21:20:51 +00:00
$scope . validateAndSave = function ( ) {
2015-06-22 22:17:37 +00:00
$scope . validating = $scope . getServices ( $scope . config ) ;
var requirePassword = false ;
for ( var i = 0 ; i < $scope . validating . length ; ++ i ) {
var serviceInfo = $scope . validating [ i ] ;
if ( serviceInfo . service . password ) {
requirePassword = true ;
break ;
}
}
if ( ! requirePassword ) {
$scope . performValidateAndSave ( ) ;
return ;
}
var box = bootbox . dialog ( {
"message" : 'Please enter your superuser password to validate your auth configuration:' +
2016-06-09 18:45:48 +00:00
'<form style="margin-top: 10px" action="javascript:$(\'.btn-continue\').click()">' +
2015-06-22 22:17:37 +00:00
'<input id="validatePassword" class="form-control" type="password" placeholder="Password">' +
'</form>' ,
"title" : 'Enter Password' ,
"buttons" : {
2015-07-20 17:18:07 +00:00
"success" : {
2015-06-22 22:17:37 +00:00
"label" : "Validate Config" ,
2016-06-09 18:45:48 +00:00
"className" : "btn-success btn-continue" ,
2015-06-22 22:17:37 +00:00
"callback" : function ( ) {
$scope . performValidateAndSave ( $ ( '#validatePassword' ) . val ( ) ) ;
}
} ,
"close" : {
"label" : "Cancel" ,
"className" : "btn-default" ,
"callback" : function ( ) {
}
}
}
} ) ;
box . bind ( 'shown.bs.modal' , function ( ) {
box . find ( "input" ) . focus ( ) ;
box . find ( "form" ) . submit ( function ( ) {
if ( ! $ ( '#validatePassword' ) . val ( ) ) { return ; }
box . modal ( 'hide' ) ;
} ) ;
} ) ;
} ;
$scope . performValidateAndSave = function ( opt _password ) {
2015-01-07 21:20:51 +00:00
$scope . savingConfiguration = false ;
$scope . validating = $scope . getServices ( $scope . config ) ;
2016-05-23 19:08:51 +00:00
authPassword = opt _password ;
2015-01-07 21:20:51 +00:00
$ ( '#validateAndSaveModal' ) . modal ( {
keyboard : false ,
backdrop : 'static'
} ) ;
for ( var i = 0 ; i < $scope . validating . length ; ++ i ) {
var serviceInfo = $scope . validating [ i ] ;
2015-06-22 22:17:37 +00:00
$scope . validateService ( serviceInfo , opt _password ) ;
2015-01-07 21:20:51 +00:00
}
} ;
$scope . saveConfiguration = function ( ) {
$scope . savingConfiguration = true ;
2015-01-23 22:19:15 +00:00
// Make sure to note that fully verified setup is completed. We use this as a signal
// in the setup tool.
$scope . config [ 'SETUP_COMPLETE' ] = true ;
2015-01-07 21:20:51 +00:00
var data = {
'config' : $scope . config ,
2016-05-23 19:08:51 +00:00
'hostname' : window . location . host ,
'password' : authPassword || ''
2015-01-07 21:20:51 +00:00
} ;
2016-05-23 19:08:51 +00:00
var errorDisplay = ApiService . errorDisplay (
'Could not save configuration. Please report this error.' ,
function ( ) {
authPassword = null ;
} ) ;
2015-01-07 21:20:51 +00:00
ApiService . scUpdateConfig ( data ) . then ( function ( resp ) {
2016-05-23 19:08:51 +00:00
authPassword = null ;
2015-01-07 21:20:51 +00:00
$scope . savingConfiguration = false ;
2015-01-23 22:19:15 +00:00
$scope . mapped . $hasChanges = false ;
2016-05-23 19:08:51 +00:00
2015-01-23 22:19:15 +00:00
$ ( '#validateAndSaveModal' ) . modal ( 'hide' ) ;
2016-05-23 19:08:51 +00:00
2015-02-04 16:48:25 +00:00
$scope . configurationSaved ( { 'config' : $scope . config } ) ;
2016-05-23 19:08:51 +00:00
} , errorDisplay ) ;
2015-01-07 21:20:51 +00:00
} ;
2014-12-26 21:54:36 +00:00
2015-10-26 23:06:05 +00:00
// Convert storage config to an array
var initializeStorageConfig = function ( $scope ) {
var config = $scope . config . DISTRIBUTED _STORAGE _CONFIG || { } ;
var defaultLocations = $scope . config . DISTRIBUTED _STORAGE _DEFAULT _LOCATIONS || [ ] ;
var preference = $scope . config . DISTRIBUTED _STORAGE _PREFERENCE || [ ] ;
$scope . serverStorageConfig = angular . copy ( config ) ;
$scope . storageConfig = [ ] ;
Object . keys ( config ) . forEach ( function ( location ) {
$scope . storageConfig . push ( {
location : location ,
defaultLocation : defaultLocations . indexOf ( location ) >= 0 ,
data : angular . copy ( config [ location ] ) ,
error : { } ,
} ) ;
} ) ;
if ( ! $scope . storageConfig . length ) {
$scope . addStorageConfig ( 'default' ) ;
return ;
}
// match DISTRIBUTED_STORAGE_PREFERENCE order first, remaining are
// ordered by unicode point value
$scope . storageConfig . sort ( function ( a , b ) {
var indexA = preference . indexOf ( a . location ) ;
var indexB = preference . indexOf ( b . location ) ;
if ( indexA > - 1 && indexB > - 1 ) return indexA < indexB ? - 1 : 1 ;
if ( indexA > - 1 ) return - 1 ;
if ( indexB > - 1 ) return 1 ;
return a . location < b . location ? - 1 : 1 ;
} ) ;
} ;
$scope . allowChangeLocationStorageConfig = function ( location ) {
if ( ! $scope . serverStorageConfig [ location ] ) { return true } ;
// allow user to change location ID if another exists with the same ID
return $scope . storageConfig . filter ( function ( sc ) {
return sc . location === location ;
} ) . length >= 2 ;
} ;
$scope . allowRemoveStorageConfig = function ( location ) {
return $scope . storageConfig . length > 1 && $scope . allowChangeLocationStorageConfig ( location ) ;
} ;
$scope . canAddStorageConfig = function ( ) {
return $scope . config &&
$scope . config . FEATURE _STORAGE _REPLICATION &&
$scope . storageConfig &&
( ! $scope . storageConfig . length || $scope . storageConfig . length < 10 ) ;
} ;
$scope . addStorageConfig = function ( location ) {
var storageType = 'LocalStorage' ;
// Use last storage type by default
if ( $scope . storageConfig . length ) {
storageType = $scope . storageConfig [ $scope . storageConfig . length - 1 ] . data [ 0 ] ;
}
$scope . storageConfig . push ( {
location : location || '' ,
defaultLocation : false ,
data : [ storageType , { } ] ,
error : { } ,
} ) ;
} ;
$scope . removeStorageConfig = function ( sc ) {
$scope . storageConfig . splice ( $scope . storageConfig . indexOf ( sc ) , 1 ) ;
} ;
var saveStorageConfig = function ( ) {
var config = { } ;
var defaultLocations = [ ] ;
var preference = [ ] ;
$scope . storageConfig . forEach ( function ( sc ) {
config [ sc . location ] = sc . data ;
if ( sc . defaultLocation ) defaultLocations . push ( sc . location ) ;
preference . push ( sc . location ) ;
} ) ;
$scope . config . DISTRIBUTED _STORAGE _CONFIG = config ;
$scope . config . DISTRIBUTED _STORAGE _DEFAULT _LOCATIONS = defaultLocations ;
$scope . config . DISTRIBUTED _STORAGE _PREFERENCE = preference ;
} ;
2015-05-03 18:50:26 +00:00
var gitlabSelector = function ( key ) {
return function ( value ) {
if ( ! value || ! $scope . config ) { return ; }
if ( ! $scope . config [ key ] ) {
$scope . config [ key ] = { } ;
}
if ( value == 'enterprise' ) {
if ( $scope . config [ key ] [ 'GITLAB_ENDPOINT' ] == 'https://gitlab.com/' ) {
$scope . config [ key ] [ 'GITLAB_ENDPOINT' ] = '' ;
}
} else if ( value == 'hosted' ) {
$scope . config [ key ] [ 'GITLAB_ENDPOINT' ] = 'https://gitlab.com/' ;
}
} ;
} ;
2015-01-05 20:18:01 +00:00
var githubSelector = function ( key ) {
return function ( value ) {
if ( ! value || ! $scope . config ) { return ; }
if ( ! $scope . config [ key ] ) {
$scope . config [ key ] = { } ;
}
if ( value == 'enterprise' ) {
2015-01-08 18:26:24 +00:00
if ( $scope . config [ key ] [ 'GITHUB_ENDPOINT' ] == 'https://github.com/' ) {
$scope . config [ key ] [ 'GITHUB_ENDPOINT' ] = '' ;
}
delete $scope . config [ key ] [ 'API_ENDPOINT' ] ;
2015-01-05 20:18:01 +00:00
} else if ( value == 'hosted' ) {
$scope . config [ key ] [ 'GITHUB_ENDPOINT' ] = 'https://github.com/' ;
$scope . config [ key ] [ 'API_ENDPOINT' ] = 'https://api.github.com/' ;
}
} ;
} ;
var getKey = function ( config , path ) {
2015-02-17 16:31:50 +00:00
if ( ! config ) {
return null ;
}
2015-01-05 20:18:01 +00:00
var parts = path . split ( '.' ) ;
var current = config ;
for ( var i = 0 ; i < parts . length ; ++ i ) {
var part = parts [ i ] ;
2015-01-07 21:20:51 +00:00
if ( ! current [ part ] ) { return null ; }
current = current [ part ] ;
2015-01-05 20:18:01 +00:00
}
return current ;
} ;
var initializeMappedLogic = function ( config ) {
var gle = getKey ( config , 'GITHUB_LOGIN_CONFIG.GITHUB_ENDPOINT' ) ;
var gte = getKey ( config , 'GITHUB_TRIGGER_CONFIG.GITHUB_ENDPOINT' ) ;
$scope . mapped [ 'GITHUB_LOGIN_KIND' ] = gle == 'https://github.com/' ? 'hosted' : 'enterprise' ;
$scope . mapped [ 'GITHUB_TRIGGER_KIND' ] = gte == 'https://github.com/' ? 'hosted' : 'enterprise' ;
2015-05-03 18:50:26 +00:00
var glabe = getKey ( config , 'GITLAB_TRIGGER_KIND.GITHUB_ENDPOINT' ) ;
$scope . mapped [ 'GITLAB_TRIGGER_KIND' ] = glabe == 'https://gitlab.com/' ? 'hosted' : 'enterprise' ;
2015-01-05 20:18:01 +00:00
$scope . mapped [ 'redis' ] = { } ;
$scope . mapped [ 'redis' ] [ 'host' ] = getKey ( config , 'BUILDLOGS_REDIS.host' ) || getKey ( config , 'USER_EVENTS_REDIS.host' ) ;
$scope . mapped [ 'redis' ] [ 'port' ] = getKey ( config , 'BUILDLOGS_REDIS.port' ) || getKey ( config , 'USER_EVENTS_REDIS.port' ) ;
$scope . mapped [ 'redis' ] [ 'password' ] = getKey ( config , 'BUILDLOGS_REDIS.password' ) || getKey ( config , 'USER_EVENTS_REDIS.password' ) ;
2016-10-13 18:49:29 +00:00
$scope . mapped [ 'TLS_SETTING' ] = 'none' ;
if ( config [ 'PREFERRED_URL_SCHEME' ] == 'https' ) {
if ( config [ 'EXTERNAL_TLS_TERMINATION' ] === true ) {
$scope . mapped [ 'TLS_SETTING' ] = 'external-tls' ;
} else {
$scope . mapped [ 'TLS_SETTING' ] = 'internal-tls' ;
}
}
} ;
var tlsSetter = function ( value ) {
if ( value == null || ! $scope . config ) { return ; }
switch ( value ) {
case 'none' :
$scope . config [ 'PREFERRED_URL_SCHEME' ] = 'http' ;
delete $scope . config [ 'EXTERNAL_TLS_TERMINATION' ] ;
return ;
case 'external-tls' :
$scope . config [ 'PREFERRED_URL_SCHEME' ] = 'https' ;
$scope . config [ 'EXTERNAL_TLS_TERMINATION' ] = true ;
return ;
case 'internal-tls' :
$scope . config [ 'PREFERRED_URL_SCHEME' ] = 'https' ;
delete $scope . config [ 'EXTERNAL_TLS_TERMINATION' ] ;
return ;
}
2015-01-05 20:18:01 +00:00
} ;
var redisSetter = function ( keyname ) {
return function ( value ) {
if ( value == null || ! $scope . config ) { return ; }
if ( ! $scope . config [ 'BUILDLOGS_REDIS' ] ) {
$scope . config [ 'BUILDLOGS_REDIS' ] = { } ;
}
if ( ! $scope . config [ 'USER_EVENTS_REDIS' ] ) {
$scope . config [ 'USER_EVENTS_REDIS' ] = { } ;
}
if ( ! value ) {
delete $scope . config [ 'BUILDLOGS_REDIS' ] [ keyname ] ;
delete $scope . config [ 'USER_EVENTS_REDIS' ] [ keyname ] ;
return ;
}
$scope . config [ 'BUILDLOGS_REDIS' ] [ keyname ] = value ;
$scope . config [ 'USER_EVENTS_REDIS' ] [ keyname ] = value ;
} ;
} ;
// Add mapped logic.
$scope . $watch ( 'mapped.GITHUB_LOGIN_KIND' , githubSelector ( 'GITHUB_LOGIN_CONFIG' ) ) ;
$scope . $watch ( 'mapped.GITHUB_TRIGGER_KIND' , githubSelector ( 'GITHUB_TRIGGER_CONFIG' ) ) ;
2015-05-03 18:50:26 +00:00
$scope . $watch ( 'mapped.GITLAB_TRIGGER_KIND' , gitlabSelector ( 'GITLAB_TRIGGER_KIND' ) ) ;
2016-10-13 18:49:29 +00:00
$scope . $watch ( 'mapped.TLS_SETTING' , tlsSetter ) ;
2015-01-05 20:18:01 +00:00
$scope . $watch ( 'mapped.redis.host' , redisSetter ( 'host' ) ) ;
$scope . $watch ( 'mapped.redis.port' , redisSetter ( 'port' ) ) ;
$scope . $watch ( 'mapped.redis.password' , redisSetter ( 'password' ) ) ;
2015-10-26 23:06:05 +00:00
// Remove extra extra fields (which are not allowed) from storage config.
var updateFields = function ( sc ) {
var type = sc . data [ 0 ] ;
var configObject = sc . data [ 1 ] ;
var allowedFields = $scope . STORAGE _CONFIG _FIELDS [ type ] ;
2015-01-07 21:20:51 +00:00
2015-01-08 20:27:49 +00:00
// Remove any fields not allowed.
2015-01-07 21:20:51 +00:00
for ( var fieldName in configObject ) {
if ( ! configObject . hasOwnProperty ( fieldName ) ) {
continue ;
}
var isValidField = $ . grep ( allowedFields , function ( field ) {
return field . name == fieldName ;
} ) . length > 0 ;
if ( ! isValidField ) {
delete configObject [ fieldName ] ;
}
}
2015-01-08 20:27:49 +00:00
2015-08-05 17:52:48 +00:00
// Set any missing boolean fields to false.
2015-01-08 20:27:49 +00:00
for ( var i = 0 ; i < allowedFields . length ; ++ i ) {
if ( allowedFields [ i ] . kind == 'bool' ) {
2015-08-05 17:52:48 +00:00
configObject [ allowedFields [ i ] . name ] = configObject [ allowedFields [ i ] . name ] || false ;
2015-01-08 20:27:49 +00:00
}
}
2015-10-26 23:06:05 +00:00
} ;
// Validate and update storage config on update.
var refreshStorageConfig = function ( ) {
if ( ! $scope . config || ! $scope . storageConfig ) return ;
var locationCounts = { } ;
var errors = [ ] ;
var valid = true ;
$scope . storageConfig . forEach ( function ( sc ) {
// remove extra fields from storage config
updateFields ( sc ) ;
if ( ! locationCounts [ sc . location ] ) locationCounts [ sc . location ] = 0 ;
locationCounts [ sc . location ] ++ ;
} ) ;
// validate storage config
$scope . storageConfig . forEach ( function ( sc ) {
var error = { } ;
if ( $scope . config . FEATURE _STORAGE _REPLICATION && sc . data [ 0 ] === 'LocalStorage' ) {
error . engine = 'Replication to a locally mounted directory is unsupported as it is only accessible on a single machine.' ;
valid = false ;
}
if ( locationCounts [ sc . location ] > 1 ) {
error . location = 'Location ID must be unique.' ;
valid = false ;
}
errors . push ( error ) ;
} ) ;
$scope . storageConfigError = errors ;
$scope . configform . $setValidity ( 'storageConfig' , valid ) ;
} ;
2017-06-09 21:12:05 +00:00
$scope . $watch ( 'config.INTERNAL_OIDC_SERVICE_ID' , function ( service _id ) {
if ( service _id ) {
$scope . config [ 'FEATURE_DIRECT_LOGIN' ] = false ;
}
} ) ;
2015-10-26 23:06:05 +00:00
$scope . $watch ( 'config.FEATURE_STORAGE_REPLICATION' , function ( ) {
refreshStorageConfig ( ) ;
2015-01-07 21:20:51 +00:00
} ) ;
2015-10-26 23:06:05 +00:00
$scope . $watch ( 'storageConfig' , function ( ) {
refreshStorageConfig ( ) ;
} , true ) ;
2015-01-05 20:18:01 +00:00
$scope . $watch ( 'config' , function ( value ) {
2015-01-07 21:20:51 +00:00
$scope . mapped [ '$hasChanges' ] = true ;
2015-01-05 20:18:01 +00:00
} , true ) ;
2015-01-05 18:01:32 +00:00
$scope . $watch ( 'isActive' , function ( value ) {
if ( ! value ) { return ; }
ApiService . scGetConfig ( ) . then ( function ( resp ) {
2015-02-18 00:15:54 +00:00
$scope . config = resp [ 'config' ] || { } ;
2015-01-05 20:18:01 +00:00
initializeMappedLogic ( $scope . config ) ;
2015-10-26 23:06:05 +00:00
initializeStorageConfig ( $scope ) ;
2015-01-07 21:20:51 +00:00
$scope . mapped [ '$hasChanges' ] = false ;
2015-02-18 00:15:54 +00:00
} , ApiService . errorDisplay ( 'Could not load config' ) ) ;
2015-01-05 18:01:32 +00:00
} ) ;
2014-12-26 21:54:36 +00:00
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configParsedField' , function ( $timeout ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-parsed-field.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'parser' : '&parser' ,
'serializer' : '&serializer'
} ,
controller : function ( $scope , $element , $transclude ) {
$scope . childScope = null ;
$transclude ( function ( clone , scope ) {
$scope . childScope = scope ;
2015-01-04 19:38:41 +00:00
$scope . childScope [ 'fields' ] = { } ;
2014-12-26 21:54:36 +00:00
$element . append ( clone ) ;
} ) ;
2015-01-04 19:38:41 +00:00
$scope . childScope . $watch ( 'fields' , function ( value ) {
2014-12-26 21:54:36 +00:00
// Note: We need the timeout here because Angular starts the digest of the
// parent scope AFTER the child scope, which means it can end up one action
// behind. The timeout ensures that the parent scope will be fully digest-ed
// and then we update the binding. Yes, this is a hack :-/.
$timeout ( function ( ) {
$scope . binding = $scope . serializer ( { 'fields' : value } ) ;
} ) ;
2015-01-04 19:38:41 +00:00
} , true ) ;
2014-12-26 21:54:36 +00:00
$scope . $watch ( 'binding' , function ( value ) {
var parsed = $scope . parser ( { 'value' : value } ) ;
for ( var key in parsed ) {
if ( parsed . hasOwnProperty ( key ) ) {
2015-01-04 19:38:41 +00:00
$scope . childScope [ 'fields' ] [ key ] = parsed [ key ] ;
2014-12-26 21:54:36 +00:00
}
}
} ) ;
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configVariableField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-variable-field.html' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'binding' : '=binding'
} ,
controller : function ( $scope , $element ) {
$scope . sections = { } ;
$scope . currentSection = null ;
$scope . setSection = function ( section ) {
$scope . binding = section . value ;
} ;
this . addSection = function ( section , element ) {
$scope . sections [ section . value ] = {
'title' : section . valueTitle ,
'value' : section . value ,
'element' : element
} ;
element . hide ( ) ;
if ( ! $scope . binding ) {
$scope . binding = section . value ;
}
} ;
$scope . $watch ( 'binding' , function ( binding ) {
if ( ! binding ) { return ; }
if ( $scope . currentSection ) {
$scope . currentSection . element . hide ( ) ;
}
if ( $scope . sections [ binding ] ) {
$scope . sections [ binding ] . element . show ( ) ;
$scope . currentSection = $scope . sections [ binding ] ;
}
} ) ;
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'variableSection' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-variable-field.html' ,
priority : 1 ,
require : '^configVariableField' ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'value' : '@value' ,
'valueTitle' : '@valueTitle'
} ,
controller : function ( $scope , $element ) {
var parentCtrl = $element . parent ( ) . controller ( 'configVariableField' ) ;
parentCtrl . addSection ( $scope , $element ) ;
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configListField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-list-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'placeholder' : '@placeholder' ,
'defaultValue' : '@defaultValue' ,
2017-04-05 18:01:55 +00:00
'itemTitle' : '@itemTitle' ,
'itemPattern' : '@itemPattern'
2014-12-26 21:54:36 +00:00
} ,
controller : function ( $scope , $element ) {
$scope . removeItem = function ( item ) {
var index = $scope . binding . indexOf ( item ) ;
if ( index >= 0 ) {
$scope . binding . splice ( index , 1 ) ;
}
} ;
$scope . addItem = function ( ) {
if ( ! $scope . newItemName ) {
return ;
}
if ( ! $scope . binding ) {
$scope . binding = [ ] ;
}
if ( $scope . binding . indexOf ( $scope . newItemName ) >= 0 ) {
return ;
}
$scope . binding . push ( $scope . newItemName ) ;
$scope . newItemName = null ;
} ;
2017-04-05 18:01:55 +00:00
$scope . patternMap = { } ;
$scope . getRegexp = function ( pattern ) {
if ( ! pattern ) {
pattern = '.*' ;
}
if ( $scope . patternMap [ pattern ] ) {
return $scope . patternMap [ pattern ] ;
}
return $scope . patternMap [ pattern ] = new RegExp ( pattern ) ;
} ;
2014-12-26 21:54:36 +00:00
$scope . $watch ( 'binding' , function ( binding ) {
if ( ! binding && $scope . defaultValue ) {
$scope . binding = eval ( $scope . defaultValue ) ;
}
} ) ;
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configFileField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-file-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
2015-06-29 05:08:10 +00:00
'filename' : '@filename' ,
'skipCheckFile' : '@skipCheckFile' ,
2018-01-10 19:46:36 +00:00
'hasFile' : '=hasFile' ,
'binding' : '=?binding'
2014-12-26 21:54:36 +00:00
} ,
controller : function ( $scope , $element , Restangular , $upload ) {
$scope . hasFile = false ;
2018-01-10 19:46:36 +00:00
var setHasFile = function ( hasFile ) {
$scope . hasFile = hasFile ;
$scope . binding = hasFile ? $scope . filename : null ;
} ;
2014-12-26 21:54:36 +00:00
$scope . onFileSelect = function ( files ) {
2015-06-29 05:08:10 +00:00
if ( files . length < 1 ) {
2018-01-10 19:46:36 +00:00
setHasFile ( false ) ;
2015-06-29 05:08:10 +00:00
return ;
}
2014-12-26 21:54:36 +00:00
$scope . uploadProgress = 0 ;
$scope . upload = $upload . upload ( {
2015-01-07 21:50:08 +00:00
url : '/api/v1/superuser/config/file/' + $scope . filename ,
2014-12-26 21:54:36 +00:00
method : 'POST' ,
2015-01-07 21:50:08 +00:00
data : { '_csrf_token' : window . _ _token } ,
2014-12-26 21:54:36 +00:00
file : files [ 0 ] ,
} ) . progress ( function ( evt ) {
$scope . uploadProgress = parseInt ( 100.0 * evt . loaded / evt . total ) ;
if ( $scope . uploadProgress == 100 ) {
$scope . uploadProgress = null ;
2018-01-10 19:46:36 +00:00
setHasFile ( true ) ;
2014-12-26 21:54:36 +00:00
}
} ) . success ( function ( data , status , headers , config ) {
$scope . uploadProgress = null ;
2018-01-10 19:46:36 +00:00
setHasFile ( true ) ;
2014-12-26 21:54:36 +00:00
} ) ;
} ;
var loadStatus = function ( filename ) {
2015-01-04 19:38:41 +00:00
Restangular . one ( 'superuser/config/file/' + filename ) . get ( ) . then ( function ( resp ) {
2018-01-10 19:46:36 +00:00
setHasFile ( false ) ;
2014-12-26 21:54:36 +00:00
} ) ;
} ;
2015-06-29 05:08:10 +00:00
if ( $scope . filename && $scope . skipCheckFile != "true" ) {
2014-12-26 21:54:36 +00:00
loadStatus ( $scope . filename ) ;
}
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configBoolField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-bool-field.html' ,
replace : false ,
2016-05-20 17:23:32 +00:00
transclude : true ,
2014-12-26 21:54:36 +00:00
restrict : 'C' ,
scope : {
'binding' : '=binding'
} ,
controller : function ( $scope , $element ) {
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configNumericField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-numeric-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'placeholder' : '@placeholder' ,
2016-12-01 18:22:27 +00:00
'defaultValue' : '@defaultValue' ,
2014-12-26 21:54:36 +00:00
} ,
controller : function ( $scope , $element ) {
$scope . bindinginternal = 0 ;
$scope . $watch ( 'binding' , function ( binding ) {
if ( $scope . binding == 0 && $scope . defaultValue ) {
$scope . binding = $scope . defaultValue * 1 ;
}
$scope . bindinginternal = $scope . binding ;
} ) ;
$scope . $watch ( 'bindinginternal' , function ( binding ) {
var newValue = $scope . bindinginternal * 1 ;
if ( isNaN ( newValue ) ) {
newValue = 0 ;
}
$scope . binding = newValue ;
} ) ;
}
} ;
return directiveDefinitionObject ;
} )
2015-01-05 22:10:01 +00:00
. directive ( 'configContactsField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-contacts-field.html' ,
priority : 1 ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding'
} ,
controller : function ( $scope , $element ) {
2015-01-07 21:20:51 +00:00
var padItems = function ( items ) {
2015-01-05 22:10:01 +00:00
// Remove the last item if both it and the second to last items are empty.
if ( items . length > 1 && ! items [ items . length - 2 ] . value && ! items [ items . length - 1 ] . value ) {
items . splice ( items . length - 1 , 1 ) ;
return ;
}
// If the last item is non-empty, add a new item.
2015-01-07 21:20:51 +00:00
if ( items . length == 0 || items [ items . length - 1 ] . value ) {
2015-01-05 22:10:01 +00:00
items . push ( { 'value' : '' } ) ;
2015-01-07 21:20:51 +00:00
return ;
}
} ;
$scope . itemHash = null ;
$scope . $watch ( 'items' , function ( items ) {
if ( ! items ) { return ; }
padItems ( items ) ;
var itemHash = '' ;
var binding = [ ] ;
for ( var i = 0 ; i < items . length ; ++ i ) {
var item = items [ i ] ;
if ( item . value && ( URI ( item . value ) . host ( ) || URI ( item . value ) . path ( ) ) ) {
binding . push ( item . value ) ;
itemHash += item . value ;
}
2015-01-05 22:10:01 +00:00
}
2015-01-07 21:20:51 +00:00
$scope . itemHash = itemHash ;
$scope . binding = binding ;
2015-01-05 22:10:01 +00:00
} , true ) ;
$scope . $watch ( 'binding' , function ( binding ) {
2015-01-08 20:58:35 +00:00
var current = binding || [ ] ;
2015-01-07 21:20:51 +00:00
var items = [ ] ;
var itemHash = '' ;
for ( var i = 0 ; i < current . length ; ++ i ) {
items . push ( { 'value' : current [ i ] } )
itemHash += current [ i ] ;
}
if ( $scope . itemHash != itemHash ) {
$scope . items = items ;
}
2015-01-05 22:10:01 +00:00
} ) ;
}
} ;
return directiveDefinitionObject ;
} )
. directive ( 'configContactField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-contact-field.html' ,
priority : 1 ,
replace : false ,
transclude : true ,
restrict : 'C' ,
scope : {
'binding' : '=binding'
} ,
controller : function ( $scope , $element ) {
$scope . kind = null ;
$scope . value = null ;
var updateBinding = function ( ) {
2015-01-07 21:20:51 +00:00
if ( $scope . value == null ) { return ; }
2015-01-05 22:10:01 +00:00
var value = $scope . value || '' ;
2018-06-01 17:50:39 +00:00
if ( ! value ) {
$scope . binding = '' ;
return ;
}
2015-01-05 22:10:01 +00:00
switch ( $scope . kind ) {
case 'mailto' :
$scope . binding = 'mailto:' + value ;
return ;
case 'tel' :
$scope . binding = 'tel:' + value ;
return ;
case 'irc' :
$scope . binding = 'irc://' + value ;
return ;
default :
$scope . binding = value ;
return ;
}
} ;
$scope . $watch ( 'kind' , updateBinding ) ;
$scope . $watch ( 'value' , updateBinding ) ;
$scope . $watch ( 'binding' , function ( value ) {
if ( ! value ) {
$scope . kind = null ;
$scope . value = null ;
return ;
}
var uri = URI ( value ) ;
$scope . kind = uri . scheme ( ) ;
switch ( $scope . kind ) {
case 'mailto' :
case 'tel' :
$scope . value = uri . path ( ) ;
break ;
case 'irc' :
$scope . value = value . substr ( 'irc://' . length ) ;
break ;
default :
$scope . kind = 'http' ;
$scope . value = value ;
break ;
}
} ) ;
$scope . getPlaceholder = function ( kind ) {
switch ( kind ) {
case 'mailto' :
return 'some@example.com' ;
case 'tel' :
return '555-555-5555' ;
case 'irc' :
return 'myserver:port/somechannel' ;
default :
return 'http://some/url' ;
}
} ;
}
} ;
return directiveDefinitionObject ;
} )
2015-05-21 19:22:59 +00:00
. directive ( 'configMapField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-map-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'keys' : '=keys'
} ,
controller : function ( $scope , $element ) {
$scope . newKey = null ;
$scope . newValue = null ;
$scope . hasValues = function ( binding ) {
return binding && Object . keys ( binding ) . length ;
} ;
$scope . removeKey = function ( key ) {
delete $scope . binding [ key ] ;
} ;
$scope . addEntry = function ( ) {
if ( ! $scope . newKey || ! $scope . newValue ) { return ; }
$scope . binding = $scope . binding || { } ;
$scope . binding [ $scope . newKey ] = $scope . newValue ;
$scope . newKey = null ;
$scope . newValue = null ;
}
}
} ;
return directiveDefinitionObject ;
} )
2016-05-02 19:29:31 +00:00
. directive ( 'configServiceKeyField' , function ( ApiService ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-service-key-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'serviceName' : '@serviceName' ,
} ,
controller : function ( $scope , $element ) {
$scope . foundKeys = [ ] ;
$scope . loading = false ;
$scope . loadError = false ;
$scope . hasValidKey = false ;
$scope . hasValidKeyStr = null ;
$scope . updateKeys = function ( ) {
$scope . foundKeys = [ ] ;
$scope . loading = true ;
ApiService . listServiceKeys ( ) . then ( function ( resp ) {
$scope . loading = false ;
$scope . loadError = false ;
resp [ 'keys' ] . forEach ( function ( key ) {
if ( key [ 'service' ] == $scope . serviceName ) {
$scope . foundKeys . push ( key ) ;
}
} ) ;
$scope . hasValidKey = checkValidKey ( $scope . foundKeys ) ;
$scope . hasValidKeyStr = $scope . hasValidKey ? 'true' : '' ;
} , function ( ) {
$scope . loading = false ;
$scope . loadError = true ;
} ) ;
} ;
// Perform initial loading of the keys.
$scope . updateKeys ( ) ;
$scope . isKeyExpired = function ( key ) {
if ( key . expiration _date != null ) {
var expiration _date = moment ( key . expiration _date ) ;
return moment ( ) . isAfter ( expiration _date ) ;
}
return false ;
} ;
$scope . showRequestServiceKey = function ( ) {
$scope . requestKeyInfo = {
'service' : $scope . serviceName
} ;
} ;
$scope . handleKeyCreated = function ( ) {
$scope . updateKeys ( ) ;
} ;
var checkValidKey = function ( keys ) {
for ( var i = 0 ; i < keys . length ; ++ i ) {
var key = keys [ i ] ;
if ( ! key . approval ) {
continue ;
}
if ( $scope . isKeyExpired ( key ) ) {
continue ;
}
return true ;
}
return false ;
} ;
}
} ;
return directiveDefinitionObject ;
} )
2014-12-26 21:54:36 +00:00
. directive ( 'configStringField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-string-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'placeholder' : '@placeholder' ,
'pattern' : '@pattern' ,
2015-01-15 19:36:05 +00:00
'defaultValue' : '@defaultValue' ,
2015-05-21 19:22:59 +00:00
'validator' : '&validator' ,
'isOptional' : '=isOptional'
2014-12-26 21:54:36 +00:00
} ,
controller : function ( $scope , $element ) {
2016-04-22 17:55:47 +00:00
var firstSet = true ;
2016-05-17 20:29:24 +00:00
$scope . patternMap = { } ;
2014-12-26 21:54:36 +00:00
$scope . getRegexp = function ( pattern ) {
2016-07-07 18:26:14 +00:00
if ( ! pattern ) {
pattern = '.*' ;
}
2016-05-17 20:29:24 +00:00
2016-07-07 18:26:14 +00:00
if ( $scope . patternMap [ pattern ] ) {
return $scope . patternMap [ pattern ] ;
}
2016-05-17 20:29:24 +00:00
2016-07-07 18:26:14 +00:00
return $scope . patternMap [ pattern ] = new RegExp ( pattern ) ;
} ;
2014-12-26 21:54:36 +00:00
$scope . $watch ( 'binding' , function ( binding ) {
2016-04-22 17:55:47 +00:00
if ( firstSet && ! binding && $scope . defaultValue ) {
2014-12-26 21:54:36 +00:00
$scope . binding = $scope . defaultValue ;
2016-04-22 17:55:47 +00:00
firstSet = false ;
2014-12-26 21:54:36 +00:00
}
2015-01-15 19:36:05 +00:00
$scope . errorMessage = $scope . validator ( { 'value' : binding || '' } ) ;
2014-12-26 21:54:36 +00:00
} ) ;
}
} ;
return directiveDefinitionObject ;
2016-07-07 18:26:14 +00:00
} )
. directive ( 'configStringListField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-string-list-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
'binding' : '=binding' ,
'itemTitle' : '@itemTitle' ,
'itemDelimiter' : '@itemDelimiter' ,
'placeholder' : '@placeholder' ,
'isOptional' : '=isOptional'
} ,
controller : function ( $scope , $element ) {
$scope . $watch ( 'internalBinding' , function ( value ) {
if ( value ) {
$scope . binding = value . split ( $scope . itemDelimiter ) ;
}
} ) ;
$scope . $watch ( 'binding' , function ( value ) {
if ( value ) {
$scope . internalBinding = value . join ( $scope . itemDelimiter ) ;
}
} ) ;
}
} ;
return directiveDefinitionObject ;
2016-10-11 19:16:28 +00:00
} )
2017-01-11 23:45:46 +00:00
. directive ( 'configCertificatesField' , function ( ) {
var directiveDefinitionObject = {
priority : 0 ,
templateUrl : '/static/directives/config/config-certificates-field.html' ,
replace : false ,
transclude : false ,
restrict : 'C' ,
scope : {
} ,
controller : function ( $scope , $element , $upload , ApiService , UserService ) {
$scope . resetUpload = 0 ;
2017-03-24 21:00:51 +00:00
$scope . certsUploading = false ;
2017-01-11 23:45:46 +00:00
var loadCertificates = function ( ) {
$scope . certificatesResource = ApiService . getCustomCertificatesAsResource ( ) . get ( function ( resp ) {
$scope . certInfo = resp ;
2017-03-24 21:00:51 +00:00
$scope . certsUploading = false ;
2017-01-11 23:45:46 +00:00
} ) ;
} ;
UserService . updateUserIn ( $scope , function ( user ) {
if ( ! user . anonymous ) {
loadCertificates ( ) ;
}
} ) ;
$scope . handleCertsSelected = function ( files , callback ) {
2017-03-24 21:00:51 +00:00
$scope . certsUploading = true ;
2017-01-11 23:45:46 +00:00
$upload . upload ( {
url : '/api/v1/superuser/customcerts/' + files [ 0 ] . name ,
method : 'POST' ,
data : { '_csrf_token' : window . _ _token } ,
file : files [ 0 ]
} ) . success ( function ( ) {
callback ( true ) ;
$scope . resetUpload ++ ;
loadCertificates ( ) ;
2017-03-29 20:06:15 +00:00
} ) . error ( function ( r ) {
bootbox . alert ( 'Could not upload certificate' )
callback ( false ) ;
$scope . resetUpload ++ ;
loadCertificates ( ) ;
2017-01-11 23:45:46 +00:00
} ) ;
} ;
$scope . deleteCert = function ( path ) {
var errorDisplay = ApiService . errorDisplay ( 'Could not delete certificate' ) ;
var params = {
'certpath' : path
} ;
ApiService . deleteCustomCertificate ( null , params ) . then ( loadCertificates , errorDisplay ) ;
} ;
}
} ;
return directiveDefinitionObject ;
2018-03-27 20:18:56 +00:00
} ) ;