Refactoring to UI
19
ui/pom.xml
|
@ -13,19 +13,10 @@
|
|||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jaxrs-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
105
ui/src/main/java/org/keycloak/ui/example/Admin.java
Normal file
|
@ -0,0 +1,105 @@
|
|||
package org.keycloak.ui.example;
|
||||
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
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.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
@ApplicationPath("ui/api")
|
||||
@Path("")
|
||||
public class Admin extends javax.ws.rs.core.Application {
|
||||
|
||||
private static Map<String, Realm> realms = new HashMap<String, Realm>();
|
||||
|
||||
private static Map<String, Application> applications = new HashMap<String, Application>();
|
||||
|
||||
@DELETE
|
||||
@Path("/applications/{key}")
|
||||
public void delete(@PathParam("key") String applicationKey) {
|
||||
applications.remove(applicationKey);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("/realms/{key}")
|
||||
public void deleteRealm(@PathParam("key") String key) {
|
||||
realms.remove(key);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/applications/{key}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Application getApplication(@PathParam("key") String applicationKey) {
|
||||
return applications.get(applicationKey);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/applications")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<Application> getApplications() {
|
||||
return new LinkedList<Application>(applications.values());
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("/realms/{key}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Realm getRealm(@PathParam("key") String key) {
|
||||
return realms.get(key);
|
||||
}
|
||||
|
||||
|
||||
@GET
|
||||
@Path("/realms")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<Realm> getRealms() {
|
||||
return new LinkedList<Realm>(realms.values());
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/applications")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response save(Application application) {
|
||||
String key = UUID.randomUUID().toString();
|
||||
application.setKey(key);
|
||||
applications.put(key, application);
|
||||
return Response.created(URI.create("/applications/" + application.getKey())).build();
|
||||
}
|
||||
|
||||
@POST
|
||||
@Path("/realms")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public Response save(Realm realm) {
|
||||
String key = UUID.randomUUID().toString();
|
||||
realm.setKey(key);
|
||||
realms.put(key, realm);
|
||||
return Response.created(URI.create("/realms/" + realm.getKey())).build();
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/applications/{key}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void save(@PathParam("key") String applicationKey, Application application) {
|
||||
applications.put(applicationKey, application);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("/realms/{key}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
public void save(@PathParam("key") String key, Realm realm) {
|
||||
realms.put(key, realm);
|
||||
}
|
||||
}
|
114
ui/src/main/java/org/keycloak/ui/example/Application.java
Normal file
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2012, Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.keycloak.ui.example;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@XmlRootElement
|
||||
public class Application {
|
||||
|
||||
private String callbackUrl;
|
||||
|
||||
private String key;
|
||||
|
||||
private String name;
|
||||
|
||||
private String owner;
|
||||
|
||||
private String javaScriptOrigin;
|
||||
|
||||
private List<IdentityProviderConfig> providers;
|
||||
|
||||
private String secret;
|
||||
|
||||
private String realm;
|
||||
|
||||
public String getCallbackUrl() {
|
||||
return callbackUrl;
|
||||
}
|
||||
|
||||
public String getJavaScriptOrigin() {
|
||||
return javaScriptOrigin;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public List<IdentityProviderConfig> getProviders() {
|
||||
return providers;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public String getRealm() {
|
||||
return realm;
|
||||
}
|
||||
|
||||
public void setCallbackUrl(String callbackUrl) {
|
||||
this.callbackUrl = callbackUrl;
|
||||
}
|
||||
|
||||
public void setJavaScriptOrigin(String javaScriptOrigin) {
|
||||
this.javaScriptOrigin = javaScriptOrigin;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public void setProviders(List<IdentityProviderConfig> providers) {
|
||||
this.providers = providers;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
public void setRealm(String realm) {
|
||||
this.realm = realm;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2012, Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.keycloak.ui.example;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
@XmlRootElement
|
||||
public class IdentityProviderConfig {
|
||||
|
||||
private Long id;
|
||||
|
||||
private String key;
|
||||
|
||||
private String providerId;
|
||||
|
||||
private String secret;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getProviderId() {
|
||||
return providerId;
|
||||
}
|
||||
|
||||
public String getSecret() {
|
||||
return secret;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void setProviderId(String providerId) {
|
||||
this.providerId = providerId;
|
||||
}
|
||||
|
||||
public void setSecret(String secret) {
|
||||
this.secret = secret;
|
||||
}
|
||||
|
||||
}
|
60
ui/src/main/java/org/keycloak/ui/example/Realm.java
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2012, Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
package org.keycloak.ui.example;
|
||||
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||
*/
|
||||
public class Realm {
|
||||
|
||||
private String key;
|
||||
|
||||
private String name;
|
||||
|
||||
private String owner;
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setOwner(String owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
[ {
|
||||
"callbackUrl" : "http://localhost:8080/test",
|
||||
"key" : "7301af66-c481-4f54-a280-16529e11a153",
|
||||
"name" : "Foo application",
|
||||
"owner" : "root",
|
||||
"javaScriptOrigin" : null,
|
||||
"providers" : [ {
|
||||
"id" : 7,
|
||||
"key" : "google-key",
|
||||
"providerId" : "google",
|
||||
"secret" : "google-secret"
|
||||
} ],
|
||||
"secret" : "77f78140-e0ee-4912-a504-32c51180e918",
|
||||
"realm" : "5ee722cc-7bdb-49fe-b76c-8b246e699065"
|
||||
}, {
|
||||
"callbackUrl" : "http://localhost:8080/bar",
|
||||
"key" : "f3ab7d43-7737-4507-a7a8-2e261f77298d",
|
||||
"name" : "Bar application",
|
||||
"owner" : "root",
|
||||
"javaScriptOrigin" : null,
|
||||
"providers" : [],
|
||||
"secret" : "7d833773-d1e9-41f3-8749-8698f4c5ed03",
|
||||
"realm" : "7d01c3cd-f483-414b-a02f-c260815224cc"
|
||||
} ]
|
|
@ -1,276 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
var eventjugglerServices = angular.module('eventjugglerAdminServices', [ 'ngResource' ]);
|
||||
|
||||
eventjugglerServices.factory('Notifications', function($rootScope, $timeout) {
|
||||
var notifications = {};
|
||||
|
||||
var scheduled = null;
|
||||
var schedulePop = function() {
|
||||
if (scheduled) {
|
||||
$timeout.cancel(scheduled);
|
||||
}
|
||||
|
||||
scheduled = $timeout(function() {
|
||||
$rootScope.notification = null;
|
||||
scheduled = null;
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
if (!$rootScope.notifications) {
|
||||
$rootScope.notifications = [];
|
||||
}
|
||||
|
||||
notifications.success = function(message) {
|
||||
$rootScope.notification = {
|
||||
type : "success",
|
||||
message : message
|
||||
};
|
||||
|
||||
schedulePop();
|
||||
};
|
||||
|
||||
return notifications;
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('Application', function($resource) {
|
||||
return $resource('/ejs-identity/api/admin/applications/:key', {
|
||||
key : '@key'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('ApplicationListLoader', function(Application, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Application.query(function(applications) {
|
||||
delay.resolve(applications);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch applications');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('ApplicationLoader', function(Application, $route, $q) {
|
||||
return function() {
|
||||
var key = $route.current.params.key;
|
||||
if (key == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
Application.get({
|
||||
key : key
|
||||
}, function(application) {
|
||||
delay.resolve(application);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch application ' + key);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('Provider', function($resource) {
|
||||
return $resource('/ejs-identity/api/admin/providers');
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('ProviderListLoader', function(Provider, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Provider.query(function(providers) {
|
||||
delay.resolve(providers);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch providers');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('Realm', function($resource) {
|
||||
return $resource('/ejs-identity/api/admin/realms/:key', {
|
||||
key : '@key'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('RealmListLoader', function(Realm, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Realm.query(function(realms) {
|
||||
delay.resolve(realms);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch realms');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('RealmLoader', function(Realm, $route, $q) {
|
||||
return function() {
|
||||
var key = $route.current.params.realmKey;
|
||||
if (key == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
Realm.get({
|
||||
key : key
|
||||
}, function(realm) {
|
||||
delay.resolve(realm);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch key ' + key);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('User', function($resource) {
|
||||
return $resource('/ejs-identity/api/im/:realmKey/users/:userId', {
|
||||
realmKey : '@realmKey',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
save : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('UserListLoader', function(User, $route, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
User.query({
|
||||
realmKey : $route.current.params.realmKey
|
||||
}, function(users) {
|
||||
delay.resolve(users);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch users');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('UserLoader', function(User, $route, $q) {
|
||||
return function() {
|
||||
var userId = $route.current.params.userId;
|
||||
if (userId == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
User.get({
|
||||
realmKey : $route.current.params.realmKey,
|
||||
userId : userId
|
||||
}, function(user) {
|
||||
delay.resolve(user);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch user ' + $route.current.params.userId);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('Activities', function($resource) {
|
||||
var activities = {};
|
||||
activities.events = $resource('/ejs-activities/api/events');
|
||||
activities.statistics = $resource('/ejs-activities/api/statistics');
|
||||
return activities;
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('ActivitiesStatisticsLoader', function(Activities, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Activities.statistics.get(function(statistics) {
|
||||
delay.resolve(statistics);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch statistics');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.factory('ActivitiesEventsLoader', function(Activities, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Activities.events.query({
|
||||
"max" : 10
|
||||
}, function(events) {
|
||||
delay.resolve(events);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch events');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
eventjugglerServices.service('Auth', function($resource, $http, $location, $routeParams) {
|
||||
var auth = {};
|
||||
auth.user = {};
|
||||
|
||||
var parameters = window.location.search.substring(1).split("&");
|
||||
for ( var i = 0; i < parameters.length; i++) {
|
||||
var param = parameters[i].split("=");
|
||||
if (decodeURIComponent(param[0]) == "token") {
|
||||
auth.token = decodeURIComponent(param[1]);
|
||||
}
|
||||
}
|
||||
|
||||
if (auth.token) {
|
||||
$location.search("token", null);
|
||||
localStorage.setItem("token", auth.token);
|
||||
} else {
|
||||
auth.token = localStorage.getItem("token");
|
||||
}
|
||||
|
||||
if (auth.token) {
|
||||
$http.defaults.headers.common['token'] = auth.token;
|
||||
|
||||
auth.user = $resource('/ejs-identity/api/auth/userinfo').get({
|
||||
appKey : "system",
|
||||
token : auth.token
|
||||
}, function() {
|
||||
if (auth.user.userId) {
|
||||
auth.loggedIn = true;
|
||||
auth.root = auth.user.userId == "root";
|
||||
|
||||
var displayName;
|
||||
if (auth.user.firstName || auth.user.lastName) {
|
||||
displayName = auth.user.firstName;
|
||||
if (auth.user.lastName) {
|
||||
displayName = displayName ? displayName + " " + auth.user.lastName : auth.user.lastName;
|
||||
}
|
||||
} else {
|
||||
displayName = auth.user.userId;
|
||||
}
|
||||
|
||||
auth.user.displayName = displayName;
|
||||
} else {
|
||||
auth.logout();
|
||||
}
|
||||
}, function() {
|
||||
auth.logout();
|
||||
});
|
||||
}
|
||||
|
||||
auth.logout = function() {
|
||||
$resource('/ejs-identity/api/auth/logout').get({
|
||||
appKey : "system"
|
||||
});
|
||||
|
||||
localStorage.removeItem("token");
|
||||
$http.defaults.headers.common['token'] = null;
|
||||
|
||||
auth.loggedIn = false;
|
||||
auth.root = false;
|
||||
|
||||
$location.url("/");
|
||||
};
|
||||
|
||||
return auth;
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
<div id="wrapper" class="container">
|
||||
<div class="row">
|
||||
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
|
||||
<div id="actions-bg"></div>
|
||||
|
||||
<div id="container-right" class="span9">
|
||||
<h1>
|
||||
<span class="gray">Events</span>
|
||||
</h1>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Time</th>
|
||||
<th>Context Path</th>
|
||||
<th>Page</th>
|
||||
<th>Remote Address</th>
|
||||
<th>Country</th>
|
||||
<th>User Agent</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="event in events">
|
||||
<td>{{event.time | date:'medium'}}</td>
|
||||
<td>{{event.contextPath}}</td>
|
||||
<td>{{event.page}}</td>
|
||||
<td>{{event.remoteAddr}}</td>
|
||||
<td>{{event.country}}</td>
|
||||
<td>{{event.userAgent}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="container-right-bg"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,14 +0,0 @@
|
|||
<nav id="local-nav">
|
||||
<ul class="nav nav-list">
|
||||
<li>
|
||||
<div>
|
||||
<span class="toggle">Activities</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li ng-class="!path[1]&& 'active'"><a href="#/activities">Statistics</a></li>
|
||||
<li ng-class="path[1] == 'pages' && 'active'"><a href="#/activities/pages">Pages</a></li>
|
||||
<li ng-class="path[1] == 'events' && 'active'"><a href="#/activities/events">Events</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
|
@ -1,26 +0,0 @@
|
|||
<div id="wrapper" class="container">
|
||||
<div class="row">
|
||||
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
|
||||
<div id="actions-bg"></div>
|
||||
|
||||
<div id="container-right" class="span9">
|
||||
<h1>
|
||||
<span class="gray">Pages</span>
|
||||
</h1>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="event in statistics['pageViews']">
|
||||
<td>{{event.label}}</td>
|
||||
<td>{{event.count}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div id="container-right-bg"></div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,30 +0,0 @@
|
|||
<div id="wrapper" class="container">
|
||||
<div class="row">
|
||||
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
|
||||
<div id="actions-bg"></div>
|
||||
|
||||
<div id="container-right" class="span9">
|
||||
<h1>
|
||||
<span class="gray">Statistics</span>
|
||||
</h1>
|
||||
|
||||
<fieldset ng-repeat="i in ['Browser', 'Country', 'Language', 'OS', 'User']">
|
||||
<legend>{{i}}</legend>
|
||||
|
||||
<table class="table table-striped table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Label</th>
|
||||
<th>Count</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr ng-repeat="event in statistics[i.toLowerCase() + 'Views']">
|
||||
<td>{{event.label}}</td>
|
||||
<td>{{event.count}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div id="container-right-bg"></div>
|
||||
</div>
|
||||
</div>
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 999 B After Width: | Height: | Size: 999 B |
Before Width: | Height: | Size: 935 B After Width: | Height: | Size: 935 B |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 80 B After Width: | Height: | Size: 80 B |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
Before Width: | Height: | Size: 3 KiB After Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
@ -1,9 +1,9 @@
|
|||
<!doctype html>
|
||||
<html lang="en" ng-app="eventjugglerAdmin">
|
||||
<html lang="en" data-ng-app="keycloak">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>EventJuggler Services Admin</title>
|
||||
<title>Keycloak</title>
|
||||
|
||||
<link href="lib/bootstrap/css/bootstrap.css" rel="stylesheet">
|
||||
<link href="lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
|
||||
|
@ -14,28 +14,28 @@
|
|||
|
||||
<script src="lib/angular/angular.js"></script>
|
||||
<script src="lib/angular/angular-resource.js"></script>
|
||||
<script src="lib/angular/ui-bootstrap-tpls-0.3.0.js"></script>
|
||||
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
|
||||
|
||||
<script src="lib/jquery/jquery-1.9.0.js"></script>
|
||||
<script src="lib/jquery/jquery-1.10.2.js"></script>
|
||||
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/controllers.js"></script>
|
||||
<script src="js/services.js"></script>
|
||||
</head>
|
||||
|
||||
<body ng-controller="GlobalCtrl">
|
||||
<body data-ng-controller="GlobalCtrl">
|
||||
|
||||
<div class="alert-container" ng-show="notification" ng-click="notification = null">
|
||||
<div class="alert-container" data-ng-show="notification" data-ng-click="notification = null">
|
||||
<div class="alert alert-{{notification.type}}">{{notification.message}}</div>
|
||||
</div>
|
||||
|
||||
<div id="wrap">
|
||||
<div ng-include src="'partials/menu.html'"></div>
|
||||
<div data-ng-include data-src="'partials/menu.html'"></div>
|
||||
|
||||
<div ng-view id="view" ng-hide="httpProviderError"></div>
|
||||
<div data-ng-view id="view" data-ng-hide="httpProviderError"></div>
|
||||
|
||||
<div id="httpProviderError" ng-show="httpProviderError">
|
||||
<button class="btn btn-danger" ng-click="httpProviderError=null">
|
||||
<div id="httpProviderError" data-ng-show="httpProviderError">
|
||||
<button class="btn btn-danger" data-ng-click="httpProviderError=null">
|
||||
<strong>Error</strong> {{httpProviderError}}
|
||||
</button>
|
||||
</div>
|
|
@ -1,34 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var eventjugglerModule = angular.module('eventjugglerAdmin', [ 'eventjugglerAdminServices', 'ui.bootstrap' ]);
|
||||
var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.controllers', 'ui.bootstrap' ]);
|
||||
var resourceRequests = 0;
|
||||
|
||||
eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/activities/events', {
|
||||
templateUrl : 'partials/activities-events.html',
|
||||
resolve : {
|
||||
events : function(ActivitiesEventsLoader) {
|
||||
return ActivitiesEventsLoader();
|
||||
}
|
||||
},
|
||||
controller : ActivitiesEventsCtrl
|
||||
}).when('/activities/pages', {
|
||||
templateUrl : 'partials/activities-pages.html',
|
||||
resolve : {
|
||||
statistics : function(ActivitiesStatisticsLoader) {
|
||||
return ActivitiesStatisticsLoader();
|
||||
}
|
||||
},
|
||||
controller : ActivitiesStatisticsCtrl
|
||||
}).when('/activities', {
|
||||
templateUrl : 'partials/activities-statistics.html',
|
||||
resolve : {
|
||||
statistics : function(ActivitiesStatisticsLoader) {
|
||||
return ActivitiesStatisticsLoader();
|
||||
}
|
||||
},
|
||||
controller : ActivitiesStatisticsCtrl
|
||||
}).when('/applications/:key', {
|
||||
module.config([ '$routeProvider', function($routeProvider) {
|
||||
$routeProvider.when('/applications/:key', {
|
||||
templateUrl : 'partials/application-detail.html',
|
||||
resolve : {
|
||||
applications : function(ApplicationListLoader) {
|
||||
|
@ -44,7 +20,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return ProviderListLoader();
|
||||
}
|
||||
},
|
||||
controller : ApplicationDetailCtrl
|
||||
controller : 'ApplicationDetailCtrl'
|
||||
}).when('/applications', {
|
||||
templateUrl : 'partials/application-list.html',
|
||||
resolve : {
|
||||
|
@ -52,7 +28,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return ApplicationListLoader();
|
||||
}
|
||||
},
|
||||
controller : ApplicationListCtrl
|
||||
controller : 'ApplicationListCtrl'
|
||||
}).when('/realms/:realmKey/users/:userId', {
|
||||
templateUrl : 'partials/user-detail.html',
|
||||
resolve : {
|
||||
|
@ -66,7 +42,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return UserLoader();
|
||||
}
|
||||
},
|
||||
controller : UserDetailCtrl
|
||||
controller : 'UserDetailCtrl'
|
||||
}).when('/realms/:realmKey/users', {
|
||||
templateUrl : 'partials/user-list.html',
|
||||
resolve : {
|
||||
|
@ -80,7 +56,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return UserListLoader();
|
||||
}
|
||||
},
|
||||
controller : UserListCtrl
|
||||
controller : 'UserListCtrl'
|
||||
}).when('/realms/:realmKey', {
|
||||
templateUrl : 'partials/realm-detail.html',
|
||||
resolve : {
|
||||
|
@ -91,7 +67,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return RealmLoader();
|
||||
}
|
||||
},
|
||||
controller : RealmDetailCtrl
|
||||
controller : 'RealmDetailCtrl'
|
||||
}).when('/realms', {
|
||||
templateUrl : 'partials/realm-list.html',
|
||||
resolve : {
|
||||
|
@ -99,13 +75,13 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
|
|||
return RealmListLoader();
|
||||
}
|
||||
},
|
||||
controller : RealmListCtrl
|
||||
controller : 'RealmListCtrl'
|
||||
}).otherwise({
|
||||
templateUrl : 'partials/home.html'
|
||||
});
|
||||
} ]);
|
||||
|
||||
eventjugglerModule.config(function($httpProvider) {
|
||||
module.config(function($httpProvider) {
|
||||
$httpProvider.responseInterceptors.push('errorInterceptor');
|
||||
|
||||
var spinnerFunction = function(data, headersGetter) {
|
||||
|
@ -121,7 +97,7 @@ eventjugglerModule.config(function($httpProvider) {
|
|||
|
||||
});
|
||||
|
||||
eventjugglerModule.factory('errorInterceptor', function($q, $window, $rootScope, $location) {
|
||||
module.factory('errorInterceptor', function($q, $window, $rootScope, $location) {
|
||||
return function(promise) {
|
||||
return promise.then(function(response) {
|
||||
$rootScope.httpProviderError = null;
|
||||
|
@ -133,7 +109,7 @@ eventjugglerModule.factory('errorInterceptor', function($q, $window, $rootScope,
|
|||
};
|
||||
});
|
||||
|
||||
eventjugglerModule.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
|
||||
module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
|
||||
return function(promise) {
|
||||
return promise.then(function(response) {
|
||||
resourceRequests--;
|
|
@ -1,7 +1,8 @@
|
|||
'use strict';
|
||||
|
||||
function GlobalCtrl($scope, Auth, $location, Notifications) {
|
||||
|
||||
var module = angular.module('keycloak.controllers', [ 'keycloak.services' ]);
|
||||
|
||||
module.controller('GlobalCtrl', function($scope, Auth, $location, Notifications) {
|
||||
$scope.addMessage = function() {
|
||||
Notifications.success("test");
|
||||
};
|
||||
|
@ -13,21 +14,14 @@ function GlobalCtrl($scope, Auth, $location, Notifications) {
|
|||
}, function() {
|
||||
$scope.path = $location.path().substring(1).split("/");
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function ActivitiesEventsCtrl($scope, events) {
|
||||
$scope.events = events;
|
||||
}
|
||||
|
||||
function ActivitiesStatisticsCtrl($scope, statistics) {
|
||||
$scope.statistics = statistics;
|
||||
}
|
||||
|
||||
function ApplicationListCtrl($scope, applications) {
|
||||
module.controller('ApplicationListCtrl', function($scope, applications) {
|
||||
$scope.applications = applications;
|
||||
}
|
||||
});
|
||||
|
||||
function ApplicationDetailCtrl($scope, applications, application, Application, realms, providers, $location, $window, $dialog, Notifications) {
|
||||
module.controller('ApplicationDetailCtrl', function($scope, applications, application, Application, realms, providers, $location, $window, $dialog, Notifications) {
|
||||
$scope.application = angular.copy(application);
|
||||
$scope.applications = applications;
|
||||
$scope.realms = realms;
|
||||
|
@ -159,19 +153,19 @@ function ApplicationDetailCtrl($scope, applications, application, Application, r
|
|||
};
|
||||
|
||||
$scope.$watch("providers.length + application.providers.length", updateAvailableProviders);
|
||||
}
|
||||
});
|
||||
|
||||
function RealmListCtrl($scope, realms) {
|
||||
module.controller('RealmListCtrl', function($scope, realms) {
|
||||
$scope.realms = realms;
|
||||
}
|
||||
});
|
||||
|
||||
function UserListCtrl($scope, realms, realm, users) {
|
||||
module.controller('UserListCtrl', function($scope, realms, realm, users) {
|
||||
$scope.realms = realms;
|
||||
$scope.realm = realm;
|
||||
$scope.users = users;
|
||||
}
|
||||
});
|
||||
|
||||
function UserDetailCtrl($scope, realms, realm, user, User, $location, $dialog, Notifications) {
|
||||
module.controller('UserDetailCtrl', function($scope, realms, realm, user, User, $location, $dialog, Notifications) {
|
||||
$scope.realms = realms;
|
||||
$scope.realm = realm;
|
||||
$scope.user = angular.copy(user);
|
||||
|
@ -239,9 +233,9 @@ function UserDetailCtrl($scope, realms, realm, user, User, $location, $dialog, N
|
|||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
function RealmDetailCtrl($scope, Realm, realms, realm, $location, $dialog, Notifications) {
|
||||
module.controller('RealmDetailCtrl', function($scope, Realm, realms, realm, $location, $dialog, Notifications) {
|
||||
$scope.realms = realms;
|
||||
$scope.realm = angular.copy(realm);
|
||||
$scope.create = !realm.name;
|
||||
|
@ -311,4 +305,4 @@ function RealmDetailCtrl($scope, Realm, realms, realm, $location, $dialog, Notif
|
|||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
});
|
188
ui/src/main/resources/META-INF/resources/ui/js/services.js
Normal file
|
@ -0,0 +1,188 @@
|
|||
'use strict';
|
||||
|
||||
var module = angular.module('keycloak.services', [ 'ngResource' ]);
|
||||
|
||||
module.factory('Notifications', function($rootScope, $timeout) {
|
||||
var notifications = {};
|
||||
|
||||
var scheduled = null;
|
||||
var schedulePop = function() {
|
||||
if (scheduled) {
|
||||
$timeout.cancel(scheduled);
|
||||
}
|
||||
|
||||
scheduled = $timeout(function() {
|
||||
$rootScope.notification = null;
|
||||
scheduled = null;
|
||||
}, 3000);
|
||||
};
|
||||
|
||||
if (!$rootScope.notifications) {
|
||||
$rootScope.notifications = [];
|
||||
}
|
||||
|
||||
notifications.success = function(message) {
|
||||
$rootScope.notification = {
|
||||
type : "success",
|
||||
message : message
|
||||
};
|
||||
|
||||
schedulePop();
|
||||
};
|
||||
|
||||
return notifications;
|
||||
});
|
||||
|
||||
module.factory('Application', function($resource) {
|
||||
return $resource('/keycloak-server/ui/api/applications/:key', {
|
||||
key : '@key'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('ApplicationListLoader', function(Application, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Application.query(function(applications) {
|
||||
delay.resolve(applications);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch applications');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('ApplicationLoader', function(Application, $route, $q) {
|
||||
return function() {
|
||||
var key = $route.current.params.key;
|
||||
if (key == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
Application.get({
|
||||
key : key
|
||||
}, function(application) {
|
||||
delay.resolve(application);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch application ' + key);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('Provider', function($resource) {
|
||||
return $resource('/ejs-identity/api/admin/providers');
|
||||
});
|
||||
|
||||
module.factory('ProviderListLoader', function(Provider, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Provider.query(function(providers) {
|
||||
delay.resolve(providers);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch providers');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('Realm', function($resource) {
|
||||
return $resource('/keycloak-server/ui/api/realms/:key', {
|
||||
key : '@key'
|
||||
}, {
|
||||
update : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('RealmListLoader', function(Realm, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
Realm.query(function(realms) {
|
||||
delay.resolve(realms);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch realms');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('RealmLoader', function(Realm, $route, $q) {
|
||||
return function() {
|
||||
var key = $route.current.params.realmKey;
|
||||
if (key == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
Realm.get({
|
||||
key : key
|
||||
}, function(realm) {
|
||||
delay.resolve(realm);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch key ' + key);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('User', function($resource) {
|
||||
return $resource('/ejs-identity/api/im/:realmKey/users/:userId', {
|
||||
realmKey : '@realmKey',
|
||||
userId : '@userId'
|
||||
}, {
|
||||
save : {
|
||||
method : 'PUT'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
module.factory('UserListLoader', function(User, $route, $q) {
|
||||
return function() {
|
||||
var delay = $q.defer();
|
||||
User.query({
|
||||
realmKey : $route.current.params.realmKey
|
||||
}, function(users) {
|
||||
delay.resolve(users);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch users');
|
||||
});
|
||||
return delay.promise;
|
||||
};
|
||||
});
|
||||
|
||||
module.factory('UserLoader', function(User, $route, $q) {
|
||||
return function() {
|
||||
var userId = $route.current.params.userId;
|
||||
if (userId == 'new') {
|
||||
return {};
|
||||
} else {
|
||||
var delay = $q.defer();
|
||||
User.get({
|
||||
realmKey : $route.current.params.realmKey,
|
||||
userId : userId
|
||||
}, function(user) {
|
||||
delay.resolve(user);
|
||||
}, function() {
|
||||
delay.reject('Unable to fetch user ' + $route.current.params.userId);
|
||||
});
|
||||
return delay.promise;
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
module.service('Auth', function($resource, $http, $location, $routeParams) {
|
||||
var auth = {
|
||||
loggedIn : true
|
||||
};
|
||||
auth.user = {
|
||||
userId : 'test',
|
||||
displayName: 'Test User'
|
||||
};
|
||||
return auth;
|
||||
});
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
@ -7,7 +7,6 @@
|
|||
<li class="divider-vertical-left" ng-class="path[0] == '' && 'active'"><a href="#">Home</a></li>
|
||||
<li class="divider-vertical-left" ng-class="path[0] == 'applications' && 'active'" ng-show="auth.loggedIn"><a href="#/applications">Applications</a></li>
|
||||
<li class="divider-vertical-left" ng-class="path[0] == 'realms' && 'active'" ng-show="auth.loggedIn"><a href="#/realms">Realms</a></li>
|
||||
<li class="divider-vertical-left" ng-class="path[0] == 'activities' && 'active'" ng-show="auth.root"><a href="#/activities">Activities</a></li>
|
||||
</ul>
|
||||
<ul class="nav pull-right" ng-hide="auth.loggedIn">
|
||||
<li><a href="/ejs-identity/api/login/system">Login</a></li>
|