mirror of https://github.com/gophish/gophish
Added ng-table support (for future pagination, sorting, etc.)
Created services for campaigns/groups Changed modals to be binded to the data. Will improve on this soon! Added trailing slash to api endpoints (I hope to be able to remove this later)pull/24/head
parent
f1aade0bfa
commit
6cbc47e80c
|
@ -32,10 +32,10 @@ func CreateRouter() *nosurf.CSRFHandler {
|
||||||
api := router.PathPrefix("/api").Subrouter()
|
api := router.PathPrefix("/api").Subrouter()
|
||||||
api.HandleFunc("/", Use(API, mid.RequireLogin))
|
api.HandleFunc("/", Use(API, mid.RequireLogin))
|
||||||
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
|
api.HandleFunc("/reset", Use(API_Reset, mid.RequireLogin))
|
||||||
api.HandleFunc("/campaigns", Use(API_Campaigns, mid.RequireAPIKey))
|
api.HandleFunc("/campaigns/", Use(API_Campaigns, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey))
|
api.HandleFunc("/campaigns/{id:[0-9]+}", Use(API_Campaigns_Id, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/campaigns/id:[0-9]+}", Use(API_Campaigns_Id_Launch, mid.RequireAPIKey))
|
api.HandleFunc("/campaigns/id:[0-9]+}", Use(API_Campaigns_Id_Launch, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/groups", Use(API_Groups, mid.RequireAPIKey))
|
api.HandleFunc("/groups/", Use(API_Groups, mid.RequireAPIKey))
|
||||||
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
|
api.HandleFunc("/groups/{id:[0-9]+}", Use(API_Groups_Id, mid.RequireAPIKey))
|
||||||
|
|
||||||
// Setup static file serving
|
// Setup static file serving
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
var gophishApp = angular.module('gophishApp', []);
|
|
||||||
|
|
||||||
gophishApp.controller('CampaignCtrl', function($scope, $http) {
|
|
||||||
$http.get('/api/campaigns?api_key=' + API_KEY).success(function(data) {
|
|
||||||
$scope.campaigns = data;
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
gophishApp.controller('GroupCtrl', function($scope, $http) {
|
|
||||||
$http.get('/api/groups?api_key=' + API_KEY).success(function(data) {
|
|
||||||
$scope.groups = data;
|
|
||||||
})
|
|
||||||
})
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
var app = angular.module('gophish', ['ngTable', 'ngResource']);
|
||||||
|
|
||||||
|
app.factory('CampaignService', function($resource) {
|
||||||
|
return $resource('/api/campaigns/:id?api_key=' + API_KEY);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.factory('GroupService', function($resource) {
|
||||||
|
return $resource('/api/groups/:id?api_key=' + API_KEY);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.controller('CampaignCtrl', function($scope, CampaignService) {
|
||||||
|
CampaignService.query(function(campaigns){
|
||||||
|
$scope.campaigns = campaigns
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
app.controller('GroupCtrl', function($scope, GroupService) {
|
||||||
|
GroupService.query(function(groups) {
|
||||||
|
$scope.groups = groups
|
||||||
|
})
|
||||||
|
|
||||||
|
$scope.editGroup = function(group) {
|
||||||
|
if (group === 'new') {
|
||||||
|
$scope.newGroup = true;
|
||||||
|
$scope.group = {
|
||||||
|
name: '',
|
||||||
|
targets: [{
|
||||||
|
email: ''
|
||||||
|
}],
|
||||||
|
id: 0
|
||||||
|
};
|
||||||
|
|
||||||
|
} else {
|
||||||
|
$scope.newGroup = false;
|
||||||
|
$scope.group = group;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
|
@ -0,0 +1,13 @@
|
||||||
|
/*
|
||||||
|
AngularJS v1.2.11
|
||||||
|
(c) 2010-2014 Google, Inc. http://angularjs.org
|
||||||
|
License: MIT
|
||||||
|
*/
|
||||||
|
(function(H,a,A){'use strict';function D(p,g){g=g||{};a.forEach(g,function(a,c){delete g[c]});for(var c in p)p.hasOwnProperty(c)&&("$"!==c.charAt(0)&&"$"!==c.charAt(1))&&(g[c]=p[c]);return g}var v=a.$$minErr("$resource"),C=/^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/;a.module("ngResource",["ng"]).factory("$resource",["$http","$q",function(p,g){function c(a,c){this.template=a;this.defaults=c||{};this.urlParams={}}function t(n,w,l){function r(h,d){var e={};d=x({},w,d);s(d,function(b,d){u(b)&&(b=b());var k;if(b&&
|
||||||
|
b.charAt&&"@"==b.charAt(0)){k=h;var a=b.substr(1);if(null==a||""===a||"hasOwnProperty"===a||!C.test("."+a))throw v("badmember",a);for(var a=a.split("."),f=0,c=a.length;f<c&&k!==A;f++){var g=a[f];k=null!==k?k[g]:A}}else k=b;e[d]=k});return e}function e(a){return a.resource}function f(a){D(a||{},this)}var F=new c(n);l=x({},B,l);s(l,function(h,d){var c=/^(POST|PUT|PATCH)$/i.test(h.method);f[d]=function(b,d,k,w){var q={},n,l,y;switch(arguments.length){case 4:y=w,l=k;case 3:case 2:if(u(d)){if(u(b)){l=
|
||||||
|
b;y=d;break}l=d;y=k}else{q=b;n=d;l=k;break}case 1:u(b)?l=b:c?n=b:q=b;break;case 0:break;default:throw v("badargs",arguments.length);}var t=this instanceof f,m=t?n:h.isArray?[]:new f(n),z={},B=h.interceptor&&h.interceptor.response||e,C=h.interceptor&&h.interceptor.responseError||A;s(h,function(a,b){"params"!=b&&("isArray"!=b&&"interceptor"!=b)&&(z[b]=G(a))});c&&(z.data=n);F.setUrlParams(z,x({},r(n,h.params||{}),q),h.url);q=p(z).then(function(b){var d=b.data,k=m.$promise;if(d){if(a.isArray(d)!==!!h.isArray)throw v("badcfg",
|
||||||
|
h.isArray?"array":"object",a.isArray(d)?"array":"object");h.isArray?(m.length=0,s(d,function(b){m.push(new f(b))})):(D(d,m),m.$promise=k)}m.$resolved=!0;b.resource=m;return b},function(b){m.$resolved=!0;(y||E)(b);return g.reject(b)});q=q.then(function(b){var a=B(b);(l||E)(a,b.headers);return a},C);return t?q:(m.$promise=q,m.$resolved=!1,m)};f.prototype["$"+d]=function(b,a,k){u(b)&&(k=a,a=b,b={});b=f[d].call(this,b,this,a,k);return b.$promise||b}});f.bind=function(a){return t(n,x({},w,a),l)};return f}
|
||||||
|
var B={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},E=a.noop,s=a.forEach,x=a.extend,G=a.copy,u=a.isFunction;c.prototype={setUrlParams:function(c,g,l){var r=this,e=l||r.template,f,p,h=r.urlParams={};s(e.split(/\W/),function(a){if("hasOwnProperty"===a)throw v("badname");!/^\d+$/.test(a)&&(a&&RegExp("(^|[^\\\\]):"+a+"(\\W|$)").test(e))&&(h[a]=!0)});e=e.replace(/\\:/g,":");g=g||{};s(r.urlParams,function(d,c){f=g.hasOwnProperty(c)?
|
||||||
|
g[c]:r.defaults[c];a.isDefined(f)&&null!==f?(p=encodeURIComponent(f).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),e=e.replace(RegExp(":"+c+"(\\W|$)","g"),function(a,c){return p+c})):e=e.replace(RegExp("(/?):"+c+"(\\W|$)","g"),function(a,c,d){return"/"==d.charAt(0)?d:c+d})});e=e.replace(/\/+$/,"")||"/";e=e.replace(/\/\.(?=\w+($|\?))/,".");c.url=e.replace(/\/\\\./,"/.");s(g,function(a,
|
||||||
|
e){r.urlParams[e]||(c.params=c.params||{},c.params[e]=a)})}};return t}])})(window,window.angular);
|
||||||
|
//# sourceMappingURL=angular-resource.min.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,6 +1,6 @@
|
||||||
{{% define "base" %}}
|
{{% define "base" %}}
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" ng-app="gophishApp">
|
<html lang="en" ng-app="gophish">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
@ -37,7 +37,9 @@
|
||||||
<script src="/js/jquery.js"></script>
|
<script src="/js/jquery.js"></script>
|
||||||
<script src="/js/bootstrap.min.js"></script>
|
<script src="/js/bootstrap.min.js"></script>
|
||||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
|
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
|
||||||
<script src="/js/app/controllers.js"></script>
|
<script src="/js/ng-resource.min.js"></script>
|
||||||
|
<script src="/js/ng-table.min.js"></script>
|
||||||
|
<script src="/js/app/gophish.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<table class="table table-hover table-striped table-bordered">
|
<table ng-table class="table table-hover table-striped table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-sm-1">Date</th>
|
<th class="col-sm-1">Date</th>
|
||||||
|
@ -43,12 +43,12 @@
|
||||||
<span class="sr-only">Toggle Dropdown</span>
|
<span class="sr-only">Toggle Dropdown</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" style="left:auto; right:0;" role="menu">
|
<ul class="dropdown-menu" style="left:auto; right:0;" role="menu">
|
||||||
<li><a href="/settings">View</a>
|
<li><a ng-href="/campaigns/{{campaign.id}}">View</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/settings">Edit</a>
|
<li><a href="/campaigns/{{campaign.id}}/relaunch">Relaunch</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="/logout">Delete</a>
|
<li><a href="/campaigns/{{campaign.id}}/delete">Delete</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container" ng-controller="GroupCtrl">
|
||||||
<div class="col-md-3 sidebar">
|
<div class="col-md-3 sidebar">
|
||||||
<ul class="nav nav-pills nav-stacked">
|
<ul class="nav nav-pills nav-stacked">
|
||||||
<li><a href="/">Dashboard</a>
|
<li><a href="/">Dashboard</a>
|
||||||
|
@ -19,13 +19,13 @@
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-9" ng-controller="GroupCtrl">
|
<div class="col-md-9">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#newGroupModal"><i class="fa fa-plus"></i> New Group</button>
|
<button type="button" class="btn btn-primary" ng-click="editGroup('new')" data-toggle="modal" data-target="#newGroupModal"><i class="fa fa-plus"></i> New Group</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<table class="table table-hover table-striped table-bordered">
|
<table ng-table class="table table-hover table-striped table-bordered">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="col-sm-1">Name</th>
|
<th class="col-sm-1">Name</th>
|
||||||
|
@ -46,12 +46,12 @@
|
||||||
<span class="sr-only">Toggle Dropdown</span>
|
<span class="sr-only">Toggle Dropdown</span>
|
||||||
</button>
|
</button>
|
||||||
<ul class="dropdown-menu" style="left:auto; right:0;" role="menu">
|
<ul class="dropdown-menu" style="left:auto; right:0;" role="menu">
|
||||||
<li><a href="/settings">View</a>
|
<li><a ng-href="/groups/{{group.id}}">View</a>
|
||||||
</li>
|
</li>
|
||||||
<li><a href="/settings">Edit</a>
|
<li><a ng-click="editGroup(group)" data-toggle="modal" ng-href="#" data-target="#newGroupModal">Edit</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="divider"></li>
|
<li class="divider"></li>
|
||||||
<li><a href="/logout">Delete</a>
|
<li><a ng-href="/groups/{{group.id}}/delete">Delete</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
@ -62,37 +62,38 @@
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<!-- New Campaign Modal -->
|
||||||
<!-- New Campaign Modal -->
|
<div class="modal" id="newGroupModal" tabindex="-1" role="dialog" aria-labelledby="groupModalLabel" aria-hidden="true" ng-controller="GroupCtrl">
|
||||||
<div class="modal" id="newGroupModal" tabindex="-1" role="dialog" aria-labelledby="groupModalLabel" aria-hidden="true">
|
<div class="modal-dialog">
|
||||||
<div class="modal-dialog">
|
<div class="modal-content">
|
||||||
<div class="modal-content">
|
<div class="modal-header">
|
||||||
<div class="modal-header">
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
<h4 class="modal-title" ng-hide="newGroup" id="groupModalLabel">Edit Group: {{group.name}}</h4>
|
||||||
<h4 class="modal-title" id="groupModalLabel">New Group</h4>
|
<h4 class="modal-title" ng-show="newGroup" id="groupModalLabel">New Group</h4>
|
||||||
|
</div>
|
||||||
|
<form action="/">
|
||||||
|
<div class="modal-body">
|
||||||
|
<label class="control-label" for="name">Name:</label>
|
||||||
|
<div class="form-group">
|
||||||
|
<input type="text" class="form-control" placeholder="Group name" id="name" value={{group.name}} />
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button class="btn btn-danger"><i class="fa fa-plus"></i> Bulk Import Users</button>
|
||||||
|
</div>
|
||||||
|
<label class="control-label" for="users">Users:</label>
|
||||||
|
<div class="input-group">
|
||||||
|
<input type="email" class="form-control" placeholder="test@example.com" id="users" />
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn btn-primary"><i class="fa fa-plus"></i> Add</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
||||||
|
<button type="button" class="btn btn-primary" type="submit">Save Group</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<form action="/">
|
|
||||||
<div class="modal-body">
|
|
||||||
<label class="control-label" for="name">Name:</label>
|
|
||||||
<div class="form-group">
|
|
||||||
<input type="text" class="form-control" placeholder="Group name" id="name" />
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<button class="btn btn-danger"><i class="fa fa-plus"></i> Bulk Import Users</button>
|
|
||||||
</div>
|
|
||||||
<label class="control-label" for="users">Users:</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="email" class="form-control" placeholder="test@example.com" id="users" />
|
|
||||||
<span class="input-group-btn">
|
|
||||||
<button class="btn btn-primary"><i class="fa fa-plus"></i> Add</button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
|
|
||||||
<button type="button" class="btn btn-primary" type="submit">Save Group</button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue