ui/acls: initial commit

This commit is contained in:
Jack Pearkes 2014-08-21 14:44:17 -07:00
parent b6279be742
commit e00941fa44
6 changed files with 252 additions and 1 deletions

View File

@ -38,6 +38,31 @@
</div>
</script>
<script type="text/x-handlebars" data-template-name="dc/unauthorized">
<div class="row">
<div class="col-md-8 col-md-offset-2 col-sm-12 col-xs-12">
<div class="text-center vertical-center">
<p class="bold">Access Denied</p>
<p>Your ACL token, <code>foobarbaz</code>, does not
have the appropriate permissions to perform the expected action.</p>
<p>Learn more in the <a href="http://www.consul.io/docs/internals/acl.html">ACL documentation</a>.</p>
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="dc/aclsdisabled">
<div class="row">
<div class="col-md-8 col-md-offset-2 col-sm-12 col-xs-12">
<div class="text-center vertical-center">
<p class="bold">ACLs Disabled</p>
<p>ACLs are disabled in this Consul cluster. This is the default behavior, as you have to implicitly enable them.</p>
</p>Learn more in the <a href="http://www.consul.io/docs/internals/acl.html">ACL documentation</a>.</p>
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" data-template-name="loading">
<div class="row">
<div class="col-md-8 col-md-offset-2 col-sm-12 col-xs-12">
@ -524,6 +549,143 @@
{{/if}}
</script>
<script type="text/x-handlebars" id="acls">
<div class="row">
<div {{ bind-attr class=":col-md-6 :col-lg-5 :padded-right-middle isShowingItem:hidden-xs isShowingItem:hidden-sm" }}>
{{view App.ActionBarView }}
{{#if filteredContent}}
{{#if condensed }}
{{#collection Ember.ListView contentBinding="filteredContent" height=800 rowHeight=44 }}
{{#link-to 'acl.show' Node tagName="div" href=false class="list-group-item list-condensed-link" }}
<div {{bind-attr class=":list-bar-horizontal"}}></div>
<div class="name">
foo
<small class="pull-right">
bar
</small>
</div>
{{/link-to}}
{{/collection}}
{{else}}
{{#collection Ember.ListView contentBinding="filteredContent" height=800 rowHeight=120 }}
{{#link-to 'nodes.show' Node tagName="div" href=false class="list-group-item list-link" }}
<div {{bind-attr class="hasFailingChecks:bg-orange:bg-green :list-bar"}}></div>
<h4 class="list-group-item-heading">
{{Node}}
<small>{{Address}}</small>
<div class="heading-helper">
<a class="subtle" href="#">{{checkMessage}}</a>
</div>
</h4>
<ul class="list-inline">
{{#each service in services}}
<li class="bold">{{service.Service}}</li>
{{/each}}
</ul>
{{/link-to}}
{{/collection}}
{{/if}}
{{else}}
<p class="light">There are no nodes to show.</p>
{{/if}}
</div>
<div class="border-left hidden-xs hidden-sm">
</div>
<div class="col-md-6 col-lg-7 border-left scrollable">
<div class="row padded-border">
{{outlet}}
</div>
</div>
</div>
</script>
<script type="text/x-handlebars" id="acl">
<div class="col-xs-12 col-sm-12 visible-xs visible-sm">
{{#link-to "nodes" class="btn btn-default btn-block" }}Back to all nodes{{/link-to}}
<hr>
</div>
<h3 class="no-margin">{{ model.Node }} <small> {{ model.Address }}</small></h3>
<hr>
<h5>Services</h5>
{{#each service in model.Services }}
{{#link-to 'services.show' service.Service tagName="div" href=false class="list-group-item list-condensed-link double-line" }}
<div class="list-bar-horizontal bg-light-gray"></div>
<div class="name">
{{service.Service}}
<small class="pull-right">
:{{service.Port}}
</small>
</div>
<ul class="list-inline sub">
{{#each tag in service.Tags}}
<li>{{tag}}</li>
{{/each}}
{{serviceTagMessage service.Tags}}
</ul>
{{/link-to}}
{{/each}}
<h5>Checks</h5>
{{#each check in model.Checks }}
<div class="panel">
{{ panelBar check.Status }}
<div class="panel-heading">
<h3 class="panel-title">
{{check.Name}}
<small>{{check.CheckID}}</small>
<span class="panel-note">{{check.Status}}</span>
</h3>
</div>
<div class="panel-body">
<h5>Notes</h5>
<p>{{ check.Notes }}</p>
<h5>Output</h5>
<pre>{{check.Output}}</pre>
</div>
</div>
{{/each}}
<h5>Lock Sessions</h5>
{{#if sessions }}
{{errorMessage}}
{{#each session in sessions }}
<div class="list-group-item list-condensed double-line">
<div class="bg-light-gray list-bar-horizontal"></div>
<div class="name">
{{ sessionName session }}
<button {{ action "invalidateSession" session.ID }} {{ bind-attr class=":btn :btn-danger :pull-right :btn-list isLoading:btn-warning" }}>Invalidate</button>
</div>
<ul class="list-inline sub">
{{#each check in session.Checks}}
<li class="bold">{{check}}</li>
{{/each}}
</ul>
</div>
{{/each}}
{{else}}
<p class="light small">No sessions</p>
{{/if}}
</script>
<script type="text/x-handlebars" id="index">
<div class="col-md-8 col-md-offset-2 col-xs-offset-0 col-sm-offset-0 col-xs-12 col-sm-12 vertical-center">
<h5>Select a datacenter</h5>

View File

@ -313,3 +313,36 @@ App.ServicesController = ItemBaseController.extend({
items: Ember.computed.alias("services"),
});
App.AclsIndexController = Ember.ArrayController.extend({
needs: ["dc", "application"],
queryParams: ["filter"],
dc: Ember.computed.alias("controllers.dc"),
isShowingItem: function() {
var currentPath = this.get('controllers.application.currentPath');
return (currentPath === "dc.acls.show");
}.property('controllers.application.currentPath'),
filteredContent: function() {
var filter = this.get('filter');
var items = this.get('items').filter(function(item, index, enumerable){
// First try to match on the name
var nameMatch = item.get('Name').toLowerCase().match(filter.toLowerCase());
if (nameMatch.length > 0) {
return nameMatch;
// Otherwise match on the ID
} else {
return item.get('ID').toLowerCase().match(filter.toLowerCase());
}
});
}.property('filter', 'items.@each'),
});
App.AclsShowController = Ember.ArrayController.extend({
needs: ["dc"],
dc: Ember.computed.alias("controllers.dc"),
});

View File

@ -239,3 +239,9 @@ App.Key = Ember.Object.extend(Ember.Validations.Mixin, {
return parts.join("/") + "/";
}.property('Key')
});
//
// An ACL
//
App.Acl = Ember.Object.extend({
});

View File

@ -25,7 +25,14 @@ App.Router.map(function() {
this.route("show", { path: "/*key" });
// Edit a specific key
this.route("edit", { path: "/*key/edit" });
})
});
// ACLs
this.resource("acls", { path: "/acls" }, function(){
this.route("show", { path: "/:name" });
});
// Shows a page explaining that ACLs haven't been set-up
this.route("aclsdisabled", { path: "/aclsdisabled" });
});
// Shows a datacenter picker. If you only have one

View File

@ -299,3 +299,36 @@ App.NodesRoute = App.BaseRoute.extend({
controller.set('nodes', model);
}
});
App.AclsRoute = App.BaseRoute.extend({
model: function(params) {
var dc = this.modelFor('dc').dc;
// Return a promise containing the ACLS
return Ember.$.getJSON('/v1/acl/list?dc=' + dc).then(function(data) {
objs = [];
data.map(function(obj){
objs.push(App.Acl.create(obj));
});
return objs;
});
},
actions: {
error: function(error, transition) {
// If consul returns 401, ACLs are disabled
if (error && error.status === 401) {
this.transitionTo('dc.aclsdisabled');
// If consul returns 403, they key isn't authorized for that
// action.
} else if (error && error.status === 403) {
this.transitionTo('dc.unauthorized');
}
return true;
}
},
setupController: function(controller, model) {
controller.set('acls', model);
}
});

View File

@ -62,3 +62,13 @@ App.KvListView = Ember.View.extend({
App.ActionBarView = Ember.View.extend({
templateName: 'actionbar'
});
// ACLS
App.AclView = Ember.View.extend({
templateName: 'acls',
});
App.AclsShowView = Ember.View.extend({
templateName: 'acl'
});