diff --git a/webgoat-container/src/main/resources/static/css/main.css b/webgoat-container/src/main/resources/static/css/main.css index 0bf116637..9b64cb031 100644 --- a/webgoat-container/src/main/resources/static/css/main.css +++ b/webgoat-container/src/main/resources/static/css/main.css @@ -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 */ } /* ========================================================================== @@ -963,8 +963,47 @@ cookie-container { 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 { @@ -975,6 +1014,8 @@ font-size: 1.3em; cursor:pointer; } +/* attack ... */ + .attack-feedback { font-weight:800; } @@ -1045,4 +1086,11 @@ font-size: 1.3em; font-weight: bold; font-size: 12px; padding: 10px; -} \ No newline at end of file +} + +/* temp override +//TODO: come up with longer term solution for full-window viewing +*/ +.col-md-8 { + width: auto !important +} diff --git a/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js index 395d31262..f26aad564 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/model/LessonContentModel.js @@ -32,6 +32,7 @@ define(['jquery', } this.set('content',content); 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); }, diff --git a/webgoat-container/src/main/resources/static/js/goatApp/templates/paging_controls.html b/webgoat-container/src/main/resources/static/js/goatApp/templates/paging_controls.html index 4e75fac0f..141c3f5af 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/templates/paging_controls.html +++ b/webgoat-container/src/main/resources/static/js/goatApp/templates/paging_controls.html @@ -1,5 +1,16 @@
- +
\ No newline at end of file diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js index 26f20f345..72610c84c 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/HelpControlsView.js @@ -38,7 +38,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(); }, diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js index 57beacd04..264ceb5c8 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/LessonContentView.js @@ -47,17 +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; - // + 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')); - //this.listenTo(this.paginationControlView,'page:set',this.navToPage); }, getCurrentPage: function () { @@ -163,8 +163,9 @@ define(['jquery', }, navToPage: function (pageNum) { - this.showCurContentPage(pageNum); this.paginationControlView.setCurrentPage(pageNum);//provides validation + this.showCurContentPage(this.paginationControlView.currentPage); + this.paginationControlView.render(); this.paginationControlView.hideShowNavButtons(); var assignmentPath = this.findAssigmentEndpointOnPage(pageNum); Backbone.trigger('navigatedToPage',{'pageNumber':pageNum, 'assignmentPath' : assignmentPath}); diff --git a/webgoat-container/src/main/resources/static/js/goatApp/view/PaginationControlView.js b/webgoat-container/src/main/resources/static/js/goatApp/view/PaginationControlView.js index a6faddb6c..2cc744859 100644 --- a/webgoat-container/src/main/resources/static/js/goatApp/view/PaginationControlView.js +++ b/webgoat-container/src/main/resources/static/js/goatApp/view/PaginationControlView.js @@ -1,38 +1,99 @@ define(['jquery', 'underscore', 'backbone', + 'goatApp/model/LessonOverviewModel', 'text!templates/paging_controls.html'], // 'css!css/paging-controls.css'], function ($, _, Backbone, + LessonOverviewModel, PaginationTemplate) { return Backbone.View.extend({ template: PaginationTemplate, el: '#lesson-page-controls', initialize: function ($contentPages,baseLessonUrl) { - this.numPages = $contentPages.length; + 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.parseLinks($contentPages); + this.initPagination(); - this.render(); - this.bindNavButtons(); + //this.render(); + + this.model.fetch(); }, render: function () { + this.parseLinks(); var t = _.template(this.template); - this.$el.html(t()); + 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($contentPages) { + 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() { @@ -75,7 +136,7 @@ define(['jquery', this.hideNextPageButton(); this.showPrevPageButton; } - this.trigger('page:set',this,this.currentPage); + this.render(); }, decrementPageView: function() { @@ -92,8 +153,7 @@ define(['jquery', this.hidePrevPageButton(); this.showNextPageButton() } - this.trigger('page:set',this,this.currentPage); - + this.render(); }, hideShowNavButtons: function () { diff --git a/webgoat-container/src/main/resources/templates/main_new.html b/webgoat-container/src/main/resources/templates/main_new.html index d45a737c1..e96256199 100644 --- a/webgoat-container/src/main/resources/templates/main_new.html +++ b/webgoat-container/src/main/resources/templates/main_new.html @@ -143,10 +143,7 @@ - +