added stats to admin UI page, restyled scopes and dynamically registered flags
parent
6ec8b77f81
commit
6ed7477bc0
|
@ -37,4 +37,19 @@ public interface StatsService {
|
||||||
*/
|
*/
|
||||||
public Map<String, Integer> calculateSummaryStats();
|
public Map<String, Integer> calculateSummaryStats();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate usage count for all clients
|
||||||
|
*
|
||||||
|
* @return a map of id of client object to number of approvals
|
||||||
|
*/
|
||||||
|
public Map<Long, Integer> calculateByClientId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the usage count for a single client
|
||||||
|
*
|
||||||
|
* @param id the id of the client to search on
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Integer countForClientId(Long id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,15 +22,21 @@ package org.mitre.openid.connect.service.impl;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.mitre.oauth2.model.ClientDetailsEntity;
|
||||||
|
import org.mitre.oauth2.service.ClientDetailsEntityService;
|
||||||
import org.mitre.openid.connect.model.ApprovedSite;
|
import org.mitre.openid.connect.model.ApprovedSite;
|
||||||
import org.mitre.openid.connect.service.ApprovedSiteService;
|
import org.mitre.openid.connect.service.ApprovedSiteService;
|
||||||
import org.mitre.openid.connect.service.StatsService;
|
import org.mitre.openid.connect.service.StatsService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import com.google.common.collect.HashMultiset;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author jricher
|
* @author jricher
|
||||||
*
|
*
|
||||||
|
@ -41,6 +47,9 @@ public class DefaultStatsService implements StatsService {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApprovedSiteService approvedSiteService;
|
private ApprovedSiteService approvedSiteService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ClientDetailsEntityService clientService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Integer> calculateSummaryStats() {
|
public Map<String, Integer> calculateSummaryStats() {
|
||||||
// get all approved sites
|
// get all approved sites
|
||||||
|
@ -62,4 +71,51 @@ public class DefaultStatsService implements StatsService {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.mitre.openid.connect.service.StatsService#calculateByClientId()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Map<Long, Integer> calculateByClientId() {
|
||||||
|
// get all approved sites
|
||||||
|
Collection<ApprovedSite> allSites = approvedSiteService.getAll();
|
||||||
|
|
||||||
|
Multiset<String> clientIds = HashMultiset.create();
|
||||||
|
for (ApprovedSite approvedSite : allSites) {
|
||||||
|
clientIds.add(approvedSite.getClientId());
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Long, Integer> counts = getEmptyClientCountMap();
|
||||||
|
for (String clientId : clientIds) {
|
||||||
|
ClientDetailsEntity client = clientService.loadClientByClientId(clientId);
|
||||||
|
counts.put(client.getId(), clientIds.count(clientId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.mitre.openid.connect.service.StatsService#countForClientId(java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Integer countForClientId(Long id) {
|
||||||
|
|
||||||
|
Map<Long, Integer> counts = calculateByClientId();
|
||||||
|
return counts.get(id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new map of all client ids set to zero
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Map<Long, Integer> getEmptyClientCountMap() {
|
||||||
|
Map<Long, Integer> counts = new HashMap<Long, Integer>();
|
||||||
|
Collection<ClientDetailsEntity> clients = clientService.getAllClients();
|
||||||
|
for (ClientDetailsEntity client : clients) {
|
||||||
|
counts.put(client.getId(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return counts;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
|
||||||
@Controller
|
@Controller
|
||||||
|
@ -44,4 +45,22 @@ public class StatsAPI {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "byclientid", produces = "application/json")
|
||||||
|
public String statsByClient(ModelMap m) {
|
||||||
|
Map<Long, Integer> e = statsService.calculateByClientId();
|
||||||
|
|
||||||
|
m.put("entity", e);
|
||||||
|
|
||||||
|
return "jsonEntityView";
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping(value = "byclientid/{id}", produces = "application/json")
|
||||||
|
public String statsByClientId(@PathVariable("id") Long id, ModelMap m) {
|
||||||
|
Integer e = statsService.countForClientId(id);
|
||||||
|
|
||||||
|
m.put("entity", e);
|
||||||
|
|
||||||
|
return "jsonEntityView";
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,6 +303,12 @@ var BlackListWidgetView = ListWidgetView.extend({
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Stats table
|
||||||
|
|
||||||
|
var StatsModel = Backbone.Model.extend({
|
||||||
|
url: "api/stats/byclientid"
|
||||||
|
});
|
||||||
|
|
||||||
// Router
|
// Router
|
||||||
var AppRouter = Backbone.Router.extend({
|
var AppRouter = Backbone.Router.extend({
|
||||||
|
|
||||||
|
@ -340,8 +346,10 @@ var AppRouter = Backbone.Router.extend({
|
||||||
this.blackListList = new BlackListCollection();
|
this.blackListList = new BlackListCollection();
|
||||||
this.approvedSiteList = new ApprovedSiteCollection();
|
this.approvedSiteList = new ApprovedSiteCollection();
|
||||||
this.systemScopeList = new SystemScopeCollection();
|
this.systemScopeList = new SystemScopeCollection();
|
||||||
|
this.clientStats = new StatsModel();
|
||||||
|
|
||||||
this.clientListView = new ClientListView({model:this.clientList});
|
|
||||||
|
this.clientListView = new ClientListView({model:this.clientList, stats: this.clientStats});
|
||||||
this.whiteListListView = new WhiteListListView({model:this.whiteListList});
|
this.whiteListListView = new WhiteListListView({model:this.whiteListList});
|
||||||
this.approvedSiteListView = new ApprovedSiteListView({model:this.approvedSiteList});
|
this.approvedSiteListView = new ApprovedSiteListView({model:this.approvedSiteList});
|
||||||
this.blackListListView = new BlackListListView({model:this.blackListList});
|
this.blackListListView = new BlackListListView({model:this.blackListList});
|
||||||
|
@ -365,8 +373,12 @@ var AppRouter = Backbone.Router.extend({
|
||||||
success: function(collection, response) {
|
success: function(collection, response) {
|
||||||
app.whiteListList.fetch({
|
app.whiteListList.fetch({
|
||||||
success: function(collection, response) {
|
success: function(collection, response) {
|
||||||
var baseUrl = $.url($('base').attr('href'));
|
app.clientStats.fetch({
|
||||||
Backbone.history.start({pushState: true, root: baseUrl.attr('relative') + 'manage/'});
|
success: function(model, response) {
|
||||||
|
var baseUrl = $.url($('base').attr('href'));
|
||||||
|
Backbone.history.start({pushState: true, root: baseUrl.attr('relative') + 'manage/'});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,7 +133,8 @@ var ClientView = Backbone.View.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
render:function (eventName) {
|
render:function (eventName) {
|
||||||
this.$el.html(this.template(this.model.toJSON()));
|
var json = {client: this.model.toJSON(), count: this.options.count};
|
||||||
|
this.$el.html(this.template(json));
|
||||||
|
|
||||||
$('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scope'), systemScopes: app.systemScopeList}));
|
$('.scope-list', this.el).html(this.scopeTemplate({scopes: this.model.get('scope'), systemScopes: app.systemScopeList}));
|
||||||
|
|
||||||
|
@ -230,7 +231,11 @@ var ClientListView = Backbone.View.extend({
|
||||||
$(this.el).html($('#tmpl-client-table').html());
|
$(this.el).html($('#tmpl-client-table').html());
|
||||||
|
|
||||||
_.each(this.model.models, function (client) {
|
_.each(this.model.models, function (client) {
|
||||||
$("#client-table",this.el).append(new ClientView({model:client}).render().el);
|
$("#client-table",this.el).append(
|
||||||
|
new ClientView({
|
||||||
|
model:client,
|
||||||
|
count:this.options.stats.get(client.get('id'))
|
||||||
|
}).render().el);
|
||||||
}, this);
|
}, this);
|
||||||
|
|
||||||
this.togglePlaceholder();
|
this.togglePlaceholder();
|
||||||
|
@ -250,9 +255,13 @@ var ClientListView = Backbone.View.extend({
|
||||||
|
|
||||||
refreshTable:function() {
|
refreshTable:function() {
|
||||||
var _self = this;
|
var _self = this;
|
||||||
this.model.fetch({
|
_self.model.fetch({
|
||||||
success: function() {
|
success: function() {
|
||||||
_self.render();
|
_self.options.stats.fetch({
|
||||||
|
success: function () {
|
||||||
|
_self.render();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ var SystemScopeView = Backbone.View.extend({
|
||||||
render:function (eventName) {
|
render:function (eventName) {
|
||||||
this.$el.html(this.template(this.model.toJSON()));
|
this.$el.html(this.template(this.model.toJSON()));
|
||||||
|
|
||||||
this.$('.dynamically-registered').tooltip({title: 'This client was dynamically registered'});
|
this.$('.allow-dyn-reg').tooltip({title: 'This scope can be used by dynamically registered clients'});
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,19 +18,24 @@
|
||||||
|
|
||||||
<script type="text/html" id="tmpl-client">
|
<script type="text/html" id="tmpl-client">
|
||||||
<td>
|
<td>
|
||||||
<% if (dynamicallyRegistered) { %>
|
<% if (count) { %>
|
||||||
<span class="dynamically-registered"><i class="icon-globe"></i></span>
|
<span class="label label-info"><%= count %></span>
|
||||||
|
<% } else { %>
|
||||||
|
<span class="label label-important">0</span>
|
||||||
|
<% } %>
|
||||||
|
<% if (client.dynamicallyRegistered) { %>
|
||||||
|
<span class="label label-inverse dynamically-registered"><i class="icon-globe icon-white"></i></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<%=clientId%>
|
<%=client.clientId%>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<%=clientName%>
|
<%=client.clientName%>
|
||||||
<% if (clientDescription) { %>
|
<% if (client.clientDescription) { %>
|
||||||
<blockquote><small><%=clientDescription%></small></blockquote>
|
<blockquote><small><%=client.clientDescription%></small></blockquote>
|
||||||
<% } %>
|
<% } %>
|
||||||
<div class="scope-list"></div>
|
<div class="scope-list"></div>
|
||||||
<!--expandable future information-->
|
<!--expandable future information-->
|
||||||
|
|
|
@ -80,7 +80,7 @@
|
||||||
<script type="text/html" id="tmpl-grant">
|
<script type="text/html" id="tmpl-grant">
|
||||||
<td>
|
<td>
|
||||||
<% if (client.dynamicallyRegistered) { %>
|
<% if (client.dynamicallyRegistered) { %>
|
||||||
<span class="dynamically-registered"><i class="icon-globe"></i></span>
|
<span class="label label-inverse dynamically-registered"><i class="icon-globe icon-white"></i></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
|
@ -47,13 +47,18 @@
|
||||||
|
|
||||||
<script type="text/html" id="tmpl-system-scope">
|
<script type="text/html" id="tmpl-system-scope">
|
||||||
<td>
|
<td>
|
||||||
<% if (icon) { %>
|
<% if (allowDynReg) { %>
|
||||||
<i class="icon-<%= icon %>"></i>
|
<span class="label label-inverse allow-dyn-reg"><i class="icon-globe icon-white"></i></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<%= value %>
|
<span class="badge badge-info">
|
||||||
|
<% if (icon) { %>
|
||||||
|
<i class="icon-<%= icon %> icon-white"></i>
|
||||||
|
<% } %>
|
||||||
|
<%= value %>
|
||||||
|
</span>
|
||||||
<blockquote><small><%= description %></small></blockquote>
|
<blockquote><small><%= description %></small></blockquote>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<script type="text/html" id="tmpl-whitelist">
|
<script type="text/html" id="tmpl-whitelist">
|
||||||
<td>
|
<td>
|
||||||
<% if (client.dynamicallyRegistered) { %>
|
<% if (client.dynamicallyRegistered) { %>
|
||||||
<span class="dynamically-registered"><i class="icon-globe"></i></span>
|
<span class="label label-inverse dynamically-registered"><i class="icon-globe icon-white"></i></span>
|
||||||
<% } %>
|
<% } %>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue