admin console
This commit is contained in:
parent
dd4c0d448c
commit
1d8e38f0c6
18 changed files with 282 additions and 35 deletions
|
@ -296,17 +296,48 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
return getUserSessions(realm, client, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserSessionModel> getOfflineUserSessions(RealmModel realm) {
|
||||
return getOfflineUserSessions(realm, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserSessionModel> getOfflineUserSessions(RealmModel realm, int first, int max) {
|
||||
return getUserSessions(realm, first, max, true);
|
||||
}
|
||||
|
||||
protected List<UserSessionModel> getUserSessions(final RealmModel realm, ClientModel client, int firstResult, int maxResults, final boolean offline) {
|
||||
final String clientUuid = client.getId();
|
||||
UserSessionPredicate predicate = UserSessionPredicate.create(realm.getId()).client(clientUuid);
|
||||
|
||||
return getUserSessionModels(realm, firstResult, maxResults, offline, predicate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserSessionModel> getUserSessions(RealmModel realm) {
|
||||
return getUserSessions(realm, -1, -1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UserSessionModel> getUserSessions(RealmModel realm, int firstResult, int maxResults) {
|
||||
return getUserSessions(realm, firstResult, maxResults, false);
|
||||
}
|
||||
|
||||
protected List<UserSessionModel> getUserSessions(final RealmModel realm, int firstResult, int maxResults, final boolean offline) {
|
||||
UserSessionPredicate predicate = UserSessionPredicate.create(realm.getId());
|
||||
|
||||
return getUserSessionModels(realm, firstResult, maxResults, offline, predicate);
|
||||
}
|
||||
|
||||
protected List<UserSessionModel> getUserSessionModels(RealmModel realm, int firstResult, int maxResults, boolean offline, UserSessionPredicate predicate) {
|
||||
Cache<String, SessionEntityWrapper<UserSessionEntity>> cache = getCache(offline);
|
||||
cache = CacheDecorators.skipCacheLoaders(cache);
|
||||
|
||||
Cache<UUID, SessionEntityWrapper<AuthenticatedClientSessionEntity>> clientSessionCache = getClientSessionCache(offline);
|
||||
Cache<UUID, SessionEntityWrapper<AuthenticatedClientSessionEntity>> clientSessionCacheDecorated = CacheDecorators.skipCacheLoaders(clientSessionCache);
|
||||
|
||||
final String clientUuid = client.getId();
|
||||
|
||||
Stream<UserSessionEntity> stream = cache.entrySet().stream()
|
||||
.filter(UserSessionPredicate.create(realm.getId()).client(clientUuid))
|
||||
.filter(predicate)
|
||||
.map(Mappers.userSessionEntity())
|
||||
.sorted(Comparators.userSessionLastSessionRefresh());
|
||||
|
||||
|
@ -330,7 +361,6 @@ public class InfinispanUserSessionProvider implements UserSessionProvider {
|
|||
return sessions;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public UserSessionModel getUserSessionWithPredicate(RealmModel realm, String id, boolean offline, Predicate<UserSessionModel> predicate) {
|
||||
UserSessionModel userSession = getUserSession(realm, id, offline);
|
||||
|
|
|
@ -27,12 +27,12 @@ import java.util.Set;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
public interface ClientProvider extends ClientLookupProvider, Provider {
|
||||
List<ClientModel> getClients(RealmModel realm);
|
||||
|
||||
ClientModel addClient(RealmModel realm, String clientId);
|
||||
|
||||
ClientModel addClient(RealmModel realm, String id, String clientId);
|
||||
|
||||
List<ClientModel> getClients(RealmModel realm);
|
||||
|
||||
RoleModel addClientRole(RealmModel realm, ClientModel client, String name);
|
||||
|
||||
RoleModel addClientRole(RealmModel realm, ClientModel client, String id, String name);
|
||||
|
|
|
@ -35,9 +35,11 @@ public interface UserSessionProvider extends Provider {
|
|||
UserSessionModel createUserSession(RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId);
|
||||
UserSessionModel createUserSession(String id, RealmModel realm, UserModel user, String loginUsername, String ipAddress, String authMethod, boolean rememberMe, String brokerSessionId, String brokerUserId);
|
||||
UserSessionModel getUserSession(RealmModel realm, String id);
|
||||
List<UserSessionModel> getUserSessions(RealmModel realm);
|
||||
List<UserSessionModel> getUserSessions(RealmModel realm, UserModel user);
|
||||
List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client);
|
||||
List<UserSessionModel> getUserSessions(RealmModel realm, ClientModel client, int firstResult, int maxResults);
|
||||
List<UserSessionModel> getUserSessions(RealmModel realm, int firstResult, int maxResults);
|
||||
List<UserSessionModel> getUserSessionByBrokerUserId(RealmModel realm, String brokerUserId);
|
||||
UserSessionModel getUserSessionByBrokerSessionId(RealmModel realm, String brokerSessionId);
|
||||
|
||||
|
@ -75,9 +77,11 @@ public interface UserSessionProvider extends Provider {
|
|||
/** Will automatically attach newly created offline client session to the offlineUserSession **/
|
||||
AuthenticatedClientSessionModel createOfflineClientSession(AuthenticatedClientSessionModel clientSession, UserSessionModel offlineUserSession);
|
||||
List<UserSessionModel> getOfflineUserSessions(RealmModel realm, UserModel user);
|
||||
List<UserSessionModel> getOfflineUserSessions(RealmModel realm);
|
||||
|
||||
long getOfflineSessionsCount(RealmModel realm, ClientModel client);
|
||||
List<UserSessionModel> getOfflineUserSessions(RealmModel realm, ClientModel client, int first, int max);
|
||||
List<UserSessionModel> getOfflineUserSessions(RealmModel realm, int first, int max);
|
||||
|
||||
/** Triggered by persister during pre-load. It optionally imports authenticatedClientSessions too if requested. Otherwise the imported UserSession will have empty list of AuthenticationSessionModel **/
|
||||
UserSessionModel importUserSession(UserSessionModel persistentUserSession, boolean offline, boolean importAuthenticatedClientSessions);
|
||||
|
|
|
@ -25,6 +25,9 @@ import org.keycloak.storage.client.ClientLookupProvider;
|
|||
/**
|
||||
* Base interface for components that want to provide an alternative storage mechanism for clients
|
||||
*
|
||||
* This is currently a private incomplete SPI. Please discuss on dev list if you want us to complete it or want to do the work yourself.
|
||||
* This work is described in KEYCLOAK-6408 JIRA issue.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.services.resources.admin;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
||||
import org.jboss.resteasy.spi.NotFoundException;
|
||||
import org.keycloak.common.ClientConnection;
|
||||
import org.keycloak.component.ComponentModel;
|
||||
import org.keycloak.events.admin.OperationType;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ServicesLogger;
|
||||
import org.keycloak.services.managers.UserStorageSyncManager;
|
||||
import org.keycloak.services.resources.admin.permissions.AdminPermissionEvaluator;
|
||||
import org.keycloak.storage.UserStorageProvider;
|
||||
import org.keycloak.storage.UserStorageProviderModel;
|
||||
import org.keycloak.storage.client.ClientStorageProvider;
|
||||
import org.keycloak.storage.ldap.LDAPStorageProvider;
|
||||
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
|
||||
import org.keycloak.storage.user.SynchronizationResult;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.HttpHeaders;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @resource User Storage Provider
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ClientStorageProviderResource {
|
||||
private static final Logger logger = Logger.getLogger(ClientStorageProviderResource.class);
|
||||
|
||||
protected RealmModel realm;
|
||||
|
||||
protected AdminPermissionEvaluator auth;
|
||||
|
||||
protected AdminEventBuilder adminEvent;
|
||||
|
||||
@Context
|
||||
protected ClientConnection clientConnection;
|
||||
|
||||
@Context
|
||||
protected UriInfo uriInfo;
|
||||
|
||||
@Context
|
||||
protected KeycloakSession session;
|
||||
|
||||
@Context
|
||||
protected HttpHeaders headers;
|
||||
|
||||
public ClientStorageProviderResource(RealmModel realm, AdminPermissionEvaluator auth, AdminEventBuilder adminEvent) {
|
||||
this.auth = auth;
|
||||
this.realm = realm;
|
||||
this.adminEvent = adminEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Need this for admin console to display simple name of provider when displaying client detail
|
||||
*
|
||||
* KEYCLOAK-4328
|
||||
*
|
||||
* @param id
|
||||
* @return
|
||||
*/
|
||||
@GET
|
||||
@Path("{id}/name")
|
||||
@NoCache
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Map<String, String> getSimpleName(@PathParam("id") String id) {
|
||||
auth.clients().requireList();
|
||||
|
||||
ComponentModel model = realm.getComponent(id);
|
||||
if (model == null) {
|
||||
throw new NotFoundException("Could not find component");
|
||||
}
|
||||
if (!model.getProviderType().equals(ClientStorageProvider.class.getName())) {
|
||||
throw new NotFoundException("found, but not a ClientStorageProvider");
|
||||
}
|
||||
|
||||
Map<String, String> data = new HashMap<>();
|
||||
data.put("id", model.getId());
|
||||
data.put("name", model.getName());
|
||||
return data;
|
||||
}
|
||||
}
|
|
@ -98,7 +98,7 @@ public class ClientsResource {
|
|||
public List<ClientRepresentation> getClients(@QueryParam("clientId") String clientId, @QueryParam("viewableOnly") @DefaultValue("false") boolean viewableOnly) {
|
||||
List<ClientRepresentation> rep = new ArrayList<>();
|
||||
|
||||
if (clientId == null) {
|
||||
if (clientId == null || clientId.trim().equals("")) {
|
||||
List<ClientModel> clientModels = realm.getClients();
|
||||
auth.clients().requireList();
|
||||
boolean view = auth.clients().canView();
|
||||
|
|
|
@ -100,6 +100,7 @@ import java.security.cert.X509Certificate;
|
|||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
|
@ -504,17 +505,62 @@ public class RealmAdminResource {
|
|||
public List<Map<String, String>> getClientSessionStats() {
|
||||
auth.realm().requireViewRealm();
|
||||
|
||||
List<Map<String, String>> data = new LinkedList<Map<String, String>>();
|
||||
for (ClientModel client : realm.getClients()) {
|
||||
long size = session.sessions().getActiveUserSessions(client.getRealm(), client);
|
||||
if (size == 0) continue;
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("id", client.getId());
|
||||
map.put("clientId", client.getClientId());
|
||||
map.put("active", size + "");
|
||||
data.add(map);
|
||||
Map<String, Map<String, String>> data = new HashMap();
|
||||
{
|
||||
List<UserSessionModel> userSessions = session.sessions().getUserSessions(realm);
|
||||
Map<String, Long> activeCount = new HashMap<>();
|
||||
// we have to iterate over all realm user sessions as clients coming from client storage provider might not be reachable from getClients()
|
||||
for (UserSessionModel userSession : userSessions) {
|
||||
for (String id : userSession.getAuthenticatedClientSessions().keySet()) {
|
||||
Long number = activeCount.get(id);
|
||||
if (number == null) {
|
||||
activeCount.put(id, new Long(1));
|
||||
} else {
|
||||
activeCount.put(id, number + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Long> entry : activeCount.entrySet()) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
ClientModel client = realm.getClientById(entry.getKey());
|
||||
map.put("id", client.getId());
|
||||
map.put("clientId", client.getClientId());
|
||||
map.put("active", entry.getValue().toString());
|
||||
map.put("offline", "0");
|
||||
data.put(client.getId(), map);
|
||||
|
||||
}
|
||||
}
|
||||
return data;
|
||||
{
|
||||
Map<String, Long> offlineCount = new HashMap<>();
|
||||
// we have to iterate over all realm user sessions as clients coming from client storage provider might not be reachable from getClients()
|
||||
List<UserSessionModel> offlineSessions = session.sessions().getOfflineUserSessions(realm);
|
||||
for (UserSessionModel userSession : offlineSessions) {
|
||||
for (String id : userSession.getAuthenticatedClientSessions().keySet()) {
|
||||
Long number = offlineCount.get(id);
|
||||
if (number == null) {
|
||||
offlineCount.put(id, new Long(1));
|
||||
} else {
|
||||
offlineCount.put(id, number + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Map.Entry<String, Long> entry : offlineCount.entrySet()) {
|
||||
Map<String, String> map = data.get(entry.getKey());
|
||||
if (map == null) {
|
||||
map = new HashMap<>();
|
||||
ClientModel client = realm.getClientById(entry.getKey());
|
||||
map.put("id", client.getId());
|
||||
map.put("clientId", client.getClientId());
|
||||
map.put("active", "0");
|
||||
data.put(client.getId(), map);
|
||||
}
|
||||
map.put("offline", entry.getValue().toString());
|
||||
}
|
||||
}
|
||||
List<Map<String, String>> result = new LinkedList<>();
|
||||
for (Map<String, String> item : data.values()) result.add(item);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.keycloak.models.ClientTemplateModel;
|
|||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.services.ForbiddenException;
|
||||
import org.keycloak.storage.StorageId;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -634,8 +635,8 @@ class ClientPermissions implements ClientPermissionEvaluator, ClientPermissionM
|
|||
public Map<String, Boolean> getAccess(ClientModel client) {
|
||||
Map<String, Boolean> map = new HashMap<>();
|
||||
map.put("view", canView(client));
|
||||
map.put("manage", canManage(client));
|
||||
map.put("configure", canConfigure(client));
|
||||
map.put("manage", StorageId.isLocalStorage(client) && canManage(client));
|
||||
map.put("configure", StorageId.isLocalStorage(client) && canConfigure(client));
|
||||
return map;
|
||||
}
|
||||
|
||||
|
|
|
@ -25,14 +25,13 @@ import org.keycloak.models.KeycloakSession;
|
|||
import org.keycloak.models.ModelException;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.models.UserModel;
|
||||
import org.keycloak.storage.client.ClientLookupProvider;
|
||||
import org.keycloak.storage.client.ClientStorageProvider;
|
||||
import org.keycloak.storage.client.ClientStorageProviderFactory;
|
||||
import org.keycloak.storage.client.ClientStorageProviderModel;
|
||||
import org.keycloak.storage.user.UserLookupProvider;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
@ -163,9 +162,12 @@ public class ClientStorageManager implements ClientProvider {
|
|||
return session.clientLocalStorage().addClient(realm, id, clientId);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public List<ClientModel> getClients(RealmModel realm) {
|
||||
return session.clientLocalStorage().getClients(realm);
|
||||
return session.clientLocalStorage().getClients(realm);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -23,7 +23,6 @@ import org.keycloak.models.ProtocolMapperModel;
|
|||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.models.RoleModel;
|
||||
import org.keycloak.storage.StorageId;
|
||||
import org.keycloak.storage.client.AbstractClientStorageAdapter;
|
||||
import org.keycloak.storage.client.AbstractReadOnlyClientStorageAdapter;
|
||||
import org.keycloak.storage.client.ClientLookupProvider;
|
||||
import org.keycloak.storage.client.ClientStorageProvider;
|
||||
|
@ -55,13 +54,13 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
|
|||
public ClientModel getClientById(String id, RealmModel realm) {
|
||||
StorageId storageId = new StorageId(id);
|
||||
final String clientId = storageId.getExternalId();
|
||||
if (clientId.equals(clientId)) return new ClientAdapter(realm);
|
||||
if (this.clientId.equals(clientId)) return new ClientAdapter(realm);
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClientModel getClientByClientId(String clientId, RealmModel realm) {
|
||||
if (clientId.equals(clientId)) return new ClientAdapter(realm);
|
||||
if (this.clientId.equals(clientId)) return new ClientAdapter(realm);
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -155,7 +154,7 @@ public class HardcodedClientStorageProvider implements ClientStorageProvider, Cl
|
|||
|
||||
@Override
|
||||
public String getProtocol() {
|
||||
return null;
|
||||
return "openid-connect";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -132,6 +132,7 @@ public class ClientStorageTest extends AbstractTestRealmKeycloakTest {
|
|||
public void testBrowser() throws Exception {
|
||||
String clientId = "hardcoded-client";
|
||||
testBrowser(clientId);
|
||||
//Thread.sleep(10000000);
|
||||
}
|
||||
|
||||
private void testBrowser(String clientId) {
|
||||
|
|
|
@ -173,6 +173,7 @@ realm-sessions=Realm Sessions
|
|||
revocation=Revocation
|
||||
logout-all=Logout all
|
||||
active-sessions=Active Sessions
|
||||
offline-sessions=Offline Sessions
|
||||
sessions=Sessions
|
||||
not-before=Not Before
|
||||
not-before.tooltip=Revoke any tokens issued before this date.
|
||||
|
@ -1343,6 +1344,8 @@ userStorage.cachePolicy.maxLifespan.tooltip=Max lifespan of a user cache entry i
|
|||
user-origin-link=Storage Origin
|
||||
user-origin.tooltip=UserStorageProvider the user was loaded from
|
||||
user-link.tooltip=UserStorageProvider this locally stored user was imported from.
|
||||
client-origin-link=Storage Origin
|
||||
client-origin.tooltip=Provider the client was loaded from
|
||||
|
||||
disable=Disable
|
||||
disableable-credential-types=Disableable Types
|
||||
|
|
|
@ -764,6 +764,15 @@ module.controller('ClientListCtrl', function($scope, realm, Client, serverInfo,
|
|||
});
|
||||
};
|
||||
|
||||
$scope.searchClient = function() {
|
||||
console.log('searchQuery!!! ' + $scope.search.clientId);
|
||||
Client.query({realm: realm.realm, viewableOnly: true, clientId: $scope.search.clientId}).$promise.then(function(clients) {
|
||||
$scope.numberOfPages = Math.ceil(clients.length/$scope.pageSize);
|
||||
$scope.clients = clients;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$scope.exportClient = function(client) {
|
||||
var clientCopy = angular.copy(client);
|
||||
delete clientCopy.id;
|
||||
|
@ -819,7 +828,7 @@ module.controller('ClientInstallationCtrl', function($scope, realm, client, serv
|
|||
}
|
||||
});
|
||||
|
||||
module.controller('ClientDetailCtrl', function($scope, realm, client, templates, $route, serverInfo, Client, ClientDescriptionConverter, $location, $modal, Dialog, Notifications) {
|
||||
module.controller('ClientDetailCtrl', function($scope, realm, client, templates, $route, serverInfo, Client, ClientDescriptionConverter, Components, ClientStorageOperations, $location, $modal, Dialog, Notifications) {
|
||||
|
||||
|
||||
|
||||
|
@ -889,6 +898,25 @@ module.controller('ClientDetailCtrl', function($scope, realm, client, templates,
|
|||
$scope.disableServiceAccountRolesTab = !client.serviceAccountsEnabled;
|
||||
$scope.disableCredentialsTab = client.publicClient;
|
||||
|
||||
if(client.origin) {
|
||||
if ($scope.access.viewRealm) {
|
||||
Components.get({realm: realm.realm, componentId: client.origin}, function (link) {
|
||||
$scope.originName = link.name;
|
||||
//$scope.originLink = "#/realms/" + realm.realm + "/user-storage/providers/" + link.providerId + "/" + link.id;
|
||||
})
|
||||
}
|
||||
else {
|
||||
// KEYCLOAK-4328
|
||||
ClientStorageOperations.simpleName.get({realm: realm.realm, componentId: client.origin}, function (link) {
|
||||
$scope.originName = link.name;
|
||||
//$scope.originLink = $location.absUrl();
|
||||
})
|
||||
}
|
||||
} else {
|
||||
console.log("origin is null");
|
||||
}
|
||||
|
||||
|
||||
function updateProperties() {
|
||||
if (!$scope.client.attributes) {
|
||||
$scope.client.attributes = {};
|
||||
|
|
|
@ -1813,6 +1813,16 @@ module.factory('UserStorageOperations', function($resource) {
|
|||
});
|
||||
|
||||
|
||||
module.factory('ClientStorageOperations', function($resource) {
|
||||
var object = {}
|
||||
object.simpleName = $resource(authUrl + '/admin/realms/:realm/client-storage/:componentId/name', {
|
||||
realm : '@realm',
|
||||
componentId : '@componentId'
|
||||
});
|
||||
return object;
|
||||
});
|
||||
|
||||
|
||||
module.factory('ClientRegistrationPolicyProviders', function($resource) {
|
||||
return $resource(authUrl + '/admin/realms/:realm/client-registration-policy/providers', {
|
||||
realm : '@realm',
|
||||
|
|
|
@ -37,6 +37,13 @@
|
|||
</div>
|
||||
<kc-tooltip>{{:: 'client.enabled.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix block" data-ng-show="client.origin">
|
||||
<label class="col-md-2 control-label">{{:: 'client-origin-link' | translate}}</label>
|
||||
<div class="col-md-6">
|
||||
{{originName}}
|
||||
</div>
|
||||
<kc-tooltip>{{:: 'client-origin.tooltip' | translate}}</kc-tooltip>
|
||||
</div>
|
||||
<div class="form-group clearfix block" data-ng-show="protocol != 'docker-v2'">
|
||||
<label class="col-md-2 control-label" for="consentRequired">{{:: 'consent-required' | translate}}</label>
|
||||
<div class="col-sm-6">
|
||||
|
|
|
@ -11,9 +11,9 @@
|
|||
<div class="form-inline">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.clientId" class="form-control search" onkeyup="if(event.keyCode === 13){$(this).next('I').click();}">
|
||||
<input type="text" placeholder="{{:: 'search.placeholder' | translate}}" data-ng-model="search.clientId" class="form-control search" onkeydown="if(event.keyCode === 13) document.getElementById('clientSearch').click()">
|
||||
<div class="input-group-addon">
|
||||
<i class="fa fa-search" type="submit"></i>
|
||||
<i class="fa fa-search" id="clientSearch" data-ng-click="searchClient()"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
<tr>
|
||||
<th>{{:: 'client' | translate}}</th>
|
||||
<th>{{:: 'active-sessions' | translate}}</th>
|
||||
<th>{{:: 'offline-sessions' | translate}}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr data-ng-repeat="data in stats">
|
||||
<td><a href="#/realms/{{realm.realm}}/clients/{{data.id}}/sessions">{{data.clientId}}</a></td>
|
||||
<td>{{data.active}}</td>
|
||||
<td>{{data.offline}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
<ul class="nav nav-tabs" data-ng-hide="create && !path[4]">
|
||||
<li ng-class="{active: !path[4]}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}">{{:: 'settings' | translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'credentials'}"
|
||||
data-ng-show="!client.publicClient && client.protocol == 'openid-connect'">
|
||||
data-ng-show="!client.publicClient && client.protocol == 'openid-connect' && !client.origin">
|
||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/credentials">{{:: 'credentials' | translate}}</a>
|
||||
</li>
|
||||
<li ng-class="{active: path[4] == 'saml'}" data-ng-show="client.protocol == 'saml' && (client.attributes['saml.client.signature'] == 'true' || client.attributes['saml.encrypt'] == 'true')"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/saml/keys">{{:: 'saml-keys' | translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'roles'}"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">{{:: 'roles' | translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'roles'}" data-ng-show="!client.origin"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/roles">{{:: 'roles' | translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'mappers'}" data-ng-show="!client.bearerOnly">
|
||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/mappers">{{:: 'mappers' | translate}}</a>
|
||||
<kc-tooltip>{{:: 'mappers.tooltip' | translate}}</kc-tooltip>
|
||||
|
@ -23,10 +23,10 @@
|
|||
<kc-tooltip>{{:: 'scope.tooltip' | translate}}</kc-tooltip>
|
||||
</li>
|
||||
<li ng-class="{active: path[4] == 'authz'}"
|
||||
data-ng-show="serverInfo.featureEnabled('AUTHORIZATION') && !disableAuthorizationTab && client.authorizationServicesEnabled">
|
||||
data-ng-show="serverInfo.featureEnabled('AUTHORIZATION') && !disableAuthorizationTab && client.authorizationServicesEnabled && !client.origin">
|
||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/authz/resource-server">{{:: 'authz-authorization' |
|
||||
translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'revocation'}" data-ng-show="client.protocol != 'docker-v2' && client.protocol != 'saml'"><a
|
||||
<li ng-class="{active: path[4] == 'revocation'}" data-ng-show="client.protocol != 'docker-v2' && client.protocol != 'saml' && !client.origin"><a
|
||||
href="#/realms/{{realm.realm}}/clients/{{client.id}}/revocation">{{:: 'revocation' | translate}}</a>
|
||||
</li>
|
||||
<!-- <li ng-class="{active: path[4] == 'identity-provider'}" data-ng-show="realm.identityFederationEnabled"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/identity-provider">Identity Provider</a></li> -->
|
||||
|
@ -40,9 +40,9 @@
|
|||
<kc-tooltip>{{:: 'offline-access.tooltip' | translate}}</kc-tooltip>
|
||||
</li>
|
||||
|
||||
<li ng-class="{active: path[4] == 'clustering'}" data-ng-show="!client.publicClient"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'clustering' | translate}}</a></li>
|
||||
<li ng-class="{active: path[4] == 'clustering'}" data-ng-show="!client.publicClient && !client.origin"><a href="#/realms/{{realm.realm}}/clients/{{client.id}}/clustering">{{:: 'clustering' | translate}}</a></li>
|
||||
|
||||
<li ng-class="{active: path[4] == 'installation'}">
|
||||
<li ng-class="{active: path[4] == 'installation'}" data-ng-show="!client.origin">
|
||||
<a href="#/realms/{{realm.realm}}/clients/{{client.id}}/installation">{{:: 'installation' | translate}}</a>
|
||||
<kc-tooltip>{{:: 'installation.tooltip' | translate}}</kc-tooltip>
|
||||
</li>
|
||||
|
|
Loading…
Reference in a new issue