Merge pull request #244 from stianst/master
Added view roles, including updating console to make forms read-only
This commit is contained in:
commit
4ea7808d5f
38 changed files with 454 additions and 201 deletions
|
@ -521,6 +521,8 @@ module.factory('errorInterceptor', function($q, $window, $rootScope, $location,
|
|||
console.log('session timeout?');
|
||||
Auth.loggedIn = false;
|
||||
window.location = '/auth/rest/admin/login?path=' + $location.path();
|
||||
} else if (response.status == 403) {
|
||||
Notifications.error("Forbidden");
|
||||
} else if (response.status == 404) {
|
||||
Notifications.error("Not found");
|
||||
} else if (response.status) {
|
||||
|
@ -785,6 +787,7 @@ module.directive('kcReadOnly', function() {
|
|||
element.find('input').attr('disabled', 'disabled');
|
||||
element.find('button').attr('disabled', 'disabled');
|
||||
element.find('select').attr('disabled', 'disabled');
|
||||
element.find('textarea').attr('disabled', 'disabled');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -22,6 +22,22 @@ module.controller('GlobalCtrl', function($scope, $http, Auth, Current, $location
|
|||
$scope.access = {
|
||||
admin: data.admin,
|
||||
|
||||
get viewRealm() {
|
||||
return getAccess(Current.realm.realm, 'view-realm') || this.viewRealm;
|
||||
},
|
||||
|
||||
get viewApplications() {
|
||||
return getAccess(Current.realm.realm, 'view-applications') || this.manageApplications;
|
||||
},
|
||||
|
||||
get viewClients() {
|
||||
return getAccess(Current.realm.realm, 'view-clients') || this.manageClients;
|
||||
},
|
||||
|
||||
get viewUsers() {
|
||||
return getAccess(Current.realm.realm, 'view-users') || this.manageClients;
|
||||
},
|
||||
|
||||
get manageRealm() {
|
||||
return getAccess(Current.realm.realm, 'manage-realm');
|
||||
},
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<li class="active">Credentials</li>
|
||||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{application.name}}</span> Credentials</h2>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageApplications">
|
||||
<fieldset >
|
||||
<legend><span class="text">Client Secret</span></legend>
|
||||
<div class="form-group">
|
||||
|
@ -27,7 +27,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageApplications">
|
||||
<button type="submit" data-ng-click="changePassword()" class="btn btn-primary btn-lg">Regenerate Secret
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<li class="active">Settings</li>
|
||||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{application.name}}</span> Settings</h2>
|
||||
<form class="form-horizontal" name="applicationForm" novalidate>
|
||||
<form class="form-horizontal" name="applicationForm" novalidate kc-read-only="!access.manageApplications">
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="name">Name <span class="required" data-ng-show="create">*</span></label>
|
||||
|
@ -108,11 +108,11 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="create">
|
||||
<div class="pull-right form-actions" data-ng-show="create && access.manageApplications">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
<div class="pull-right form-actions" data-ng-show="!create">
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageApplications">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<h2 data-ng-hide="create"><span>{{application.name}}</span> {{role.name}}</h2>
|
||||
<h2 data-ng-show="create"><span>{{application.name}}</span> Add Role</h2>
|
||||
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageApplications">
|
||||
<span class="fieldset-notice"><span class="required">*</span> Required fields</span>
|
||||
|
||||
<fieldset class="border-top">
|
||||
|
@ -134,11 +134,11 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="create">
|
||||
<div class="pull-right form-actions" data-ng-show="create && access.manageApplications">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
<div class="pull-right form-actions" data-ng-show="!create">
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageApplications">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="kc-table-actions" colspan="3">
|
||||
<th class="kc-table-actions" colspan="3" data-ng-show="access.manageApplications">
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-primary" href="#/create/role/{{realm.realm}}/applications/{{application.name}}">Add Role</a>
|
||||
<!-- <button class="remove disabled">Remove</button> -->
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
</ol>
|
||||
<h2><span>{{application.name}}</span> Scope Mappings</h2>
|
||||
<p class="subtitle"></p>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageApplications">
|
||||
<fieldset>
|
||||
<legend><span class="text">Realm Roles</span></legend>
|
||||
<div class="form-group col-sm-10">
|
||||
|
@ -59,7 +59,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in (applications|remove:application:'id')">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in (applications|remove:application:'id')" ng-disabled="false">
|
||||
<option value="" selected> Select an Application </option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<li class="active">Credentials</li>
|
||||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{oauth.name}}</span> Credentials</h2>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate>
|
||||
<form class="form-horizontal" name="credentialForm" novalidate kc-read-only="!access.manageClients">
|
||||
<fieldset >
|
||||
<legend><span class="text">Client Secret</span></legend>
|
||||
<div class="form-group">
|
||||
|
@ -26,7 +26,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageClients">
|
||||
<button type="submit" data-ng-click="changePassword()" class="btn btn-primary btn-lg">Regenerate Secret
|
||||
</button>
|
||||
</div>
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
<li class="active">Settings</li>
|
||||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{oauth.name}}</span> Settings</h2>
|
||||
<form class="form-horizontal" name="oauthForm" novalidate>
|
||||
<form class="form-horizontal" name="oauthForm" novalidate kc-read-only="!access.manageClients">
|
||||
<fieldset class="border-top">
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -90,11 +90,11 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="create">
|
||||
<div class="pull-right form-actions" data-ng-show="create && access.manageClients">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
<div class="pull-right form-actions" data-ng-show="!create">
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageClients">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</ol>
|
||||
<h2><span>{{oauth.name}}</span> Scope Mappings</h2>
|
||||
<p class="subtitle"></p>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageClients">
|
||||
<fieldset>
|
||||
<legend><span class="text">Realm Roles</span></legend>
|
||||
<div class="form-group col-sm-10">
|
||||
|
@ -57,7 +57,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in (applications)">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="targetApp" ng-options="a.name for a in (applications)" ng-disabled="false">
|
||||
<option value="" selected> Select an Application </option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
<li class="active">Required Credentials</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Credentials</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset class="border-top">
|
||||
<legend uncollapsed><span class="text">Realm Credentials Settings</span></legend>
|
||||
<legend><span class="text">Realm Credentials Settings</span></legend>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="user" class="control-label two-lines">Required User Credentials</label>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
<fieldset class="border-top">
|
||||
<legend uncollapsed><span class="text">Realm Password Policy</span></legend>
|
||||
<legend><span class="text">Realm Password Policy</span></legend>
|
||||
<table class="table">
|
||||
<caption class="hidden">Table of Password Policies</caption>
|
||||
<thead>
|
||||
|
@ -63,7 +63,7 @@
|
|||
</tbody>
|
||||
</table>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<li class="active">Registration</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Default Roles</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset>
|
||||
<legend><span class="text">Realm Default Roles</span> </legend>
|
||||
<div class="form-group">
|
||||
|
@ -48,7 +48,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications" ng-disabled="false">
|
||||
<option value="" selected> Select an Application...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
<li><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
<li class="active">General</li>
|
||||
</ol>
|
||||
<div data-ng-show="access.manageRealm">
|
||||
<div data-ng-show="access.viewRealm">
|
||||
<h2 class="pull-left" data-ng-show="createRealm">Add Realm</h2>
|
||||
<h2 data-ng-hide="createRealm"><span>{{realm.realm}}</span> General Settings</h2>
|
||||
<p class="subtitle" data-ng-show="createRealm"><span class="required">*</span> Required fields</p>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset>
|
||||
<legend class="aj-collapse open"><span class="text">Required Settings</span></legend>
|
||||
<div class="form-group">
|
||||
|
@ -91,18 +91,18 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="createRealm">
|
||||
<div class="pull-right form-actions" data-ng-show="createRealm && access.manageRealm">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
<div class="pull-right form-actions" data-ng-show="!createRealm">
|
||||
<div class="pull-right form-actions" data-ng-show="!createRealm && access.manageRealm">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div data-ng-hide="access.manageRealm">
|
||||
<div data-ng-hide="access.viewRealm">
|
||||
<h2 ><span>{{realm.realm}}</span></h2>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<li class="active">Keys</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Keys</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="publicKey">Public key</label>
|
||||
|
@ -19,7 +19,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
||||
<button class="btn btn-primary btn-lg" type="submit" data-ng-click="generate()">Generate new keys</button>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<ul data-ng-hide="createRealm">
|
||||
<li data-ng-show="access.manageRealm" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
|
||||
<li data-ng-show="access.viewRealm" data-ng-class="((!path[2] || path[1] == 'role' || path[2] == 'roles' || path[2] == 'token-settings' ||
|
||||
path[2] == 'social-settings' || path[2] == 'required-credentials' || path[2] == 'default-roles' || path[2] == 'registration-settings' ||
|
||||
path[2] == 'keys-settings' || path[2] == 'smtp-settings') && path[3] != 'applications') && 'active'"><a href="#/realms/{{realm.realm}}">Settings</a></li>
|
||||
<li data-ng-show="access.manageUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
|
||||
<li data-ng-show="access.viewUsers" data-ng-class="(path[2] == 'users' || path[1] == 'user') && 'active'"><a href="#/realms/{{realm.realm}}/users">Users</a>
|
||||
</li>
|
||||
<li data-ng-show="access.manageApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
||||
<li data-ng-show="access.manageClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
|
||||
<li data-ng-show="access.viewApplications" data-ng-class="(path[2] == 'applications' || path[1] == 'application' || path[3] == 'applications') && 'active'"><a href="#/realms/{{realm.realm}}/applications">Applications</a></li>
|
||||
<li data-ng-show="access.viewClients" data-ng-class="(path[2] == 'oauth-clients' || path[1] == 'oauth-client') && 'active'"><a href="#/realms/{{realm.realm}}/oauth-clients">OAuth Clients</a></li>
|
||||
</ul>
|
|
@ -8,10 +8,10 @@
|
|||
<li class="active">SMTP Configuration</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Email Server Settings</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<span class="fieldset-notice"><span class="required">*</span> Required fields</span>
|
||||
<fieldset>
|
||||
<legend uncollapsed><span class="text">Required Settings</span></legend>
|
||||
<legend><span class="text">Required Settings</span></legend>
|
||||
<div class="form-group clearfix">
|
||||
<label class="col-sm-2 control-label" for="smtpHost">Host <span class="required">*</span></label>
|
||||
<div class="col-sm-4">
|
||||
|
@ -44,7 +44,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend uncollapsed><span class="text">Authentication</span></legend>
|
||||
<legend><span class="text">Authentication</span></legend>
|
||||
<div class="form-group clearfix">
|
||||
<label class="col-sm-2 control-label" for="smtpAuth">Enable Authentication</label>
|
||||
<div class="col-sm-4">
|
||||
|
@ -65,7 +65,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
||||
<button data-kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button data-kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<li class="active">Token</li>
|
||||
</ol>
|
||||
<h2><span>{{realm.realm}}</span> Token Settings</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="rememberMe">Remember Me</label>
|
||||
|
@ -113,7 +113,7 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions">
|
||||
<div class="pull-right form-actions" data-ng-show="access.manageRealm">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
</ol>
|
||||
<h2 data-ng-show="create"><span>{{realm.realm}}</span> Add Role</h2>
|
||||
<p class="subtitle" data-ng-show="create"><span class="required">*</span> Required fields</p>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageRealm">
|
||||
<fieldset>
|
||||
<div class="form-group">
|
||||
<label class="col-sm-2 control-label" for="name">Role name <span class="required" data-ng-show="create">*</span></label>
|
||||
|
@ -96,7 +96,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="compositeApp" ng-options="a.name for a in applications">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="compositeApp" ng-options="a.name for a in applications" ng-disabled="false">
|
||||
<option value="" selected> Select an Application...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -133,7 +133,7 @@
|
|||
</div>
|
||||
</fieldset>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="!create">
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageRealm">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="kc-table-actions" colspan="3">
|
||||
<th class="kc-table-actions" colspan="3" data-ng-show="access.manageRealm">
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-primary" href="#/create/role/{{realm.realm}}">Add Role</a>
|
||||
<!-- <button class="remove disabled">Remove</button> -->
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<div id="content-area" class="col-md-9" role="main">
|
||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}">Attributes</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}/user-credentials">Credentials</a></li>
|
||||
<li data-ng-show="access.manageUsers"><a href="#/realms/{{realm.realm}}/users/{{user.username}}/user-credentials">Credentials</a></li>
|
||||
<li class="active"><a href="#/realms/{{realm.realm}}/users/{{user.username}}/role-mappings">Role Mappings</a></li>
|
||||
</ul>
|
||||
<div id="content">
|
||||
|
@ -13,7 +13,7 @@
|
|||
<li class="active">Role Mappings</li>
|
||||
</ol>
|
||||
<h2><span>{{user.username}}'s</span> Role Mappings</h2>
|
||||
<form class="form-horizontal" name="realmForm" novalidate>
|
||||
<form class="form-horizontal" name="realmForm" novalidate kc-read-only="!access.manageUsers">
|
||||
|
||||
<fieldset>
|
||||
<legend><span class="text">Realm Roles</span> </legend>
|
||||
|
@ -54,7 +54,7 @@
|
|||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="select-kc">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications">
|
||||
<select id="applications" name="applications" ng-change="changeApplication()" ng-model="application" ng-options="a.name for a in applications" ng-disabled="false">
|
||||
<option value="" selected> Select an Application...</option>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<ul class="nav nav-tabs nav-tabs-pf" data-ng-show="!create">
|
||||
<li class="active"><a href="#/realms/{{realm.realm}}/users/{{user.username}}">Attributes</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}/user-credentials">Credentials</a></li>
|
||||
<li data-ng-show="access.manageUsers"><a href="#/realms/{{realm.realm}}/users/{{user.username}}/user-credentials">Credentials</a></li>
|
||||
<li><a href="#/realms/{{realm.realm}}/users/{{user.username}}/role-mappings">Role Mappings</a></li>
|
||||
</ul>
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
|||
</ol>
|
||||
<h2 data-ng-hide="create"><span>{{user.username}}'s</span> Attributes</h2>
|
||||
|
||||
<form class="form-horizontal" name="userForm" novalidate>
|
||||
<form class="form-horizontal" name="userForm" novalidate kc-read-only="!access.manageUsers">
|
||||
<span class="fieldset-notice"><span class="required">*</span> Required fields</span>
|
||||
<fieldset class="border-top">
|
||||
<div class="form-group">
|
||||
|
@ -79,12 +79,12 @@
|
|||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="pull-right form-actions" data-ng-show="create">
|
||||
<div class="pull-right form-actions" data-ng-show="create && access.manageUsers">
|
||||
<button kc-cancel data-ng-click="cancel()">Cancel</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
</div>
|
||||
|
||||
<div class="pull-right form-actions" data-ng-show="!create">
|
||||
<div class="pull-right form-actions" data-ng-show="!create && access.manageUsers">
|
||||
<button kc-reset data-ng-show="changed">Clear changes</button>
|
||||
<button kc-save data-ng-show="changed">Save</button>
|
||||
<button kc-delete data-ng-click="remove()" data-ng-hide="changed">Delete</button>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<ul class="nav nav-tabs nav-tabs-pf">
|
||||
<li ng-class="{active: !path[2]}"><a href="#/realms/{{realm.realm}}">General</a></li>
|
||||
<li ng-class="{active: path[2] == 'social'}" data-ng-show="kcSocial && auth.hasAccess(realm.realm, 'manage-realm')"><a href="#/realms/{{realm.realm}}/social-settings">Social</a></li>
|
||||
<li ng-class="{active: path[2] == 'roles'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
|
||||
<li ng-class="{active: path[2] == 'default-roles'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
|
||||
<li ng-class="{active: path[2] == 'required-credentials'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/required-credentials">Credentials</a></li>
|
||||
<li ng-class="{active: path[2] == 'token-settings'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/token-settings">Token</a></li>
|
||||
<li ng-class="{active: path[2] == 'keys-settings'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/keys-settings">Keys</a></li>
|
||||
<li ng-class="{active: path[2] == 'smtp-settings'}" data-ng-show="access.manageRealm"><a href="#/realms/{{realm.realm}}/smtp-settings">Email</a></li>
|
||||
<li ng-class="{active: path[2] == 'social'}" data-ng-show="kcSocial && access.viewRealm"><a href="#/realms/{{realm.realm}}/social-settings">Social</a></li>
|
||||
<li ng-class="{active: path[2] == 'roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
|
||||
<li ng-class="{active: path[2] == 'default-roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
|
||||
<li ng-class="{active: path[2] == 'required-credentials'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/required-credentials">Credentials</a></li>
|
||||
<li ng-class="{active: path[2] == 'token-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/token-settings">Token</a></li>
|
||||
<li ng-class="{active: path[2] == 'keys-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/keys-settings">Keys</a></li>
|
||||
<li ng-class="{active: path[2] == 'smtp-settings'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/smtp-settings">Email</a></li>
|
||||
</ul>
|
|
@ -9,12 +9,17 @@ public class AdminRoles {
|
|||
|
||||
public static String ADMIN = "admin";
|
||||
|
||||
public static String VIEW_REALM = "view-realm";
|
||||
public static String VIEW_USERS = "view-users";
|
||||
public static String VIEW_APPLICATIONS = "view-applications";
|
||||
public static String VIEW_CLIENTS = "view-clients";
|
||||
|
||||
public static String MANAGE_REALM = "manage-realm";
|
||||
public static String MANAGE_USERS = "manage-users";
|
||||
public static String MANAGE_APPLICATIONS = "manage-applications";
|
||||
public static String MANAGE_CLIENTS = "manage-clients";
|
||||
|
||||
public static String[] ALL_REALM_ROLES = {MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS};
|
||||
public static String[] ALL_REALM_ROLES = {VIEW_REALM, VIEW_USERS, VIEW_APPLICATIONS, VIEW_CLIENTS, MANAGE_REALM, MANAGE_USERS, MANAGE_APPLICATIONS, MANAGE_CLIENTS};
|
||||
|
||||
public static String getAdminApp(RealmModel realm) {
|
||||
return realm.getName() + APP_SUFFIX;
|
||||
|
|
|
@ -1,23 +1,14 @@
|
|||
package org.keycloak.services.managers;
|
||||
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
|
||||
import javax.ws.rs.ForbiddenException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class Auth {
|
||||
|
||||
private final boolean cookie;
|
||||
private final RealmModel realm;
|
||||
private final AccessToken token;
|
||||
|
@ -62,45 +53,25 @@ public class Auth {
|
|||
return token;
|
||||
}
|
||||
|
||||
public void require(String role) {
|
||||
if (!has(role)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void require(String app, String role) {
|
||||
if (!has(app, role)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void require(ApplicationModel app, String role) {
|
||||
if (!has(app, role)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireOneOf(String app, String... roles) {
|
||||
if(!hasOneOf(app, roles)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireOneOf(ApplicationModel app, String... roles) {
|
||||
if(!hasOneOf(app, roles)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(String role) {
|
||||
public boolean hasRealmRole(String role) {
|
||||
if (cookie) {
|
||||
return realm.hasRole(user, realm.getRole(role));
|
||||
} else {
|
||||
return token.getRealmAccess() != null && token.getRealmAccess().isUserInRole(role);
|
||||
AccessToken.Access access = token.getRealmAccess();
|
||||
return access != null && access.isUserInRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean has(String app, String role) {
|
||||
public boolean hasOneOfRealmRole(String... roles) {
|
||||
for (String r : roles) {
|
||||
if (hasRealmRole(r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasAppRole(String app, String role) {
|
||||
if (cookie) {
|
||||
return realm.hasRole(user, realm.getApplicationByName(app).getRole(role));
|
||||
} else {
|
||||
|
@ -109,30 +80,13 @@ public class Auth {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean has(ApplicationModel app, String role) {
|
||||
if (cookie) {
|
||||
return realm.hasRole(user, app.getRole(role));
|
||||
} else {
|
||||
AccessToken.Access access = token.getResourceAccess(app.getName());
|
||||
return access != null && access.isUserInRole(role);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasOneOf(String app, String... roles) {
|
||||
public boolean hasOneOfAppRole(String app, String... roles) {
|
||||
for (String r : roles) {
|
||||
if (has(app, r)) {
|
||||
if (hasAppRole(app, r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean hasOneOf(ApplicationModel app, String... roles) {
|
||||
for (String r : roles) {
|
||||
if (has(app, r)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -81,7 +81,7 @@ public class AccountService {
|
|||
Auth auth = getAuth(false);
|
||||
if (auth != null) {
|
||||
try {
|
||||
auth.require(application, AccountRoles.MANAGE_ACCOUNT);
|
||||
require(auth, AccountRoles.MANAGE_ACCOUNT);
|
||||
} catch (ForbiddenException e) {
|
||||
return Flows.forms(realm, request, uriInfo).setError("No access").createErrorPage();
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ public class AccountService {
|
|||
return forwardToPage(null, AccountPages.ACCOUNT);
|
||||
} else if (types.contains(MediaType.APPLICATION_JSON_TYPE)) {
|
||||
Auth auth = getAuth(true);
|
||||
auth.requireOneOf(application, AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
|
||||
requireOneOf(auth, AccountRoles.MANAGE_ACCOUNT, AccountRoles.VIEW_PROFILE);
|
||||
|
||||
return Cors.add(request, Response.ok(ModelToRepresentation.toRepresentation(auth.getUser()))).auth().allowedOrigins(auth.getClient()).build();
|
||||
} else {
|
||||
|
@ -138,7 +138,7 @@ public class AccountService {
|
|||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processAccountUpdate(final MultivaluedMap<String, String> formData) {
|
||||
Auth auth = getAuth(true);
|
||||
auth.require(application, AccountRoles.MANAGE_ACCOUNT);
|
||||
require(auth, AccountRoles.MANAGE_ACCOUNT);
|
||||
|
||||
UserModel user = auth.getUser();
|
||||
|
||||
|
@ -160,7 +160,7 @@ public class AccountService {
|
|||
@GET
|
||||
public Response processTotpRemove() {
|
||||
Auth auth = getAuth(true);
|
||||
auth.require(application, AccountRoles.MANAGE_ACCOUNT);
|
||||
require(auth, AccountRoles.MANAGE_ACCOUNT);
|
||||
|
||||
UserModel user = auth.getUser();
|
||||
user.setTotp(false);
|
||||
|
@ -174,7 +174,7 @@ public class AccountService {
|
|||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processTotpUpdate(final MultivaluedMap<String, String> formData) {
|
||||
Auth auth = getAuth(true);
|
||||
auth.require(application, AccountRoles.MANAGE_ACCOUNT);
|
||||
require(auth, AccountRoles.MANAGE_ACCOUNT);
|
||||
|
||||
UserModel user = auth.getUser();
|
||||
|
||||
|
@ -204,7 +204,7 @@ public class AccountService {
|
|||
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
|
||||
public Response processPasswordUpdate(final MultivaluedMap<String, String> formData) {
|
||||
Auth auth = getAuth(true);
|
||||
auth.require(application, AccountRoles.MANAGE_ACCOUNT);
|
||||
require(auth, AccountRoles.MANAGE_ACCOUNT);
|
||||
|
||||
UserModel user = auth.getUser();
|
||||
|
||||
|
@ -345,4 +345,16 @@ public class AccountService {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void require(Auth auth, String role) {
|
||||
if (!auth.hasAppRole(application.getName(), role)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireOneOf(Auth auth, String... roles) {
|
||||
if (!auth.hasOneOfAppRole(application.getName(), roles)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -234,6 +234,7 @@ public class AdminService {
|
|||
if (auth == null) {
|
||||
throw new NotAuthorizedException("Bearer");
|
||||
}
|
||||
|
||||
RealmsAdminResource adminResource = new RealmsAdminResource(auth, tokenManager);
|
||||
resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
|
|
|
@ -34,9 +34,10 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ApplicationResource extends RoleContainerResource {
|
||||
public class ApplicationResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected RealmModel realm;
|
||||
private RealmAuth auth;
|
||||
protected ApplicationModel application;
|
||||
protected KeycloakSession session;
|
||||
@Context
|
||||
|
@ -49,16 +50,20 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
return (KeycloakApplication)keycloak;
|
||||
}
|
||||
|
||||
public ApplicationResource(RealmModel realm, ApplicationModel applicationModel, KeycloakSession session) {
|
||||
super(realm, applicationModel);
|
||||
public ApplicationResource(RealmModel realm, RealmAuth auth, ApplicationModel applicationModel, KeycloakSession session) {
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
this.application = applicationModel;
|
||||
this.session = session;
|
||||
|
||||
auth.init(RealmAuth.Resource.APPLICATION);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void update(final ApplicationRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
applicationManager.updateApplication(rep, application);
|
||||
}
|
||||
|
@ -68,6 +73,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public ApplicationRepresentation getApplication() {
|
||||
auth.requireView();
|
||||
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
return applicationManager.toRepresentation(application);
|
||||
}
|
||||
|
@ -78,6 +85,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Path("installation/json")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String getInstallation() throws IOException {
|
||||
auth.requireView();
|
||||
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
Object rep = applicationManager.toInstallationRepresentation(realm, application, getKeycloakApplication().getBaseUri(uriInfo));
|
||||
|
||||
|
@ -90,6 +99,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Path("installation/jboss")
|
||||
@Produces(MediaType.TEXT_PLAIN)
|
||||
public String getJBossInstallation() throws IOException {
|
||||
auth.requireView();
|
||||
|
||||
ApplicationManager applicationManager = new ApplicationManager(new RealmManager(session));
|
||||
return applicationManager.toJBossSubsystemConfig(realm, application, getKeycloakApplication().getBaseUri(uriInfo));
|
||||
}
|
||||
|
@ -97,6 +108,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@DELETE
|
||||
@NoCache
|
||||
public void deleteApplication() {
|
||||
auth.requireManage();
|
||||
|
||||
realm.removeApplication(application.getId());
|
||||
}
|
||||
|
||||
|
@ -105,6 +118,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Produces("application/json")
|
||||
@Consumes("application/json")
|
||||
public CredentialRepresentation regenerateSecret() {
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("regenerateSecret");
|
||||
UserCredentialModel cred = new ApplicationManager().generateSecret(realm, application);
|
||||
CredentialRepresentation rep = ModelToRepresentation.toRepresentation(cred);
|
||||
|
@ -115,6 +130,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@GET
|
||||
@Produces("application/json")
|
||||
public CredentialRepresentation getClientSecret() {
|
||||
auth.requireView();
|
||||
|
||||
logger.debug("getClientSecret");
|
||||
UserCredentialModel model = realm.getSecret(application.getApplicationUser());
|
||||
if (model == null) throw new NotFoundException("Application does not have a secret");
|
||||
|
@ -124,7 +141,12 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
|
||||
@Path("scope-mappings")
|
||||
public ScopeMappedResource getScopeMappedResource() {
|
||||
return new ScopeMappedResource(realm, application.getApplicationUser(), session);
|
||||
return new ScopeMappedResource(realm, auth, application.getApplicationUser(), session);
|
||||
}
|
||||
|
||||
@Path("roles")
|
||||
public RoleContainerResource getRoleContainerResource() {
|
||||
return new RoleContainerResource(realm, auth, application);
|
||||
}
|
||||
|
||||
@Path("allowed-origins")
|
||||
|
@ -132,6 +154,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Produces("application/json")
|
||||
public Set<String> getAllowedOrigins()
|
||||
{
|
||||
auth.requireView();
|
||||
|
||||
return application.getApplicationUser().getWebOrigins();
|
||||
}
|
||||
|
||||
|
@ -140,6 +164,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Consumes("application/json")
|
||||
public void updateAllowedOrigins(Set<String> allowedOrigins)
|
||||
{
|
||||
auth.requireManage();
|
||||
|
||||
application.getApplicationUser().setWebOrigins(allowedOrigins);
|
||||
}
|
||||
|
||||
|
@ -148,6 +174,8 @@ public class ApplicationResource extends RoleContainerResource {
|
|||
@Consumes("application/json")
|
||||
public void deleteAllowedOrigins(Set<String> allowedOrigins)
|
||||
{
|
||||
auth.requireManage();
|
||||
|
||||
for (String origin : allowedOrigins) {
|
||||
application.getApplicationUser().removeWebOrigin(origin);
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import java.util.List;
|
|||
public class ApplicationsResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected RealmModel realm;
|
||||
private RealmAuth auth;
|
||||
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
|
@ -39,19 +40,32 @@ public class ApplicationsResource {
|
|||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
public ApplicationsResource(RealmModel realm) {
|
||||
public ApplicationsResource(RealmModel realm, RealmAuth auth) {
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
|
||||
auth.init(RealmAuth.Resource.APPLICATION);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
@NoCache
|
||||
public List<ApplicationRepresentation> getApplications() {
|
||||
auth.requireAny();
|
||||
|
||||
List<ApplicationRepresentation> rep = new ArrayList<ApplicationRepresentation>();
|
||||
List<ApplicationModel> applicationModels = realm.getApplications();
|
||||
ApplicationManager resourceManager = new ApplicationManager(new RealmManager(session));
|
||||
|
||||
boolean view = auth.hasView();
|
||||
for (ApplicationModel applicationModel : applicationModels) {
|
||||
if (view) {
|
||||
rep.add(resourceManager.toRepresentation(applicationModel));
|
||||
} else {
|
||||
ApplicationRepresentation app = new ApplicationRepresentation();
|
||||
app.setName(applicationModel.getName());
|
||||
rep.add(app);
|
||||
}
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
@ -59,6 +73,8 @@ public class ApplicationsResource {
|
|||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response createApplication(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
if (realm.getApplicationNameMap().containsKey(rep.getName())) {
|
||||
return Flows.errors().exists("Application " + rep.getName() + " already exists");
|
||||
}
|
||||
|
@ -73,7 +89,7 @@ public class ApplicationsResource {
|
|||
if (applicationModel == null) {
|
||||
throw new NotFoundException("Could not find application: " + name);
|
||||
}
|
||||
ApplicationResource applicationResource = new ApplicationResource(realm, applicationModel, session);
|
||||
ApplicationResource applicationResource = new ApplicationResource(realm, auth, applicationModel, session);
|
||||
resourceContext.initResource(applicationResource);
|
||||
return applicationResource;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import java.util.List;
|
|||
public class OAuthClientResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected RealmModel realm;
|
||||
private RealmAuth auth;
|
||||
protected OAuthClientModel oauthClient;
|
||||
protected KeycloakSession session;
|
||||
@Context
|
||||
|
@ -50,15 +51,20 @@ public class OAuthClientResource {
|
|||
return (KeycloakApplication)application;
|
||||
}
|
||||
|
||||
public OAuthClientResource(RealmModel realm, OAuthClientModel oauthClient, KeycloakSession session) {
|
||||
public OAuthClientResource(RealmModel realm, RealmAuth auth, OAuthClientModel oauthClient, KeycloakSession session) {
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
this.oauthClient = oauthClient;
|
||||
this.session = session;
|
||||
|
||||
auth.init(RealmAuth.Resource.CLIENT);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void update(final OAuthClientRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
OAuthClientManager manager = new OAuthClientManager(realm);
|
||||
manager.update(rep, oauthClient);
|
||||
}
|
||||
|
@ -68,6 +74,8 @@ public class OAuthClientResource {
|
|||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public OAuthClientRepresentation getOAuthClient() {
|
||||
auth.requireView();
|
||||
|
||||
return OAuthClientManager.toRepresentation(oauthClient);
|
||||
}
|
||||
|
||||
|
@ -76,6 +84,8 @@ public class OAuthClientResource {
|
|||
@Path("installation")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public String getInstallation() throws IOException {
|
||||
auth.requireView();
|
||||
|
||||
OAuthClientManager manager = new OAuthClientManager(realm);
|
||||
Object rep = manager.toInstallationRepresentation(realm, oauthClient, getApplication().getBaseUri(uriInfo));
|
||||
|
||||
|
@ -86,6 +96,8 @@ public class OAuthClientResource {
|
|||
@DELETE
|
||||
@NoCache
|
||||
public void deleteOAuthClient() {
|
||||
auth.requireManage();
|
||||
|
||||
realm.removeOAuthClient(oauthClient.getId());
|
||||
}
|
||||
|
||||
|
@ -94,6 +106,8 @@ public class OAuthClientResource {
|
|||
@Produces("application/json")
|
||||
@Consumes("application/json")
|
||||
public CredentialRepresentation regenerateSecret() {
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("regenerateSecret");
|
||||
UserCredentialModel cred = UserCredentialModel.generateSecret();
|
||||
realm.updateCredential(oauthClient.getOAuthAgent(), cred);
|
||||
|
@ -105,6 +119,8 @@ public class OAuthClientResource {
|
|||
@GET
|
||||
@Produces("application/json")
|
||||
public CredentialRepresentation getClientSecret() {
|
||||
auth.requireView();
|
||||
|
||||
logger.debug("getClientSecret");
|
||||
UserCredentialModel model = realm.getSecret(oauthClient.getOAuthAgent());
|
||||
if (model == null) throw new NotFoundException("Application does not have a secret");
|
||||
|
@ -113,7 +129,7 @@ public class OAuthClientResource {
|
|||
|
||||
@Path("scope-mappings")
|
||||
public ScopeMappedResource getScopeMappedResource() {
|
||||
return new ScopeMappedResource(realm, oauthClient.getOAuthAgent(), session);
|
||||
return new ScopeMappedResource(realm, auth, oauthClient.getOAuthAgent(), session);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,10 +35,14 @@ public class OAuthClientsResource {
|
|||
|
||||
@Context
|
||||
protected ResourceContext resourceContext;
|
||||
private RealmAuth auth;
|
||||
|
||||
public OAuthClientsResource(RealmModel realm, KeycloakSession session) {
|
||||
public OAuthClientsResource(RealmModel realm, RealmAuth auth, KeycloakSession session) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
this.session = session;
|
||||
|
||||
auth.init(RealmAuth.Resource.CLIENT);
|
||||
}
|
||||
|
||||
@GET
|
||||
|
@ -47,8 +51,16 @@ public class OAuthClientsResource {
|
|||
public List<OAuthClientRepresentation> getOAuthClients() {
|
||||
List<OAuthClientRepresentation> rep = new ArrayList<OAuthClientRepresentation>();
|
||||
List<OAuthClientModel> oauthModels = realm.getOAuthClients();
|
||||
|
||||
boolean view = auth.hasView();
|
||||
for (OAuthClientModel oauth : oauthModels) {
|
||||
if (view) {
|
||||
rep.add(OAuthClientManager.toRepresentation(oauth));
|
||||
} else {
|
||||
OAuthClientRepresentation client = new OAuthClientRepresentation();
|
||||
client.setName(oauth.getOAuthAgent().getLoginName());
|
||||
rep.add(client);
|
||||
}
|
||||
}
|
||||
return rep;
|
||||
}
|
||||
|
@ -56,6 +68,8 @@ public class OAuthClientsResource {
|
|||
@POST
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response createOAuthClient(final @Context UriInfo uriInfo, final OAuthClientRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
OAuthClientManager resourceManager = new OAuthClientManager(realm);
|
||||
OAuthClientModel oauth = resourceManager.create(rep);
|
||||
return Response.created(uriInfo.getAbsolutePathBuilder().path(oauth.getId()).build()).build();
|
||||
|
@ -63,11 +77,13 @@ public class OAuthClientsResource {
|
|||
|
||||
@Path("{id}")
|
||||
public OAuthClientResource getOAuthClient(final @PathParam("id") String id) {
|
||||
auth.requireView();
|
||||
|
||||
OAuthClientModel oauth = realm.getOAuthClientById(id);
|
||||
if (oauth == null) {
|
||||
throw new NotFoundException();
|
||||
}
|
||||
OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, oauth, session);
|
||||
OAuthClientResource oAuthClientResource = new OAuthClientResource(realm, auth, oauth, session);
|
||||
resourceContext.initResource(oAuthClientResource);
|
||||
return oAuthClientResource;
|
||||
}
|
||||
|
|
|
@ -19,9 +19,9 @@ import javax.ws.rs.core.Context;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmAdminResource extends RoleContainerResource {
|
||||
public class RealmAdminResource {
|
||||
protected static final Logger logger = Logger.getLogger(RealmAdminResource.class);
|
||||
protected Auth auth;
|
||||
protected RealmAuth auth;
|
||||
protected RealmModel realm;
|
||||
private TokenManager tokenManager;
|
||||
|
||||
|
@ -31,43 +31,43 @@ public class RealmAdminResource extends RoleContainerResource {
|
|||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
public RealmAdminResource(Auth auth, RealmModel realm, TokenManager tokenManager) {
|
||||
super(realm, realm);
|
||||
public RealmAdminResource(RealmAuth auth, RealmModel realm, TokenManager tokenManager) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
|
||||
auth.init(RealmAuth.Resource.REALM);
|
||||
}
|
||||
|
||||
@Path("applications")
|
||||
public ApplicationsResource getApplications() {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_APPLICATIONS);
|
||||
|
||||
ApplicationsResource applicationsResource = new ApplicationsResource(realm);
|
||||
ApplicationsResource applicationsResource = new ApplicationsResource(realm, auth);
|
||||
resourceContext.initResource(applicationsResource);
|
||||
return applicationsResource;
|
||||
}
|
||||
|
||||
@Path("oauth-clients")
|
||||
public OAuthClientsResource getOAuthClients() {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_CLIENTS);
|
||||
|
||||
OAuthClientsResource oauth = new OAuthClientsResource(realm, session);
|
||||
OAuthClientsResource oauth = new OAuthClientsResource(realm, auth, session);
|
||||
resourceContext.initResource(oauth);
|
||||
return oauth;
|
||||
}
|
||||
|
||||
@Path("roles")
|
||||
public RoleContainerResource getRoleContainerResource() {
|
||||
return new RoleContainerResource(realm, auth, realm);
|
||||
}
|
||||
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public RealmRepresentation getRealm() {
|
||||
String realmAdminApp = AdminRoles.getAdminApp(realm);
|
||||
if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) {
|
||||
if (auth.hasView()) {
|
||||
return ModelToRepresentation.toRepresentation(realm);
|
||||
} else {
|
||||
auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES);
|
||||
auth.requireAny();
|
||||
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setId(realm.getId());
|
||||
rep.setRealm(realm.getName());
|
||||
|
||||
return rep;
|
||||
|
@ -77,15 +77,15 @@ public class RealmAdminResource extends RoleContainerResource {
|
|||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void updateRealm(final RealmRepresentation rep) {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("updating realm: " + realm.getName());
|
||||
new RealmManager(session).updateRealm(rep, realm);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
public void deleteRealms() {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
|
||||
public void deleteRealm() {
|
||||
auth.requireManage();
|
||||
|
||||
if (!new RealmManager(session).removeRealm(realm)) {
|
||||
throw new NotFoundException();
|
||||
|
@ -94,18 +94,14 @@ public class RealmAdminResource extends RoleContainerResource {
|
|||
|
||||
@Path("users")
|
||||
public UsersResource users() {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_USERS);
|
||||
|
||||
UsersResource users = new UsersResource(realm, tokenManager);
|
||||
UsersResource users = new UsersResource(realm, auth, tokenManager);
|
||||
resourceContext.initResource(users);
|
||||
return users;
|
||||
}
|
||||
|
||||
@Path("roles-by-id")
|
||||
public RoleByIdResource rolesById() {
|
||||
auth.require(AdminRoles.getAdminApp(realm), AdminRoles.MANAGE_REALM);
|
||||
|
||||
RoleByIdResource resource = new RoleByIdResource(realm);
|
||||
RoleByIdResource resource = new RoleByIdResource(realm, auth);
|
||||
resourceContext.initResource(resource);
|
||||
return resource;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
|
||||
import javax.ws.rs.ForbiddenException;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class RealmAuth {
|
||||
|
||||
private Resource resource;
|
||||
|
||||
public enum Resource {
|
||||
APPLICATION, CLIENT, USER, REALM
|
||||
}
|
||||
|
||||
private Auth auth;
|
||||
private String realmAdminApp;
|
||||
|
||||
public RealmAuth(Auth auth, String realmAdminApp) {
|
||||
this.auth = auth;
|
||||
this.realmAdminApp = realmAdminApp;
|
||||
}
|
||||
|
||||
public RealmAuth init(Resource resource) {
|
||||
this.resource = resource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void requireAny() {
|
||||
if (!auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasView() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getViewRole(resource), getManageRole(resource));
|
||||
}
|
||||
|
||||
public boolean hasManage() {
|
||||
return auth.hasOneOfAppRole(realmAdminApp, getManageRole(resource));
|
||||
}
|
||||
|
||||
public void requireView() {
|
||||
if (!hasView()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
public void requireManage() {
|
||||
if (!hasManage()) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getViewRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.VIEW_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.VIEW_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.VIEW_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.VIEW_REALM;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
private String getManageRole(Resource resource) {
|
||||
switch (resource) {
|
||||
case APPLICATION:
|
||||
return AdminRoles.MANAGE_APPLICATIONS;
|
||||
case CLIENT:
|
||||
return AdminRoles.MANAGE_CLIENTS;
|
||||
case USER:
|
||||
return AdminRoles.MANAGE_USERS;
|
||||
case REALM:
|
||||
return AdminRoles.MANAGE_REALM;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -6,8 +6,6 @@ import org.jboss.resteasy.plugins.providers.multipart.InputPart;
|
|||
import org.jboss.resteasy.plugins.providers.multipart.MultipartFormDataInput;
|
||||
import org.jboss.resteasy.util.GenericType;
|
||||
import org.keycloak.models.AdminRoles;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
|
@ -67,11 +65,10 @@ public class RealmsAdminResource {
|
|||
for (RealmModel realm : realms) {
|
||||
String realmAdminApp = AdminRoles.getAdminApp(realm);
|
||||
|
||||
if (auth.has(realmAdminApp, AdminRoles.MANAGE_REALM)) {
|
||||
if (auth.hasAppRole(realmAdminApp, AdminRoles.MANAGE_REALM)) {
|
||||
reps.add(ModelToRepresentation.toRepresentation(realm));
|
||||
} else if (auth.hasOneOf(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
|
||||
} else if (auth.hasOneOfAppRole(realmAdminApp, AdminRoles.ALL_REALM_ROLES)) {
|
||||
RealmRepresentation rep = new RealmRepresentation();
|
||||
rep.setId(realm.getId());
|
||||
rep.setRealm(realm.getName());
|
||||
reps.add(rep);
|
||||
}
|
||||
|
@ -90,7 +87,9 @@ public class RealmsAdminResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) {
|
||||
auth.require(AdminRoles.ADMIN);
|
||||
if (!auth.hasRealmRole(AdminRoles.ADMIN)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
logger.debug("importRealm: {0}", rep.getRealm());
|
||||
RealmManager realmManager = new RealmManager(session);
|
||||
|
@ -107,7 +106,9 @@ public class RealmsAdminResource {
|
|||
@POST
|
||||
@Consumes(MediaType.MULTIPART_FORM_DATA)
|
||||
public Response uploadRealm(MultipartFormDataInput input) throws IOException {
|
||||
auth.require(AdminRoles.ADMIN);
|
||||
if (!auth.hasRealmRole(AdminRoles.ADMIN)) {
|
||||
throw new ForbiddenException();
|
||||
}
|
||||
|
||||
Map<String, List<InputPart>> uploadForm = input.getFormDataMap();
|
||||
List<InputPart> inputParts = uploadForm.get("file");
|
||||
|
@ -128,9 +129,9 @@ public class RealmsAdminResource {
|
|||
RealmModel realm = realmManager.getRealmByName(name);
|
||||
if (realm == null) throw new NotFoundException("{realm} = " + name);
|
||||
|
||||
auth.requireOneOf(AdminRoles.getAdminApp(realm), AdminRoles.ALL_REALM_ROLES);
|
||||
RealmAuth realmAuth = new RealmAuth(auth, AdminRoles.getAdminApp(realm));
|
||||
|
||||
RealmAdminResource adminResource = new RealmAdminResource(auth, realm, tokenManager);
|
||||
RealmAdminResource adminResource = new RealmAdminResource(realmAuth, realm, tokenManager);
|
||||
resourceContext.initResource(adminResource);
|
||||
return adminResource;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.OAuthClientModel;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.representations.idm.RoleRepresentation;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.resources.admin.RoleResource;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
|
@ -19,10 +18,6 @@ import javax.ws.rs.PUT;
|
|||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -33,8 +28,14 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RoleByIdResource extends RoleResource {
|
||||
public RoleByIdResource(RealmModel realm) {
|
||||
private final RealmModel realm;
|
||||
private final RealmAuth auth;
|
||||
|
||||
public RoleByIdResource(RealmModel realm, RealmAuth auth) {
|
||||
super(realm);
|
||||
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
@Path("{role-id}")
|
||||
|
@ -43,6 +44,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Produces("application/json")
|
||||
public RoleRepresentation getRole(final @PathParam("role-id") String id) {
|
||||
RoleModel roleModel = getRoleModel(id);
|
||||
auth.requireView();
|
||||
return getRole(roleModel);
|
||||
}
|
||||
|
||||
|
@ -51,6 +53,19 @@ public class RoleByIdResource extends RoleResource {
|
|||
if (roleModel == null || roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role with id: " + id);
|
||||
}
|
||||
|
||||
RealmAuth.Resource r = null;
|
||||
if (roleModel.getContainer() instanceof RealmModel) {
|
||||
r = RealmAuth.Resource.REALM;
|
||||
} else if (roleModel.getContainer() instanceof ApplicationModel) {
|
||||
r = RealmAuth.Resource.APPLICATION;
|
||||
} else if (roleModel.getContainer() instanceof OAuthClientModel) {
|
||||
r = RealmAuth.Resource.CLIENT;
|
||||
} else if (roleModel.getContainer() instanceof UserModel) {
|
||||
r = RealmAuth.Resource.USER;
|
||||
}
|
||||
auth.init(r);
|
||||
|
||||
return roleModel;
|
||||
}
|
||||
|
||||
|
@ -59,6 +74,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@NoCache
|
||||
public void deleteRole(final @PathParam("role-id") String id) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireManage();
|
||||
deleteRole(role);
|
||||
}
|
||||
|
||||
|
@ -67,6 +83,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Consumes("application/json")
|
||||
public void updateRole(final @PathParam("role-id") String id, final RoleRepresentation rep) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireManage();
|
||||
updateRole(rep, role);
|
||||
}
|
||||
|
||||
|
@ -75,6 +92,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Consumes("application/json")
|
||||
public void addComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireManage();
|
||||
addComposites(roles, role);
|
||||
}
|
||||
|
||||
|
@ -84,6 +102,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Produces("application/json")
|
||||
public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-id") String id) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireView();
|
||||
return getRoleComposites(role);
|
||||
}
|
||||
|
||||
|
@ -93,6 +112,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Produces("application/json")
|
||||
public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-id") String id) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireView();
|
||||
return getRealmRoleComposites(role);
|
||||
}
|
||||
|
||||
|
@ -103,6 +123,7 @@ public class RoleByIdResource extends RoleResource {
|
|||
public Set<RoleRepresentation> getApplicationRoleComposites(final @PathParam("role-id") String id,
|
||||
final @PathParam("app") String appName) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireView();
|
||||
return getApplicationRoleComposites(appName, role);
|
||||
}
|
||||
|
||||
|
@ -112,8 +133,8 @@ public class RoleByIdResource extends RoleResource {
|
|||
@Consumes("application/json")
|
||||
public void deleteComposites(final @PathParam("role-id") String id, List<RoleRepresentation> roles) {
|
||||
RoleModel role = getRoleModel(id);
|
||||
auth.requireManage();
|
||||
deleteComposites(roles, role);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.keycloak.models.ApplicationModel;
|
||||
import org.keycloak.models.Constants;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleContainerModel;
|
||||
|
@ -10,13 +9,19 @@ import org.keycloak.representations.idm.RoleRepresentation;
|
|||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.resources.flows.Flows;
|
||||
|
||||
import javax.ws.rs.*;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.NotFoundException;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.PUT;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -25,18 +30,24 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RoleContainerResource extends RoleResource {
|
||||
private final RealmModel realm;
|
||||
private final RealmAuth auth;
|
||||
protected RoleContainerModel roleContainer;
|
||||
|
||||
public RoleContainerResource(RealmModel realm, RoleContainerModel roleContainer) {
|
||||
public RoleContainerResource(RealmModel realm, RealmAuth auth, RoleContainerModel roleContainer) {
|
||||
super(realm);
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
this.roleContainer = roleContainer;
|
||||
}
|
||||
|
||||
@Path("roles")
|
||||
@Path("")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public List<RoleRepresentation> getRoles() {
|
||||
auth.requireAny();
|
||||
|
||||
Set<RoleModel> roleModels = roleContainer.getRoles();
|
||||
List<RoleRepresentation> roles = new ArrayList<RoleRepresentation>();
|
||||
for (RoleModel roleModel : roleModels) {
|
||||
|
@ -47,10 +58,12 @@ public class RoleContainerResource extends RoleResource {
|
|||
return roles;
|
||||
}
|
||||
|
||||
@Path("roles")
|
||||
@Path("")
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
if (roleContainer.getRole(rep.getName()) != null || rep.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
return Flows.errors().exists("Role with name " + rep.getName() + " already exists");
|
||||
}
|
||||
|
@ -62,11 +75,13 @@ public class RoleContainerResource extends RoleResource {
|
|||
return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getName()).build()).build();
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}")
|
||||
@Path("{role-name}")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public RoleRepresentation getRole(final @PathParam("role-name") String roleName) {
|
||||
auth.requireView();
|
||||
|
||||
RoleModel roleModel = roleContainer.getRole(roleName);
|
||||
if (roleModel == null || roleModel.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -74,10 +89,12 @@ public class RoleContainerResource extends RoleResource {
|
|||
return getRole(roleModel);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}")
|
||||
@Path("{role-name}")
|
||||
@DELETE
|
||||
@NoCache
|
||||
public void deleteRole(final @PathParam("role-name") String roleName) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -85,10 +102,12 @@ public class RoleContainerResource extends RoleResource {
|
|||
deleteRole(role);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}")
|
||||
@Path("{role-name}")
|
||||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void updateRole(final @PathParam("role-name") String roleName, final RoleRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -96,10 +115,12 @@ public class RoleContainerResource extends RoleResource {
|
|||
updateRole(rep, role);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}/composites")
|
||||
@Path("{role-name}/composites")
|
||||
@POST
|
||||
@Consumes("application/json")
|
||||
public void addComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -107,11 +128,13 @@ public class RoleContainerResource extends RoleResource {
|
|||
addComposites(roles, role);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}/composites")
|
||||
@Path("{role-name}/composites")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Set<RoleRepresentation> getRoleComposites(final @PathParam("role-name") String roleName) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -119,11 +142,13 @@ public class RoleContainerResource extends RoleResource {
|
|||
return getRoleComposites(role);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}/composites/realm")
|
||||
@Path("{role-name}/composites/realm")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Set<RoleRepresentation> getRealmRoleComposites(final @PathParam("role-name") String roleName) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -131,12 +156,14 @@ public class RoleContainerResource extends RoleResource {
|
|||
return getRealmRoleComposites(role);
|
||||
}
|
||||
|
||||
@Path("roles/{role-name}/composites/application/{app}")
|
||||
@Path("{role-name}/composites/application/{app}")
|
||||
@GET
|
||||
@NoCache
|
||||
@Produces("application/json")
|
||||
public Set<RoleRepresentation> getApplicationRoleComposites(final @PathParam("role-name") String roleName,
|
||||
final @PathParam("app") String appName) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
@ -145,10 +172,12 @@ public class RoleContainerResource extends RoleResource {
|
|||
}
|
||||
|
||||
|
||||
@Path("roles/{role-name}/composites")
|
||||
@Path("{role-name}/composites")
|
||||
@DELETE
|
||||
@Consumes("application/json")
|
||||
public void deleteComposites(final @PathParam("role-name") String roleName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
RoleModel role = roleContainer.getRole(roleName);
|
||||
if (role == null || role.getName().startsWith(Constants.INTERNAL_ROLE)) {
|
||||
throw new NotFoundException("Could not find role: " + roleName);
|
||||
|
|
|
@ -16,7 +16,7 @@ import java.util.Set;
|
|||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RoleResource {
|
||||
public abstract class RoleResource {
|
||||
protected RealmModel realm;
|
||||
|
||||
public RoleResource(RealmModel realm) {
|
||||
|
|
|
@ -32,11 +32,13 @@ import java.util.Set;
|
|||
*/
|
||||
public class ScopeMappedResource {
|
||||
protected RealmModel realm;
|
||||
private RealmAuth auth;
|
||||
protected UserModel agent;
|
||||
protected KeycloakSession session;
|
||||
|
||||
public ScopeMappedResource(RealmModel realm, UserModel account, KeycloakSession session) {
|
||||
public ScopeMappedResource(RealmModel realm, RealmAuth auth, UserModel account, KeycloakSession session) {
|
||||
this.realm = realm;
|
||||
this.auth = auth;
|
||||
this.agent = account;
|
||||
this.session = session;
|
||||
}
|
||||
|
@ -45,6 +47,8 @@ public class ScopeMappedResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public MappingsRepresentation getScopeMappings() {
|
||||
auth.requireView();
|
||||
|
||||
MappingsRepresentation all = new MappingsRepresentation();
|
||||
Set<RoleModel> realmMappings = realm.getRealmScopeMappings(agent);
|
||||
RealmManager manager = new RealmManager(session);
|
||||
|
@ -83,6 +87,8 @@ public class ScopeMappedResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public List<RoleRepresentation> getRealmScopeMappings() {
|
||||
auth.requireView();
|
||||
|
||||
Set<RoleModel> realmMappings = realm.getRealmScopeMappings(agent);
|
||||
List<RoleRepresentation> realmMappingsRep = new ArrayList<RoleRepresentation>();
|
||||
RealmManager manager = new RealmManager(session);
|
||||
|
@ -96,6 +102,8 @@ public class ScopeMappedResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public void addRealmScopeMappings(List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
for (RoleRepresentation role : roles) {
|
||||
RoleModel roleModel = realm.getRoleById(role.getId());
|
||||
if (roleModel == null) {
|
||||
|
@ -111,6 +119,8 @@ public class ScopeMappedResource {
|
|||
@DELETE
|
||||
@Consumes("application/json")
|
||||
public void deleteRealmScopeMappings(List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
if (roles == null) {
|
||||
Set<RoleModel> roleModels = realm.getRealmScopeMappings(agent);
|
||||
for (RoleModel roleModel : roleModels) {
|
||||
|
@ -133,6 +143,8 @@ public class ScopeMappedResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public List<RoleRepresentation> getApplicationScopeMappings(@PathParam("app") String appName) {
|
||||
auth.requireView();
|
||||
|
||||
ApplicationModel app = realm.getApplicationByName(appName);
|
||||
|
||||
if (app == null) {
|
||||
|
@ -151,6 +163,8 @@ public class ScopeMappedResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public void addApplicationScopeMapping(@PathParam("app") String appName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
ApplicationModel app = realm.getApplicationByName(appName);
|
||||
|
||||
if (app == null) {
|
||||
|
@ -171,6 +185,8 @@ public class ScopeMappedResource {
|
|||
@DELETE
|
||||
@Consumes("application/json")
|
||||
public void deleteApplicationScopeMapping(@PathParam("app") String appName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
ApplicationModel app = realm.getApplicationByName(appName);
|
||||
|
||||
if (app == null) {
|
||||
|
|
|
@ -13,6 +13,7 @@ import org.keycloak.representations.idm.*;
|
|||
import org.keycloak.services.email.EmailException;
|
||||
import org.keycloak.services.email.EmailSender;
|
||||
import org.keycloak.services.managers.AccessCodeEntry;
|
||||
import org.keycloak.services.managers.Auth;
|
||||
import org.keycloak.services.managers.ModelToRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.services.managers.TokenManager;
|
||||
|
@ -50,11 +51,15 @@ public class UsersResource {
|
|||
|
||||
protected RealmModel realm;
|
||||
|
||||
private RealmAuth auth;
|
||||
private TokenManager tokenManager;
|
||||
|
||||
public UsersResource(RealmModel realm, TokenManager tokenManager) {
|
||||
public UsersResource(RealmModel realm, RealmAuth auth, TokenManager tokenManager) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
this.tokenManager = tokenManager;
|
||||
|
||||
auth.init(RealmAuth.Resource.USER);
|
||||
}
|
||||
|
||||
@Context
|
||||
|
@ -71,6 +76,8 @@ public class UsersResource {
|
|||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void updateUser(final @PathParam("username") String username, final UserRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -81,6 +88,8 @@ public class UsersResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public Response createUser(final @Context UriInfo uriInfo, final UserRepresentation rep) {
|
||||
auth.requireManage();
|
||||
|
||||
if (realm.getUser(rep.getUsername()) != null) {
|
||||
return Flows.errors().exists("User with username " + rep.getUsername() + " already exists");
|
||||
}
|
||||
|
@ -125,6 +134,8 @@ public class UsersResource {
|
|||
@NoCache
|
||||
@Produces("application/json")
|
||||
public UserRepresentation getUser(final @PathParam("username") String username) {
|
||||
auth.requireView();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null || !isUser(user)) {
|
||||
throw new NotFoundException();
|
||||
|
@ -136,6 +147,8 @@ public class UsersResource {
|
|||
@DELETE
|
||||
@NoCache
|
||||
public void deleteUser(final @PathParam("username") String username) {
|
||||
auth.requireManage();
|
||||
|
||||
realm.removeUser(username);
|
||||
}
|
||||
|
||||
|
@ -147,6 +160,8 @@ public class UsersResource {
|
|||
@QueryParam("firstName") String first,
|
||||
@QueryParam("email") String email,
|
||||
@QueryParam("username") String username) {
|
||||
auth.requireView();
|
||||
|
||||
RealmManager manager = new RealmManager(session);
|
||||
List<UserRepresentation> results = new ArrayList<UserRepresentation>();
|
||||
List<UserModel> userModels;
|
||||
|
@ -191,6 +206,8 @@ public class UsersResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public MappingsRepresentation getRoleMappings(@PathParam("username") String username) {
|
||||
auth.requireView();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -234,6 +251,8 @@ public class UsersResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public List<RoleRepresentation> getRealmRoleMappings(@PathParam("username") String username) {
|
||||
auth.requireView();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -252,6 +271,8 @@ public class UsersResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public void addRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("** addRealmRoleMappings: {0}", roles);
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
|
@ -273,6 +294,8 @@ public class UsersResource {
|
|||
@DELETE
|
||||
@Consumes("application/json")
|
||||
public void deleteRealmRoleMappings(@PathParam("username") String username, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("deleteRealmRoleMappings");
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
|
@ -301,6 +324,8 @@ public class UsersResource {
|
|||
@Produces("application/json")
|
||||
@NoCache
|
||||
public List<RoleRepresentation> getApplicationRoleMappings(@PathParam("username") String username, @PathParam("app") String appName) {
|
||||
auth.requireView();
|
||||
|
||||
logger.debug("getApplicationRoleMappings");
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
|
@ -327,6 +352,8 @@ public class UsersResource {
|
|||
@POST
|
||||
@Consumes("application/json")
|
||||
public void addApplicationRoleMapping(@PathParam("username") String username, @PathParam("app") String appName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
logger.debug("addApplicationRoleMapping");
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
|
@ -353,6 +380,8 @@ public class UsersResource {
|
|||
@DELETE
|
||||
@Consumes("application/json")
|
||||
public void deleteApplicationRoleMapping(@PathParam("username") String username, @PathParam("app") String appName, List<RoleRepresentation> roles) {
|
||||
auth.requireManage();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -389,6 +418,8 @@ public class UsersResource {
|
|||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void resetPassword(@PathParam("username") String username, CredentialRepresentation pass) {
|
||||
auth.requireManage();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -406,6 +437,8 @@ public class UsersResource {
|
|||
@PUT
|
||||
@Consumes("application/json")
|
||||
public void removeTotp(@PathParam("username") String username) {
|
||||
auth.requireManage();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
@ -418,6 +451,8 @@ public class UsersResource {
|
|||
@PUT
|
||||
@Consumes("application/json")
|
||||
public Response resetPasswordEmail(@PathParam("username") String username) {
|
||||
auth.requireManage();
|
||||
|
||||
UserModel user = realm.getUser(username);
|
||||
if (user == null) {
|
||||
throw new NotFoundException();
|
||||
|
|
Loading…
Reference in a new issue