Commit a23a9b4f authored by Sascha's avatar Sascha

Merge branch 'develop' into 'master'

Preparing v1.14.0

See merge request !125
parents af806c1e eebef5f0
......@@ -15,12 +15,12 @@ test-unittests:
image: psono-docker.jfrog.io/ubuntu:16.04
script:
- sh ./var/build-ubuntu.sh
- apt-get install -y --no-install-recommends xvfb x11vnc fluxbox xterm
- curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
- echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
- apt-get update
- apt-get install -y google-chrome-stable
- karma start ./unittests/karma-chrome-headless.conf.js
- apt-get install -y --no-install-recommends xvfb x11vnc fluxbox xterm chromium-browser
# - curl -fsSL https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
# - echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" > /etc/apt/sources.list.d/google-chrome.list
# - apt-get update
# - apt-get install -y google-chrome-stable
- karma start ./unittests/karma-chromium-headless.conf.js
test-linter:
except:
......
......@@ -240,6 +240,7 @@ var build = function(build_path, type) {
"src/common/data/js/service/api-client.js",
"src/common/data/js/service/api-gcp.js",
"src/common/data/js/service/api-do.js",
"src/common/data/js/service/api-aws.js",
"src/common/data/js/service/api-fileserver.js",
"src/common/data/js/service/api-pwnedpasswords.js",
......
......@@ -246,6 +246,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -162,6 +162,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -480,6 +480,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -231,6 +231,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -363,6 +363,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -237,6 +237,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -559,6 +559,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -121,6 +121,39 @@
return;
}
if ($scope.selected_type === 'do_spaces' && !$scope.storage_config['do_space']) {
$scope.errors.push('SPACE_IS_REQUIRED');
return;
}
if ($scope.selected_type === 'do_spaces' && !$scope.storage_config['do_region']) {
$scope.errors.push('REGION_IS_REQUIRED');
return;
}
var do_spaces_regions = [
'ams3',
'fra1',
'nyc3',
'sfo2',
'sgp1'
];
if ($scope.selected_type === 'do_spaces' && do_spaces_regions.indexOf($scope.storage_config['do_region']) === -1) {
$scope.errors.push('REGION_IS_INVALID');
return;
}
if ($scope.selected_type === 'do_spaces' && !$scope.storage_config['do_key']) {
$scope.errors.push('KEY_IS_REQUIRED');
return;
}
if ($scope.selected_type === 'do_spaces' && !$scope.storage_config['do_secret']) {
$scope.errors.push('SECRET_IS_REQUIRED');
return;
}
if ($scope.modalCreateFileRepositoryForm.$invalid) {
return;
......@@ -141,7 +174,11 @@
$scope.storage_config['aws_s3_bucket'],
$scope.storage_config['aws_s3_region'],
$scope.storage_config['aws_s3_access_key_id'],
$scope.storage_config['aws_s3_secret_access_key']
$scope.storage_config['aws_s3_secret_access_key'],
$scope.storage_config['do_space'],
$scope.storage_config['do_region'],
$scope.storage_config['do_key'],
$scope.storage_config['do_secret']
)
.then(onSuccess, onError);
}
......
......@@ -113,6 +113,26 @@
return;
}
if ($scope.file_repository.type === 'do_spaces' && !$scope.file_repository['do_space']) {
$scope.errors.push('SPACE_IS_REQUIRED');
return;
}
if ($scope.file_repository.type === 'do_spaces' && !$scope.file_repository['do_region']) {
$scope.errors.push('REGION_IS_REQUIRED');
return;
}
if ($scope.file_repository.type === 'do_spaces' && !$scope.file_repository['do_key']) {
$scope.errors.push('KEY_IS_REQUIRED');
return;
}
if ($scope.file_repository.type === 'do_spaces' && !$scope.file_repository['do_secret']) {
$scope.errors.push('SECRET_IS_REQUIRED');
return;
}
if ($scope.modalEditFileRepositoryForm.$invalid) {
return;
}
......@@ -135,7 +155,11 @@
$scope.file_repository['aws_s3_bucket'],
$scope.file_repository['aws_s3_region'],
$scope.file_repository['aws_s3_access_key_id'],
$scope.file_repository['aws_s3_secret_access_key']
$scope.file_repository['aws_s3_secret_access_key'],
$scope.file_repository['do_space'],
$scope.file_repository['do_region'],
$scope.file_repository['do_key'],
$scope.file_repository['do_secret']
)
.then(onSuccess, onError);
}
......
......@@ -450,10 +450,23 @@ var ClassWorkerContentScript = function (base, browser, jQuery, setTimeout) {
*/
function on_return_secret (data) {
var fill_field_helper = function(field, value) {
field.value = value;
// jQuery event triggering is not working for angular apps
if ("createEvent" in document) {
var evt = document.createEvent("HTMLEvents");
evt.initEvent("change", false, true);
field.dispatchEvent(evt);
} else {
field.fireEvent("onchange");
}
};
for (var i = 0; i < myForms.length; i++) {
if (myForms[i].username.isEqualNode(last_request_element) || myForms[i].password.isEqualNode(last_request_element)) {
myForms[i].username.value = data.website_password_username;
myForms[i].password.value = data.website_password_password;
fill_field_helper(myForms[i].username, data.website_password_username);
fill_field_helper(myForms[i].password, data.website_password_password);
for (var ii = 0; ii < dropInstances.length; ii++) {
dropInstances[ii].close();
......
......@@ -2319,10 +2319,17 @@
* @param {string} [aws_s3_region] (optional) The s3 region
* @param {string} [aws_s3_access_key_id] (optional) The s3 access key
* @param {string} [aws_s3_secret_access_key] (optional) The s3 secret key
* @param {string} [do_space] (optional) The digital ocean space
* @param {string} [do_region] (optional) The digital ocean region
* @param {string} [do_key] (optional) The digital ocean key
* @param {string} [do_secret] (optional) The digital ocean secret
*
* @returns {promise} promise
*/
var create_file_repository = function (token, session_secret_key, title, type, gcp_cloud_storage_bucket, gcp_cloud_storage_json_key, aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key) {
var create_file_repository = function (token, session_secret_key, title, type,
gcp_cloud_storage_bucket, gcp_cloud_storage_json_key,
aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key,
do_space, do_region, do_key, do_secret) {
var endpoint = '/file-repository/';
var connection_type = "PUT";
......@@ -2334,7 +2341,11 @@
aws_s3_bucket: aws_s3_bucket,
aws_s3_region: aws_s3_region,
aws_s3_access_key_id: aws_s3_access_key_id,
aws_s3_secret_access_key: aws_s3_secret_access_key
aws_s3_secret_access_key: aws_s3_secret_access_key,
do_space: do_space,
do_region: do_region,
do_key: do_key,
do_secret: do_secret
};
var headers = {
......@@ -2363,11 +2374,18 @@
* @param {string} [aws_s3_region] (optional) The s3 region
* @param {string} [aws_s3_access_key_id] (optional) The s3 access key
* @param {string} [aws_s3_secret_access_key] (optional) The s3 secret key
* @param {string} [do_space] (optional) The digital ocean space
* @param {string} [do_region] (optional) The digital ocean region
* @param {string} [do_key] (optional) The digital ocean key
* @param {string} [do_secret] (optional) The digital ocean secret
* @param {bool} active Active or not
*
* @returns {promise} Returns a promise which can succeed or fail
*/
var update_file_repository = function (token, session_secret_key, file_repository_id, title, type, gcp_cloud_storage_bucket, gcp_cloud_storage_json_key, active, aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key) {
var update_file_repository = function (token, session_secret_key, file_repository_id, title, type,
gcp_cloud_storage_bucket, gcp_cloud_storage_json_key, active,
aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key,
do_space, do_region, do_key, do_secret) {
var endpoint = '/file-repository/';
var connection_type = "POST";
var data = {
......@@ -2380,7 +2398,11 @@
aws_s3_bucket: aws_s3_bucket,
aws_s3_region: aws_s3_region,
aws_s3_access_key_id: aws_s3_access_key_id,
aws_s3_secret_access_key: aws_s3_secret_access_key
aws_s3_secret_access_key: aws_s3_secret_access_key,
do_space: do_space,
do_region: do_region,
do_key: do_key,
do_secret: do_secret
};
var headers = {
......
(function(angular) {
'use strict';
/**
* @ngdoc service
* @name psonocli.apiDO
* @requires $http
* @requires $q
* @requires psonocli.converter
*
* @description
* Service to talk to the psono REST api
*/
var apiDO = function($http, $q, converter) {
var call = function(fileserver_url, connection_type, endpoint, data, headers, transformRequest, responseType) {
if (!transformRequest) {
transformRequest = $http.defaults.transformRequest;
}
var req = {
method: connection_type,
url: fileserver_url + endpoint,
data: data,
transformRequest: transformRequest,
responseType: responseType
};
req.headers = headers;
return $q(function(resolve, reject) {
var onSuccess = function(data) {
return resolve(data);
};
var onError = function(data) {
return reject(data);
};
$http(req)
.then(onSuccess, onError);
});
};
/**
* @ngdoc
* @name psonocli.apiDO#upload
* @methodOf psonocli.apiDO
*
* @description
* Ajax PUT request to upload a file chunk to AWS S3
*
* @param {string} signed_url The signed ulr
* @param {object} fields Array of fields that need to be part of the request
* @param {Blob} chunk The content of the chunk to upload
*
* @returns {promise} promise
*/
var upload = function (signed_url, fields, chunk) {
var endpoint = ''; // the signed url already has everything
var connection_type = "POST";
var data = new FormData();
for (var field_name in fields) {
if (!fields.hasOwnProperty(field_name)) {
continue;
}
data.append(field_name, fields[field_name]);
}
data.append('file', chunk);
var headers = {
'Content-Type': undefined
};
return call(signed_url, connection_type, endpoint, data, headers, angular.identity);
};
/**
* @ngdoc
* @name psonocli.apiDO#download
* @methodOf psonocli.apiDO
*
* @description
* Ajax GET request to download a file chunk from AWS S3
*
* @param {string} signed_url The signed ulr
*
* @returns {promise} promise with the data
*/
var download = function (signed_url) {
var endpoint = ''; // the signed url already has everything
var connection_type = "GET";
var data = null;
var headers = {
};
return call(signed_url, connection_type, endpoint, data, headers, undefined, 'arraybuffer').then(function(data) {
return data
},function(data) {
if (data.status === 400) {
data.data = JSON.parse(converter.bytes_to_string(data.data));
}
return $q.reject(data)
});
};
return {
upload: upload,
download: download
};
};
var app = angular.module('psonocli');
app.factory("apiDO", ['$http', '$q', 'converter', apiDO]);
}(angular));
......@@ -168,7 +168,8 @@
var get_possible_types = function() {
return [
{value: 'aws_s3', title: 'AWS S3'},
{value: 'gcp_cloud_storage', title: 'GCP Cloud Storage'}
{value: 'gcp_cloud_storage', title: 'GCP Cloud Storage'},
{value: 'do_spaces', title: 'Digital Ocean Spaces'}
];
};
......@@ -242,10 +243,17 @@
* @param {string} [aws_s3_region] (optional) The s3 region
* @param {string} [aws_s3_access_key_id] (optional) The s3 access key
* @param {string} [aws_s3_secret_access_key] (optional) The s3 secret key
* @param {string} [do_space] (optional) The digital ocean space
* @param {string} [do_region] (optional) The digital ocean region
* @param {string} [do_key] (optional) The digital ocean key
* @param {string} [do_secret] (optional) The digital ocean secret
*
* @returns {promise} Promise with the new id
*/
var create_file_repository = function(title, type, gcp_cloud_storage_bucket, gcp_cloud_storage_json_key, aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key) {
var create_file_repository = function(title, type,
gcp_cloud_storage_bucket, gcp_cloud_storage_json_key,
aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key,
do_space, do_region, do_key, do_secret) {
var onSuccess = function (result) {
var file_repository_id = result.data['file_repository_id'];
......@@ -267,7 +275,11 @@
aws_s3_bucket,
aws_s3_region,
aws_s3_access_key_id,
aws_s3_secret_access_key
aws_s3_secret_access_key,
do_space,
do_region,
do_key,
do_secret
)
.then(onSuccess, onError);
};
......@@ -289,12 +301,17 @@
* @param {string} [aws_s3_region] (optional) The s3 region
* @param {string} [aws_s3_access_key_id] (optional) The s3 access key
* @param {string} [aws_s3_secret_access_key] (optional) The s3 secret key
* @param {string} [do_space] (optional) The digital ocean space
* @param {string} [do_region] (optional) The digital ocean region
* @param {string} [do_key] (optional) The digital ocean key
* @param {string} [do_secret] (optional) The digital ocean secret
* @param {bool} active
*
* @returns {promise} Promise with the new id
*/
var update_file_repository = function(file_repository_id, title, type, gcp_cloud_storage_bucket, gcp_cloud_storage_json_key, active,
aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key) {
aws_s3_bucket, aws_s3_region, aws_s3_access_key_id, aws_s3_secret_access_key,
do_space, do_region, do_key, do_secret) {
return apiClient.update_file_repository(
managerBase.get_token(),
......@@ -308,7 +325,11 @@
aws_s3_bucket,
aws_s3_region,
aws_s3_access_key_id,
aws_s3_secret_access_key
aws_s3_secret_access_key,
do_space,
do_region,
do_key,
do_secret
)
};
......
......@@ -14,13 +14,14 @@
* @requires psonocli.apiClient
* @requires psonocli.apiFileserver
* @requires psonocli.apiGCP
* @requires psonocli.apiDO
* @requires psonocli.apiAWS
*
* @description
* Service to manage everything around file transfer
*/
var managerFileTransfer = function($q, helper, storage, managerBase, browserClient, cryptoLibrary , converter, apiClient, apiFileserver, apiGCP, apiAWS) {
var managerFileTransfer = function($q, helper, storage, managerBase, browserClient, cryptoLibrary , converter, apiClient, apiFileserver, apiGCP, apiDO, apiAWS) {
var registrations = {};
......@@ -221,6 +222,48 @@
};
/**
* @ngdoc
* @name psonocli.managerFileTransfer#upload_file_repository_do_spaces
* @methodOf psonocli.managerFileTransfer
*
* @description
* Triggered once someone wants to actually upload the file to Digital ocean spaces
*
* @param {Blob} chunk The content of the chunk to upload
* @param {uuid} file_transfer_id The id of the file transfer
* @param {string} file_transfer_secret_key The file transfer secret key
* @param {int} chunk_size The size of the complete chunk in bytes
* @param {int} chunk_position The sequence number of the chunk to determine the order
* @param {string} hash_checksum The sha512 hash
*
* @returns {promise} promise
*/
var upload_file_repository_do_spaces = function(chunk, file_transfer_id, file_transfer_secret_key, chunk_size, chunk_position, hash_checksum) {
var onError = function(result) {
return $q.reject(result.data)
};
var onSuccess = function(result) {
var onError = function(result) {
return $q.reject(result.data)
};
var onSuccess = function(result) {
return result;
};
return apiDO.upload(result.data.url, result.data.fields, chunk)
.then(onSuccess, onError);
};
return apiClient.file_repository_upload(file_transfer_id, file_transfer_secret_key, chunk_size, chunk_position, hash_checksum)
.then(onSuccess, onError);
};
/**
* @ngdoc
* @name psonocli.managerFileTransfer#upload
......@@ -246,6 +289,8 @@
return upload_shard(chunk, file_transfer_id, file_transfer_secret_key, chunk_position, shard, hash_checksum);
} else if (typeof(file_repository) !== 'undefined' && file_repository['type'] === 'gcp_cloud_storage') {
return upload_file_repository_gcp_cloud_storage(chunk, file_transfer_id, file_transfer_secret_key, chunk_size, chunk_position, hash_checksum);
} else if (typeof(file_repository) !== 'undefined' && file_repository['type'] === 'do_spaces') {
return upload_file_repository_do_spaces(chunk, file_transfer_id, file_transfer_secret_key, chunk_size, chunk_position, hash_checksum);
} else if (typeof(file_repository) !== 'undefined' && file_repository['type'] === 'aws_s3') {
return upload_file_repository_aws_s3(chunk, file_transfer_id, file_transfer_secret_key, chunk_size, chunk_position, hash_checksum);
}
......@@ -473,6 +518,9 @@
} else if(result.data.type === 'gcp_cloud_storage') {
return apiGCP.download(result.data.url)
.then(onSuccess, onError);
} else if(result.data.type === 'do_spaces') {
return apiDO.download(result.data.url)
.then(onSuccess, onError);
} else {
return $q.reject('UNKNOW_FILE_REPOSITORY_TYPE');
}
......@@ -715,6 +763,6 @@
};
var app = angular.module('psonocli');
app.factory("managerFileTransfer", ['$q', 'helper', 'storage', 'managerBase', 'browserClient', 'cryptoLibrary', 'converter', 'apiClient', 'apiFileserver', 'apiGCP', 'apiAWS', managerFileTransfer]);
app.factory("managerFileTransfer", ['$q', 'helper', 'storage', 'managerBase', 'browserClient', 'cryptoLibrary', 'converter', 'apiClient', 'apiFileserver', 'apiGCP', 'apiDO', 'apiAWS', managerFileTransfer]);
}(angular, saveAs));
\ No newline at end of file
......@@ -322,6 +322,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -334,6 +334,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -209,6 +209,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -435,6 +435,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -202,6 +202,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -295,6 +295,7 @@
<script src="js/service/api-client.js" type="application/javascript"></script>
<script src="js/service/api-gcp.js" type="application/javascript"></script>
<script src="js/service/api-do.js" type="application/javascript"></script>
<script src="js/service/api-aws.js" type="application/javascript"></script>
<script src="js/service/api-fileserver.js" type="application/javascript"></script>
<script src="js/service/api-pwnedpasswords.js" type="application/javascript"></script>
......
......@@ -289,6 +289,7 @@ self.addEventListener('install', function(event) {
'./js/service/api-client.js',
'./js/service/api-gcp.js',
'./js/service/api-do.js',
'./js/service/api-aws.js',
'./js/service/api-fileserver.js',
'./js/service/api-pwnedpasswords.js',
......
{
"SECRET": "Secret",
"SPACE": "Space",
"KEY_IS_REQUIRED": "Der Key ist erforderlich",
"SECRET_IS_REQUIRED": "Das Secret ist erforderlich",
"ACCOUNT_NOT_VERIFIED": "Account nicht verifiziert",
"USER_INACTIVE_OR_DELETED": "Benutzer inaktiv oder gelöscht",
"FILE_TRANSFER_INVALID": "Ungültiger Datei Transfer",
"UNKNOW_FILE_REPOSITORY_TYPE": "Unbekannter file repository typ",
"EITHER_SECRET_OR_FILE_REQUIRED_NOT_BOTH": "Entweder Secret oder Datei erforderlich. nicht beides",
"EITHER_SECRET_OR_FILE_REQUIRED": "Entweder Secret oder Datei erforderlich",
"ENTER_PASSPHRASE": "Geben sie ihre Passphrase ein:",
"ENTER_PASSPHRASE": "Geben sie die Passphrase ein:",
"PASSPHRASE_REQUIRED": "Passphrase erforderlich",
"VALID_TILL_CANNOT_BE_IN_THE_PAST": "'Gültig bis' kann nicht in der Vergangenheit liegen.",
"CHANGE_PASSPHRASE": "Passphrase editieren",
......@@ -67,6 +71,7 @@
"UNKNOWN_TYPE": "Unbekannter Typ",
"JSON_KEY_IS_INVALID": "JSON Key ist nicht korrekt",
"TYPE_IS_REQUIRED": "Typ ist erforderlich",
"SPACE_IS_REQUIRED": "Space ist erforderlich",
"BUCKET_IS_REQUIRED": "Bucket ist erforderlich",
"REGION_IS_REQUIRED": "Region ist erforderlich",
"REGION_IS_INVALID": "Region ist ungültig",
......
{
"SECRET": "Secret",
"SPACE": "Space",
"KEY_IS_REQUIRED": "The key is required",
"SECRET_IS_REQUIRED": "The secret is required",
"ACCOUNT_NOT_VERIFIED": "Account not verified",
"USER_INACTIVE_OR_DELETED": "User inactive or deleted",
"FILE_TRANSFER_INVALID": "File transfer invalid",
"UNKNOW_FILE_REPOSITORY_TYPE": "Unknown file repository type",
"EITHER_SECRET_OR_FILE_REQUIRED_NOT_BOTH": "Either secret or file required, not both",
"EITHER_SECRET_OR_FILE_REQUIRED": "Either secret or file required",
"ENTER_PASSPHRASE": "Enter your passphrase:",
"ENTER_PASSPHRASE": "Enter the passphrase:",
"PASSPHRASE_REQUIRED": "Passphrase required",
"VALID_TILL_CANNOT_BE_IN_THE_PAST": "'Valid till' cannot be in the past.",
"CHANGE_PASSPHRASE": "Change passphrase",
......@@ -67,6 +71,7 @@
"UNKNOWN_TYPE": "Unknown type",
"JSON_KEY_IS_INVALID": "JSON key is invalid",
"TYPE_IS_REQUIRED": "Type is required",
"SPACE_IS_REQUIRED": "Space is required",
"BUCKET_IS_REQUIRED": "Bucket is required",
"REGION_IS_REQUIRED": "Region is required",
"REGION_IS_INVALID": "Region is invalid",
......
......@@ -45,6 +45,22 @@
</div>
</div>
<div ng-if="selected_type === 'do_spaces'">
<div class="form-group">
<input type="text" name="do_space" class="form-control" id="do_space" placeholder="{{'SPACE' | translate}}" ng-model="storage_config.do_space">
</div>
<div class="form-group">
<input type="text" name="do_region" class="form-control" id="do_region" placeholder="{{'REGION' | translate}}" ng-model="storage_config.do_region">
</div>
<div class="form-group">
<input type="text" name="do_key" class="form-control" id="do_key" placeholder="{{'KEY' | translate}}" ng-model="storage_config.do_key">