KEYCLOAK-1866
Allow changing name and view details of imported realm
This commit is contained in:
parent
d08fca4e0a
commit
7ac1d1f14c
6 changed files with 70 additions and 116 deletions
|
@ -2036,3 +2036,26 @@ module.directive( 'kcOpen', function ( $location ) {
|
|||
});
|
||||
};
|
||||
});
|
||||
|
||||
module.directive('kcOnReadFile', function ($parse) {
|
||||
console.debug('kcOnReadFile');
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: false,
|
||||
link: function(scope, element, attrs) {
|
||||
var fn = $parse(attrs.kcOnReadFile);
|
||||
|
||||
element.on('change', function(onChangeEvent) {
|
||||
var reader = new FileReader();
|
||||
|
||||
reader.onload = function(onLoadEvent) {
|
||||
scope.$apply(function() {
|
||||
fn(scope, {$fileContent:onLoadEvent.target.result});
|
||||
});
|
||||
};
|
||||
|
||||
reader.readAsText((onChangeEvent.srcElement || onChangeEvent.target).files[0]);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
|
|
|
@ -155,7 +155,7 @@ module.controller('RealmDropdownCtrl', function($scope, Realm, Current, Auth, $l
|
|||
}
|
||||
});
|
||||
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, Dialog, Notifications, Auth) {
|
||||
module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $http, WhoAmI, $location, $route, Dialog, Notifications, Auth, $modal) {
|
||||
console.log('RealmCreateCtrl');
|
||||
|
||||
Current.realm = null;
|
||||
|
@ -169,55 +169,21 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
|
||||
var oldCopy = angular.copy($scope.realm);
|
||||
|
||||
$scope.onFileSelect = function($files) {
|
||||
$scope.files = $files;
|
||||
$scope.importFile = function($fileContent){
|
||||
$scope.realm = angular.copy(JSON.parse($fileContent));
|
||||
$scope.importing = true;
|
||||
};
|
||||
|
||||
$scope.clearFileSelect = function() {
|
||||
$scope.files = null;
|
||||
$scope.viewImportDetails = function() {
|
||||
$modal.open({
|
||||
templateUrl: resourceUrl + '/partials/modal/view-object.html',
|
||||
controller: 'ObjectModalCtrl',
|
||||
resolve: {
|
||||
object: function () {
|
||||
return $scope.realm;
|
||||
}
|
||||
|
||||
$scope.uploadFile = function() {
|
||||
//$files: an array of files selected, each file has name, size, and type.
|
||||
for (var i = 0; i < $scope.files.length; i++) {
|
||||
var $file = $scope.files[i];
|
||||
$scope.upload = $upload.upload({
|
||||
url: authUrl + '/admin/realms', //upload.php script, node.js route, or servlet url
|
||||
// method: POST or PUT,
|
||||
// headers: {'headerKey': 'headerValue'}, withCredential: true,
|
||||
data: {myObj: ""},
|
||||
file: $file
|
||||
/* set file formData name for 'Content-Desposition' header. Default: 'file' */
|
||||
//fileFormDataName: myFile,
|
||||
/* customize how data is added to formData. See #40#issuecomment-28612000 for example */
|
||||
//formDataAppender: function(formData, key, val){}
|
||||
}).progress(function(evt) {
|
||||
console.log('percent: ' + parseInt(100.0 * evt.loaded / evt.total));
|
||||
}).success(function(data, status, headers) {
|
||||
Realm.query(function(data) {
|
||||
Current.realms = data;
|
||||
|
||||
|
||||
WhoAmI.get(function(user) {
|
||||
Auth.user = user;
|
||||
|
||||
Notifications.success("The realm has been uploaded.");
|
||||
|
||||
var location = headers('Location');
|
||||
if (location) {
|
||||
$location.url("/realms/" + location.substring(location.lastIndexOf('/') + 1));
|
||||
} else {
|
||||
$location.url("/realms");
|
||||
}
|
||||
});
|
||||
});
|
||||
})
|
||||
.error(function() {
|
||||
Notifications.error("The realm can not be uploaded. Please verify the file.");
|
||||
|
||||
});
|
||||
//.then(success, error, progress);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.$watch('realm', function() {
|
||||
|
@ -226,6 +192,12 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
}
|
||||
}, true);
|
||||
|
||||
$scope.$watch('realm.realm', function() {
|
||||
if (create) {
|
||||
$scope.realm.id = $scope.realm.realm;
|
||||
}
|
||||
}, true);
|
||||
|
||||
$scope.save = function() {
|
||||
var realmCopy = angular.copy($scope.realm);
|
||||
Realm.create(realmCopy, function() {
|
||||
|
@ -243,10 +215,17 @@ module.controller('RealmCreateCtrl', function($scope, Current, Realm, $upload, $
|
|||
};
|
||||
|
||||
$scope.cancel = function() {
|
||||
window.history.back();
|
||||
$location.url("/");
|
||||
};
|
||||
|
||||
$scope.reset = function() {
|
||||
$route.reload();
|
||||
}
|
||||
});
|
||||
|
||||
module.controller('ObjectModalCtrl', function($scope, object) {
|
||||
$scope.object = object;
|
||||
});
|
||||
|
||||
module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, serverInfo, $http, $location, Dialog, Notifications, WhoAmI, Auth) {
|
||||
$scope.createRealm = !realm.realm;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
<div style="padding: 20px 20px 10px 20px">
|
||||
<pre ng-bind = "{{object}} | json"></pre>
|
||||
</div>
|
|
@ -1,29 +1,22 @@
|
|||
<div class="col-sm-9 col-md-10 col-sm-push-3 col-md-push-2">
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<legend><span class="text">Import Realm</span></legend>
|
||||
<div class="form-group">
|
||||
<label for="import-file" class="col-sm-2 control-label">Import JSON File </label>
|
||||
<div class="col-md-6">
|
||||
<div class="controls kc-button-input-file" data-ng-show="!files || files.length == 0">
|
||||
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
|
||||
<input id="import-file" type="file" class="hidden" ng-file-select="onFileSelect($files)">
|
||||
</div>
|
||||
<span class="kc-uploaded-file" data-ng-show="files.length > 0">{{files[0].name}}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-md-10 col-md-offset-2">
|
||||
<button type="submit" data-ng-disabled="files.length == 0" data-ng-click="uploadFile()" class="btn btn-primary">Upload</button>
|
||||
<button type="submit" data-ng-disabled="files.length == 0" data-ng-click="clearFileSelect()" class="btn btn-default">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<fieldset>
|
||||
<legend><span class="text">Create Realm</span></legend>
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">Import</label>
|
||||
|
||||
<div class="col-md-6" data-ng-hide="importing">
|
||||
<label for="import-file" class="btn btn-default">Select file <i class="pficon pficon-import"></i></label>
|
||||
<input id="import-file" type="file" class="hidden" kc-on-read-file="importFile($fileContent)">
|
||||
</div>
|
||||
|
||||
<div class="col-md-6" data-ng-show="importing">
|
||||
<button class="btn btn-default" data-ng-click="viewImportDetails()">View details</button>
|
||||
<button class="btn btn-default" data-ng-click="reset()">Clear import</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="name" class="col-sm-2 control-label">Name <span class="required">*</span></label>
|
||||
|
||||
|
@ -42,6 +35,7 @@
|
|||
<div class="form-group">
|
||||
<div class="col-md-10 col-md-offset-2">
|
||||
<button kc-save data-ng-disabled="!changed">Create</button>
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -111,7 +111,7 @@ public class RealmAdminResource {
|
|||
* @return
|
||||
*/
|
||||
@Path("attack-detection")
|
||||
public AttackDetectionResource getClientImporter() {
|
||||
public AttackDetectionResource getAttackDetection() {
|
||||
AttackDetectionResource resource = new AttackDetectionResource(auth, realm, adminEvent);
|
||||
ResteasyProviderFactory.getInstance().injectProperties(resource);
|
||||
return resource;
|
||||
|
|
|
@ -144,51 +144,6 @@ public class RealmsAdminResource {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Import a realm from uploaded JSON file
|
||||
*
|
||||
* The posted represenation is expected to be a multipart/form-data encapsulation
|
||||
* of a JSON file. The same format a browser would use when uploading a file.
|
||||
*
|
||||
* @param uriInfo
|
||||
* @param input multipart/form data
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public Response uploadRealm(@Context final UriInfo uriInfo, MultipartFormDataInput input) throws IOException {
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
realmManager.setContextPath(keycloak.getContextPath());
|
||||
if (!auth.getRealm().equals(realmManager.getKeycloakAdminstrationRealm())) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
if (!auth.hasRealmRole(AdminRoles.CREATE_REALM)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
|
||||
List<InputPart> inputParts = uploadForm.get("file");
|
||||
RealmRepresentation rep = null;
|
||||
|
||||
for (InputPart inputPart : inputParts) {
|
||||
// inputPart.getBody doesn't work as content-type is wrong, and inputPart.setMediaType is not supported on AS7 (RestEasy 2.3.2.Final)
|
||||
rep = JsonSerialization.readValue(inputPart.getBodyAsString(), RealmRepresentation.class);
|
||||
|
||||
RealmModel realm = realmManager.importRealm(rep);
|
||||
|
||||
grantPermissionsToRealmCreator(realm);
|
||||
|
||||
URI location = null;
|
||||
if (inputParts.size() == 1) {
|
||||
location = AdminRoot.realmsUrl(uriInfo).path(realm.getName()).build();
|
||||
return Response.created(location).build();
|
||||
}
|
||||
}
|
||||
|
||||
return Response.noContent().build();
|
||||
}
|
||||
|
||||
private void grantPermissionsToRealmCreator(RealmModel realm) {
|
||||
if (auth.hasRealmRole(AdminRoles.ADMIN)) {
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue