Merge branch 'challenge' into develop

Conflicts:
	webgoat-container/src/main/resources/static/css/main.css
This commit is contained in:
Nanne Baars
2017-05-04 03:02:00 +02:00
145 changed files with 3992 additions and 965 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 KiB

View File

@ -152,7 +152,7 @@ img {
margin-left: 1.5em;*/
margin-right: 5px;
margin-top: -38px; /* << don't like doing this, but otherwise it does not line up correctly */
color:#0F0
color:#88FB88 /* #0F0 */
}
/* ==========================================================================
@ -958,8 +958,52 @@ cookie-container {
cursor:pointer;
}
.page-nav-wrapper {
display:inline-block;
width: 30px;
}
.attack-link, .page-link {
display: inline-block;
background-color: #555;
border-radius: 8px;
min-width: 20px;
text-align: center;
font-weight: bold;
padding-top:2px;
}
.attack-link.solved-true {
color:#88FB88;
}
.attack-link.solved-false {
color:#f2baba;
}
.attack-link.cur-page, .page-link.cur-page {
color:#fff;
}
.page-link {
color:#eee;
}
.page-link-wrapper {
display:inline-block;
}
.page-link-wrapper span {
margin: 3px;
}
.cur-page {
border-bottom: 2px solid #000;
color:#aaa;
}
span.show-next-page, span.show-prev-page {
font-size: 1.3em;
font-size: 1.3em;
}
.show-prev-page {
@ -970,6 +1014,8 @@ font-size: 1.3em;
cursor:pointer;
}
/* attack ... */
.attack-feedback {
font-weight:800;
}
@ -984,10 +1030,11 @@ font-size: 1.3em;
}
#lesson-hint {
background-color: #ccc;
background-color: #f1f1f1;
border-radius: 4px;
border-color: #999;
margin-top:4px;
border-color: #4fa44c;
margin-top: 4px;
border: 2px solid #24b054;
}
#hintsViewTop{
@ -1043,6 +1090,60 @@ font-size: 1.3em;
padding: 10px;
}
/* temp override
//TODO: come up with longer term solution for full-window viewing
*/
.col-md-8 {
width: 95% !important;
width: 95% !important
}
/* scoreboard */
div.scoreboard-title {
font-size:xx-large;
}
.scoreboard-table tr {
}
div.scoreboard-username {
background-color: #222;
color: aliceblue;
padding: 4px;
padding-left:8px;
font-size: x-large;
border-radius:6px;
}
th.username {
padding-bottom: 6px;
}
td.user-flags {
padding-left: 8px;
padding-bottom: 6px;
}
div.captured-flag {
border-radius: 6px;
background-color: #444;
color: white;
padding: 4px;
font-size: x-large;
display: inline-block;
}
.scoreboard-page {
background-color: #e0dfdc;
padding: 20px;
}
.fa-flag {
color:red
}
.appseceu-banner {
background: url('img/appseceu-17.png') no-repeat 0px 0px;
height: 117px;
width: 1268px;
margin-bottom: 20px;
}

View File

@ -3,12 +3,11 @@ define(['jquery',
'libs/backbone',
'goatApp/model/LessonContentModel',
'goatApp/view/LessonContentView',
'goatApp/view/PlanView',
'goatApp/view/SourceView',
'goatApp/view/SolutionView',
// 'goatApp/view/PlanView',
// 'goatApp/view/SourceView',
// 'goatApp/view/SolutionView',
'goatApp/view/HintView',
'goatApp/view/HelpControlsView',
'goatApp/view/CookieView',
'goatApp/view/ParamView',
'goatApp/model/ParamModel',
'goatApp/view/DeveloperControlsView',
@ -27,12 +26,11 @@ define(['jquery',
Backbone,
LessonContentModel,
LessonContentView,
PlanView,
SourceView,
SolutionView,
// PlanView,
// SourceView,
// SolutionView,
HintView,
HelpControlsView,
CookieView,
ParamView,
ParamModel,
DeveloperControlsView,
@ -66,13 +64,29 @@ define(['jquery',
this.menuButtonView = new MenuButtonView();
this.listenTo(this.lessonContentView, 'assignment:complete', this.updateMenu);
this.listenTo(this.lessonContentView, 'assignment:complete', this.updateLessonOverview);
this.listenTo(this.lessonContentView, 'endpoints:filtered', this.filterPageHints);
};
this.loadLesson = function(name,pageNum) {
this.filterPageHints = function(endpoints) {
//filter hints for page by
this.lessonHintView.filterHints(endpoints);
}
this.onHideHintsButton = function() {
this.helpControlsView.hideHintsButton();
}
this.onShowHintsButton = function() {
this.helpControlsView.showHintsButton();
}
this.loadLesson = function(name,pageNum) {
if (this.name === name) {
this.listenTo(this.lessonHintView, 'hints:showButton', this.onShowHintsButton);
this.listenTo(this.lessonHintView, 'hints:hideButton', this.onHideHintsButton);
this.lessonContentView.navToPage(pageNum);
this.lessonHintView.hideHints();
//this.lessonHintView.selectHints();
this.titleView.render(this.lessonInfoModel.get('lessonTitle'));
return;
}
@ -82,10 +96,10 @@ define(['jquery',
//TODO: implement lesson not found or return to welcome page?
}
this.lessonContent.loadData({'name':name});
this.planView = {};
this.solutionView = {};
this.sourceView = {};
this.lessonHintView = {};
// this.planView = {};
// this.solutionView = {};
// this.sourceView = {};
// this.lessonHintView = {};
this.name = name;
};
@ -98,15 +112,13 @@ define(['jquery',
this.listenTo(this.helpControlsView,'hints:show',this.showHints);
this.listenTo(this.helpControlsView,'lessonOverview:show',this.showLessonOverview)
this.listenTo(this.helpControlsView,'solution:show',this.hideShowHelps);
this.listenTo(this.helpControlsView,'source:show',this.hideShowHelps);
this.listenTo(this.helpControlsView,'lesson:restart',this.restartLesson);
this.listenTo(this.developerControlsView, 'dev:labels', this.restartLesson);
this.helpControlsView.render();
this.lessonOverview.hideLessonOverview();
this.titleView.render(this.lessonInfoModel.get('lessonTitle'));
this.helpControlsView.showHideHintsButton({});
};
this.updateMenu = function() {
@ -126,11 +138,14 @@ define(['jquery',
this.lessonContentView.model = this.lessonContent;
this.lessonContentView.render();
this.planView = new PlanView();
this.solutionView = new SolutionView();
this.sourceView = new SourceView();
//this.planView = new PlanView();
//this.solutionView = new SolutionView();
//this.sourceView = new SourceView();
if (this.lessonHintView) {
this.lessonHintView.stopListening();
this.lessonHintView = null;
}
this.lessonHintView = new HintView();
this.cookieView = new CookieView();
//TODO: instantiate model with values (not sure why was not working before)
var paramModel = new ParamModel({});
@ -150,34 +165,34 @@ define(['jquery',
this.helpsLoaded[curHelp.helpElement] = curHelp.value;
};
this.hideShowHelps = function(showHelp) {
var showId = '#lesson-' + showHelp + '-row';
var contentId = '#lesson-' + showHelp + '-content';
$('.lesson-help').not(showId).hide();
if (!showId) {
return;
}
if ($(showId).is(':visible')) {
$(showId).hide();
return;
} else {
//TODO: move individual .html operations into individual help views
switch(showHelp) {
case 'plan':
$(contentId).html(this.planView.model.get('content'));
break;
case 'solution':
$(showId).html(this.solutionView.model.get('content'));
break;
case 'source':
$(contentId).html('<pre>' + this.sourceView.model.get('content') + '</pre>');
break;
}
$(showId).show();
GoatUtils.scrollToHelp()
}
};
// this.hideShowHelps = function(showHelp) {
// var showId = '#lesson-' + showHelp + '-row';
// var contentId = '#lesson-' + showHelp + '-content';
// $('.lesson-help').not(showId).hide();
// if (!showId) {
// return;
// }
//
// if ($(showId).is(':visible')) {
// $(showId).hide();
// return;
// } else {
// //TODO: move individual .html operations into individual help views
// switch(showHelp) {
// case 'plan':
// $(contentId).html(this.planView.model.get('content'));
// break;
// case 'solution':
// $(showId).html(this.solutionView.model.get('content'));
// break;
// case 'source':
// $(contentId).html('<pre>' + this.sourceView.model.get('content') + '</pre>');
// break;
// }
// $(showId).show();
// GoatUtils.scrollToHelp()
// }
// };
this.showHints = function() {
this.lessonHintView.render();
@ -194,6 +209,7 @@ define(['jquery',
method:'GET'
}).done(function(lessonLink) {
self.loadLesson(self.name);
self.updateMenu();
});
};

View File

@ -1,13 +1,13 @@
define(['jquery',
'underscore',
'backbone',
'goatApp/model/CookieModel'],
'goatApp/model/FlagModel'],
function($,
_,
Backbone,
CookieModel) {
FlagModel) {
return Backbone.Collection.extend({
url:'service/cookie.mvc',
model:CookieModel
url:'/WebGoat/scoreboard-data',
model:FlagModel
});
});

View File

@ -20,7 +20,6 @@ define(['jquery',
loadData: function(options) {
this.urlRoot = _.escape(encodeURIComponent(options.name)) + '.lesson'
var self = this;
this.fetch().done(function(data) {
self.setContent(data);
@ -32,7 +31,8 @@ define(['jquery',
loadHelps = true;
}
this.set('content',content);
this.set('lessonUrl',document.URL);
this.set('lessonUrl',document.URL.replace(/\.lesson.*/,'.lesson'));
this.set('pageNum',document.URL.replace(/.*\.lesson\/(\d{1,4})$/,'$1'));
this.trigger('content:loaded',this,loadHelps);
},

View File

@ -3,7 +3,7 @@ define([
function(
Backbone) {
return Backbone.Collection.extend({
tagName: 'ul',
//tagName: 'ul',
url: 'service/lessonoverview.mvc'
});
});

View File

@ -0,0 +1,17 @@
define(['jquery',
'underscore',
'backbone',
'goatApp/support/goatAsyncErrorHandler',
'goatApp/view/ScoreboardView'],
function ($,
_,
Backbone,
asyncErrorHandler,
ScoreboardView) {
'use strict'
return {
initApp: function () {
scoreboard = new ScoreboardView();
}
};
});

View File

@ -0,0 +1,16 @@
<div>
<div class="page-nav-wrapper"><span class="glyphicon-class glyphicon glyphicon-circle-arrow-left show-prev-page"></span></div>
<div class="page-link-wrapper">
<% var baseUrl = overview.baseUrl; %>
<% _.each(overview.pages, function(page,index) { %>
<a href="<%=overview.baseUrl%>/<%=index%>" alt="Page <%=index++ %>">
<% if (page.content === 'assignment') { %>
<div class="<%=page.pageClass%> <%=page.solvedClass%> <%=page.curPageClass%>"><%=index++%></div>
<% } else { %>
<div class="<%=page.pageClass%> <%=page.curPageClass%>"><%=index++%></div>
<% } %>
</a>
<% }); %>
</div>
<div class="page-nav-wrapper"><span class="glyphicon-class glyphicon glyphicon-circle-arrow-right show-next-page"></span></div>
</div>

View File

@ -0,0 +1,16 @@
<div class="scoreboard-title">WebGoat Challenge - AppSec EU 2017</div>
<div class="appseceu-banner">banner here</div>
<table class="scoreboard-table">
<% _.each(rankings, function(userRanking, index) { %>
<tr>
<th class="username"> <div class="scoreboard-username"><%= index%> <%=userRanking.username %> </div></th>
<td class="user-flags"> <% _.each(userRanking.flagsCaptured, function(flag) { %>
<div class="captured-flag">
<i class="fa fa-flag" aria-hidden="true"></i>
<%=flag%> </div>
<% }); %>
</td>
</tr>
<% }); %>
</table>

View File

@ -1,34 +0,0 @@
define(['jquery',
'underscore',
'backbone',
'goatApp/model/CookieCollection'],
function($,
_,
Backbone,
CookieCollection) {
return Backbone.View.extend({
el:'#cookies-view',
initialize: function() {
this.collection = new CookieCollection();
this.listenTo(this.collection,'reset',this.render)
this.collection.fetch({reset:true});
},
render: function() {
this.$el.html('')
var cookieTable;
this.collection.each(function(model) {
cookieTable = $('<table>',{'class':'cookie-table table-striped table-nonfluid'});
_.each(model.keys(), function(attribute) {
var newRow = $('<tr>');
newRow.append($('<th>',{text:_.escape(attribute)}))
newRow.append($('<td>',{text:_.escape(model.get(attribute))}));
cookieTable.append(newRow);
});
});
this.$el.append($('<h4>',{text:'Cookie/s'}));
this.$el.append(cookieTable);
}
});
});

View File

@ -12,18 +12,14 @@ function($,_,Backbone) {
this.hasPlan = options.hasPlan;
this.hasSolution = options.hasSolution;
this.hasSource = options.hasSource;
var self = this;
Backbone.on('navigatedToPage', function(nav) {
self.showHideHintsButton(nav)
});
},
showHideHintsButton: function(nav) {
if (typeof nav['assignmentPath'] !== 'undefined') {
this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show();
} else {
$('#show-hints-button').hide();
}
showHintsButton: function(nav) {
this.$el.find('#show-hints-button').unbind().on('click',this.showHints.bind(this)).show();
},
hideHintsButton: function(){
$('#show-hints-button').hide();
},
render:function(title) {
@ -38,7 +34,7 @@ function($,_,Backbone) {
this.$el.find('#show-solution-button').unbind().on('click',_.bind(this.showSolution,this)).show();
}
this.$el.find('#show-lesson-overview-button').unbind().on('click', _.bind(this.showLessonOverview, this)).show();
//this.$el.find('#show-lesson-overview-button').unbind().on('click', _.bind(this.showLessonOverview, this)).show();
this.$el.find('#restart-lesson-button').unbind().on('click',_.bind(this.restartLesson,this)).show();
},

View File

@ -19,8 +19,10 @@ function($,
this.listenTo(this.collection,'loaded',this.onModelLoaded);
this.hideHints();
var self = this;
// different way to do this?
Backbone.on('navigatedToPage', function(nav){
self.selectHints(nav)
self.selectHints(nav);
// end event delegation??
});
},
@ -61,14 +63,25 @@ function($,
*
* @param nav the json structure for navigating
*/
selectHints: function(nav) {
this.curHint = 0;
var assignmentPath = nav['assignmentPath'];
if (assignmentPath != null) {
this.hintsToShow = this.collection.getHintsForAssignment(assignmentPath);
filterHints: function(endpoints) {
this.hintsToShow = [];
_.each(endpoints, this.filterHint, this);
if (this.hintsToShow.length > 0) {
this.trigger('hints:showButton');
} else {
this.hintsToShow = new Array();
}
this.trigger('hints:hideButton');
}
},
filterHint: function(endpoint) {
var self = this;
_.each(this.collection.models, function(hintModel) {
if (endpoint.indexOf(hintModel.get('assignmentPath')) > -1) {
self.hintsToShow.push(hintModel.get('hint'));
}
});
console.log(this.hintsToShow);
},
onModelLoaded: function() {
@ -97,7 +110,7 @@ function($,
if(this.hintsToShow.length == 0) {
// this.hideHints();
} else {
this.$el.find('#lesson-hint-content').html(polyglot.t(this.hintsToShow[curHint].get('hint')));
this.$el.find('#lesson-hint-content').html(polyglot.t(this.hintsToShow[curHint]));
}
},

View File

@ -3,13 +3,15 @@ define(['jquery',
'underscore',
'backbone',
'libs/jquery.form',
'goatApp/view/ErrorNotificationView'],
'goatApp/view/ErrorNotificationView',
'goatApp/view/PaginationControlView'],
function(
$,
_,
Backbone,
JQueryForm,
ErrorNotificationView) {
ErrorNotificationView,
PaginationControlView) {
return Backbone.View.extend({
el:'#lesson-content-wrapper', //TODO << get this fixed up in DOM
@ -37,7 +39,7 @@ define(['jquery',
return -1;
},
/* initial renering */
/* initial rendering */
render: function() {
this.$el.find('.lesson-content').html(this.model.get('content'));
this.$el.find('.attack-feedback').hide();
@ -45,31 +47,17 @@ define(['jquery',
this.makeFormsAjax();
//this.ajaxifyAttackHref();
$(window).scrollTop(0); //work-around til we get the scroll down sorted out
this.initPagination();
var startPageNum = this.model.get('pageNum');
this.initPagination(startPageNum);
},
initPagination: function() {
initPagination: function(startPageNum) {
//get basic pagination info
this.currentPage = 0;
this.$contentPages = this.$el.find('.lesson-page-wrapper');
this.numPages = this.$contentPages.length;
//
this.addPaginationControls();
if (this.numPages > 1) {
//no animation on init
this.$contentPages.hide();
this.$el.find(this.$contentPages[this.currentPage]).show();
this.showNextPageButton();
this.hidePrevPageButton();
} else if (this.numPages === 1) {
this.hideNextPageButton();
this.hidePrevPageButton();
}
},
setCurrentPage: function (pageNum) {
this.currentPage = (_.isNumber(pageNum) && pageNum < this.numPages) ? pageNum : 0;
var currentPage = (!isNaN(startPageNum) && startPageNum && startPageNum < this.$contentPages) ? startPageNum : 0;
//init views & pagination
this.showCurContentPage(currentPage);
this.paginationControlView = new PaginationControlView(this.$contentPages,this.model.get('lessonUrl'));
},
getCurrentPage: function () {
@ -160,128 +148,29 @@ define(['jquery',
this.$curOutput.show(400)
},
/* create, show & hide pagination controls */
addPaginationControls: function() {
var pagingControlsDiv;
//this.$el.html();
//prev
var prevPageButton = $('<span>',{class:'glyphicon-class glyphicon glyphicon-circle-arrow-left show-prev-page'});
prevPageButton.unbind().on('click',this.decrementPageView.bind(this));
//next
var nextPageButton = $('<span>',{class:'glyphicon-class glyphicon glyphicon-circle-arrow-right show-next-page'});
nextPageButton.unbind().on('click',this.incrementPageView.bind(this));
//add to DOM
if (this.$el.find('#lesson-page-controls').length < 1) {
pagingControlsDiv = $('<div>',{class:'panel-body', id:'lesson-page-controls'});
pagingControlsDiv.append(prevPageButton);
pagingControlsDiv.append(nextPageButton);
this.$el.find('.lesson-page-controls').append(pagingControlsDiv);
}
},
showPrevPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').show();
},
hidePrevPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').hide();
},
showNextPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').show();
},
hideNextPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
},
/* increment, decrement & display handlers */
incrementPageView: function() {
if (this.currentPage < this.numPages -1) {
this.currentPage++;
window.location.href = this.model.get('lessonUrl') + '/' + this.currentPage;
//this.showCurContentPage(true);Con
}
if (this.currentPage > 0) {
this.showPrevPageButton();
}
if (this.currentPage >= this.numPages -1) {
this.hideNextPageButton();
this.showPrevPageButton;
}
},
decrementPageView: function() {
if (this.currentPage > 0) {
this.currentPage--;
window.location.href = this.model.get('lessonUrl') + '/' + this.currentPage;
//this.showCurContentPage(false);
}
if (this.currentPage < this.numPages -1) {
this.showNextPageButton();
}
if (this.currentPage == 0) {
this.hidePrevPageButton();
this.showNextPageButton()
}
},
showCurContentPage: function(isIncrement) {
showCurContentPage: function(pageNum) {
this.$contentPages.hide();
this.$el.find(this.$contentPages[this.currentPage]).show();
this.$el.find(this.$contentPages[pageNum]).show();
},
findAssigmentEndpointOnPage: function(pageNumber) {
var contentPage = this.$contentPages[this.currentPage];
var form = $('form.attack-form', contentPage);
var action = form.attr('action')
if (action !== undefined) {
return action;
findAssigmentEndpointsOnPage: function(pageNumber) {
var contentPage = this.$contentPages[pageNumber];
var endpoints = []; //going to assume uniqueness since these are assignments
var pageForms = $(contentPage).find('form.attack-form');
for (var i=0; i<pageForms.length; i++) {
endpoints.push(pageForms[i].action);
}
console.log(endpoints);
return endpoints;
},
navToPage: function (pageNum) {
this.setCurrentPage(pageNum);//provides validation
this.showCurContentPage(this.currentPage);
this.hideShowNavButtons();
var assignmentPath = this.findAssigmentEndpointOnPage(pageNum);
Backbone.trigger('navigatedToPage',{'pageNumber':pageNum, 'assignmentPath' : assignmentPath});
},
hideShowNavButtons: function () {
//one page only
if (this.numPages === 1) {
this.hidePrevPageButton();
this.hideNextPageButton();
}
//first page
if (this.currentPage === 0) {
this.hidePrevPageButton();
if (this.numPages > 1) {
this.showNextPageButton();
}
return;
}
// > first page, but not last
if (this.currentPage > 0 && this.currentPage < this.numPages -1) {
this.showNextPageButton();
this.showPrevPageButton();
return;
}
// last page and more than one page
if (this.currentPage === this.numPages -1 && this.numPages > 1) {
this.hideNextPageButton();
this.showPrevPageButton();
return;
}
this.paginationControlView.setCurrentPage(pageNum);//provides validation
this.showCurContentPage(this.paginationControlView.currentPage);
this.paginationControlView.render();
this.paginationControlView.hideShowNavButtons();
var assignmentPaths = this.findAssigmentEndpointsOnPage(pageNum);
this.trigger('endpoints:filtered',assignmentPaths);
},
/* for testing */

View File

@ -39,7 +39,7 @@ function($,
} else {
this.$el.show();
}
this.showAssignments();
//this.showAssignments();
return this;
},

View File

@ -0,0 +1,186 @@
define(['jquery',
'underscore',
'backbone',
'goatApp/model/LessonOverviewModel',
'text!templates/paging_controls.html'],
function ($,
_,
Backbone,
LessonOverviewModel,
PaginationTemplate) {
return Backbone.View.extend({
template: PaginationTemplate,
el: '#lesson-page-controls',
initialize: function ($contentPages,baseLessonUrl) {
this.$contentPages = $contentPages;
this.model = new LessonOverviewModel();
this.listenTo(this.model, 'change add remove update reset', this.render);
this.numPages = this.$contentPages.length;
this.baseUrl = baseLessonUrl;
this.model.fetch();
this.initPagination();
this.render();
},
render: function () {
this.parseLinks();
var t = _.template(this.template);
this.$el.html(t({'overview':this.lessonOverview}));
this.bindNavButtons();
this.hideShowNavButtons();
},
bindNavButtons: function() {
this.$el.find('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').unbind().on('click',this.incrementPageView.bind(this));
this.$el.find('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').unbind().on('click', this.decrementPageView.bind(this));
this.navButtonsBound = true;
},
parseLinks: function() {
var assignmentCount = this.$contentPages.find('.attack-container');
var solvedMap = {};
var pages = [];
// one pass on solved assignmets
_.each(this.model.toJSON(), function(assignment) {
if (assignment.solved) {
var key = assignment.assignment.path; //.replace(/\//g,'');
solvedMap[key] = assignment.assignment.name;
}
});
isAttackSolved = function (path) {
//strip
var newPath = path.replace(/^\/WebGoat/,'');
if (typeof solvedMap[newPath] !== 'undefined') {
return true;
}
return false;
};
var self = this;
var pages, pageClass, solved;
_.each(this.$contentPages,function(page,index) {
var curPageClass = (self.currentPage == index) ? ' cur-page' : '';
if ($(page).find('.attack-container').length < 1) { // no assignments [attacks]
pageClass = 'page-link';
pages.push({content:'content',pageClass:pageClass,curPageClass:curPageClass});
} else {
var $assignmentForms = $(page).find('.attack-container form');
// use for loop to avoid anonymous function scope hell
//var pageAssignments = {content:'attack',attacks:[]}
pageClass = 'attack-link'
var solvedClass = 'solved-true'
for (var i=0; i< $assignmentForms.length; i++) {
//normalize path
var action = $assignmentForms.attr('action');//.replace(/\//g,'');
if (action && isAttackSolved(action)) {
//pageClass = 'fa fa-check-square-o assignment-solved';
//pageAssignments.attacks.push({solved:true});
} else {
solvedClass = 'solved-false';
}
}
pages.push({solvedClass:solvedClass,content:'assignment',curPageClass:curPageClass,pageClass:pageClass});
}
});
//assign to the view
this.lessonOverview = {
baseUrl: this.baseUrl,
pages: pages
}
},
showPrevPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').show();
},
hidePrevPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-left.show-prev-page').hide();
},
showNextPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').show();
},
hideNextPageButton: function() {
$('span.glyphicon-class.glyphicon.glyphicon-circle-arrow-right.show-next-page').hide();
},
initPagination: function() {
//track pagination state in this view ... start at 0
this.currentPage = 0;
},
setCurrentPage: function (pageNum) {
this.currentPage = (_.isNumber(pageNum) && pageNum < this.numPages) ? pageNum : 0;
},
/* increment, decrement & display handlers */
incrementPageView: function() {
if (this.currentPage < this.numPages -1) {
this.currentPage++;
window.location.href = this.baseUrl + '/' + this.currentPage;
}
if (this.currentPage > 0) {
this.showPrevPageButton();
}
if (this.currentPage >= this.numPages -1) {
this.hideNextPageButton();
this.showPrevPageButton;
}
this.render();
},
decrementPageView: function() {
if (this.currentPage > 0) {
this.currentPage--;
window.location.href = this.baseUrl + '/' + this.currentPage;
}
if (this.currentPage < this.numPages -1) {
this.showNextPageButton();
}
if (this.currentPage == 0) {
this.hidePrevPageButton();
this.showNextPageButton()
}
this.render();
},
hideShowNavButtons: function () {
//one page only
if (this.numPages === 1) {
this.hidePrevPageButton();
this.hideNextPageButton();
}
//first page
if (this.currentPage === 0) {
this.hidePrevPageButton();
if (this.numPages > 1) {
this.showNextPageButton();
}
return;
}
// > first page, but not last
if (this.currentPage > 0 && this.currentPage < this.numPages -1) {
this.showNextPageButton();
this.showPrevPageButton();
return;
}
// last page and more than one page
if (this.currentPage === this.numPages -1 && this.numPages > 1) {
this.hideNextPageButton();
this.showPrevPageButton();
return;
}
},
});
});

View File

@ -0,0 +1,32 @@
define(['jquery',
'underscore',
'backbone',
'goatApp/model/FlagsCollection',
'text!templates/scoreboard.html'],
function($,
_,
Backbone,
FlagsCollection,
ScoreboardTemplate) {
return Backbone.View.extend({
el:'#scoreboard',
initialize: function() {
this.template = ScoreboardTemplate,
this.collection = new FlagsCollection();
this.listenTo(this.collection,'reset',this.render)
this.collection.fetch({reset:true});
},
render: function() {
//this.$el.html('test');
var t = _.template(this.template);
this.$el.html(t({'rankings':this.collection.toJSON()}));
setTimeout(this.pollData.bind(this), 5000);
},
pollData: function() {
this.collection.fetch({reset:true});
}
});
});

View File

@ -0,0 +1,47 @@
//main.js
/*
/js
js/main.js << main file for require.js
--/libs/(jquery,backbone,etc.) << base libs
--/goatApp/ << base dir for goat application, js-wise
--/goatApp/model
--/goatApp/view
--/goatApp/support
--/goatApp/controller
*/
require.config({
baseUrl: "js/",
paths: {
jquery: 'libs/jquery-2.2.4.min',
jqueryui: 'libs/jquery-ui-1.10.4',
underscore: 'libs/underscore-min',
backbone: 'libs/backbone-min',
text: 'libs/text',
templates: 'goatApp/templates',
polyglot: 'libs/polyglot.min'
},
map: {
'libs/jquery-base' : {'jquery':'libs/jquery-2.2.4.min'},
'libs/jquery-vuln' : {'jquery':'libs/jquery-2.1.4.min'}
},
shim: {
"jqueryui": {
exports:"$",
deps: ['jquery']
},
underscore: {
exports: "_"
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
});
require(['jquery','libs/jquery-base','libs/jquery-vuln','jqueryui', 'underscore','backbone','goatApp/scoreboardApp'], function($,jqueryBase,jqueryVuln,jqueryui,_,Backbone,ScoreboardApp){
ScoreboardApp.initApp();
});