added stats to admin UI page, restyled scopes and dynamically registered flags

pull/349/head
Justin Richer 2013-06-07 18:01:57 -04:00
parent 6ec8b77f81
commit 6ed7477bc0
10 changed files with 140 additions and 19 deletions

View File

@ -37,4 +37,19 @@ public interface StatsService {
*/
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);
}

View File

@ -22,15 +22,21 @@ package org.mitre.openid.connect.service.impl;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
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.service.ApprovedSiteService;
import org.mitre.openid.connect.service.StatsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
/**
* @author jricher
*
@ -41,6 +47,9 @@ public class DefaultStatsService implements StatsService {
@Autowired
private ApprovedSiteService approvedSiteService;
@Autowired
private ClientDetailsEntityService clientService;
@Override
public Map<String, Integer> calculateSummaryStats() {
// get all approved sites
@ -62,4 +71,51 @@ public class DefaultStatsService implements StatsService {
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;
}
}

View File

@ -23,6 +23,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
@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";
}
}

View File

@ -303,6 +303,12 @@ var BlackListWidgetView = ListWidgetView.extend({
});
// Stats table
var StatsModel = Backbone.Model.extend({
url: "api/stats/byclientid"
});
// Router
var AppRouter = Backbone.Router.extend({
@ -340,8 +346,10 @@ var AppRouter = Backbone.Router.extend({
this.blackListList = new BlackListCollection();
this.approvedSiteList = new ApprovedSiteCollection();
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.approvedSiteListView = new ApprovedSiteListView({model:this.approvedSiteList});
this.blackListListView = new BlackListListView({model:this.blackListList});
@ -365,8 +373,12 @@ var AppRouter = Backbone.Router.extend({
success: function(collection, response) {
app.whiteListList.fetch({
success: function(collection, response) {
var baseUrl = $.url($('base').attr('href'));
Backbone.history.start({pushState: true, root: baseUrl.attr('relative') + 'manage/'});
app.clientStats.fetch({
success: function(model, response) {
var baseUrl = $.url($('base').attr('href'));
Backbone.history.start({pushState: true, root: baseUrl.attr('relative') + 'manage/'});
}
});
}
});
}

View File

@ -133,7 +133,8 @@ var ClientView = Backbone.View.extend({
},
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}));
@ -230,7 +231,11 @@ var ClientListView = Backbone.View.extend({
$(this.el).html($('#tmpl-client-table').html());
_.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.togglePlaceholder();
@ -250,9 +255,13 @@ var ClientListView = Backbone.View.extend({
refreshTable:function() {
var _self = this;
this.model.fetch({
_self.model.fetch({
success: function() {
_self.render();
_self.options.stats.fetch({
success: function () {
_self.render();
}
});
}
});
}

View File

@ -80,7 +80,7 @@ var SystemScopeView = Backbone.View.extend({
render:function (eventName) {
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;
},

View File

@ -18,19 +18,24 @@
<script type="text/html" id="tmpl-client">
<td>
<% if (dynamicallyRegistered) { %>
<span class="dynamically-registered"><i class="icon-globe"></i></span>
<% if (count) { %>
<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>
<%=clientId%>
<%=client.clientId%>
</td>
<td>
<%=clientName%>
<% if (clientDescription) { %>
<blockquote><small><%=clientDescription%></small></blockquote>
<%=client.clientName%>
<% if (client.clientDescription) { %>
<blockquote><small><%=client.clientDescription%></small></blockquote>
<% } %>
<div class="scope-list"></div>
<!--expandable future information-->

View File

@ -80,7 +80,7 @@
<script type="text/html" id="tmpl-grant">
<td>
<% 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>

View File

@ -47,13 +47,18 @@
<script type="text/html" id="tmpl-system-scope">
<td>
<% if (icon) { %>
<i class="icon-<%= icon %>"></i>
<% if (allowDynReg) { %>
<span class="label label-inverse allow-dyn-reg"><i class="icon-globe icon-white"></i></span>
<% } %>
</td>
<td>
<%= value %>
<span class="badge badge-info">
<% if (icon) { %>
<i class="icon-<%= icon %> icon-white"></i>
<% } %>
<%= value %>
</span>
<blockquote><small><%= description %></small></blockquote>
</td>

View File

@ -19,7 +19,7 @@
<script type="text/html" id="tmpl-whitelist">
<td>
<% 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>