Commit 6cd57261 authored by Luca Lamorte's avatar Luca Lamorte

Add template

parent 2622aeb4
# Created by .ignore support plugin (hsz.mobi)
### Node template
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# nyc test coverage
.nyc_output
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Typescript v1 declaration files
typings/
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
### Python template
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# pyenv
.python-version
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# dotenv
.env
# virtualenv
.venv
venv/
ENV/
# Spyder project settings
.spyderproject
# Rope project settings
.ropeproject
.idea
import osimport pikaimport traceback VERSION = '0.0.1'COMPONENT_ID = "gui_tt" UPLOAD_FOLDER = './tmp'ALLOWED_EXTENSIONS = set(['json', 'pcap']) RABBIT_MQ_CONNECTED = False try: AMQP_EXCHANGE = str(os.environ['AMQP_EXCHANGE'])except KeyError as e: print('couldnt import AMQP_EXCHANGE from environment') AMQP_EXCHANGE = "default" try: AMQP_URL = str(os.environ['AMQP_URL'])except KeyError as e: print('couldnt import AMQP_URL from environment') # TODO: REMOVE PERSONAL CONFIGURATION ## AMQP_URL = "amqp://guest:guest@localhost/" AMQP_URL = str(os.getenv('AMQP_URL', 'amqp://luca:luca@finterop1/session1')) def get_connection(AMQP_URL): try: print('Setting up AMQP connection... %s' % AMQP_URL) # setup AMQP connection return pika.BlockingConnection(pika.URLParameters(AMQP_URL)) except pika.exceptions.ConnectionClosed as cc: print(' AMQP cannot be established, is message broker up? \n More: %s' % traceback.format_exc()) return None def get_configuration(status = None): global RABBIT_MQ_CONNECTED if status: RABBIT_MQ_CONNECTED = status cfg = dict() cfg["url"] = AMQP_URL cfg["exchange"] = AMQP_EXCHANGE cfg["version"] = VERSION cfg["component"] = COMPONENT_ID cfg["connected"] = RABBIT_MQ_CONNECTED return cfg
\ No newline at end of file
import osimport pikaimport tracebackimport logging VERSION = '0.0.1'COMPONENT_ID = "gui_tt" UPLOAD_FOLDER = './tmp'ALLOWED_EXTENSIONS = set(['json', 'pcap']) RABBIT_MQ_CONNECTED = False logger = logging.getLogger(__name__)logger.setLevel(logging.DEBUG) try: AMQP_EXCHANGE = str(os.environ['AMQP_EXCHANGE'])except KeyError as e: print('couldnt import AMQP_EXCHANGE from environment') AMQP_EXCHANGE = "default" try: AMQP_URL = str(os.environ['AMQP_URL'])except KeyError as e: print('couldnt import AMQP_URL from environment') # TODO: REMOVE PERSONAL CONFIGURATION ## AMQP_URL = "amqp://guest:guest@localhost/" AMQP_URL = str(os.getenv('AMQP_URL', 'amqp://luca:luca@finterop1/session1')) def get_connection(AMQP_URL): try: print('Setting up AMQP connection... %s' % AMQP_URL) # setup AMQP connection return pika.BlockingConnection(pika.URLParameters(AMQP_URL)) except pika.exceptions.ConnectionClosed as cc: print(' AMQP cannot be established, is message broker up? \n More: %s' % traceback.format_exc()) return None def get_configuration(status = None): global RABBIT_MQ_CONNECTED if status: RABBIT_MQ_CONNECTED = status cfg = dict() cfg["url"] = AMQP_URL cfg["exchange"] = AMQP_EXCHANGE cfg["version"] = VERSION cfg["component"] = COMPONENT_ID cfg["connected"] = RABBIT_MQ_CONNECTED return cfg
\ No newline at end of file
......
from flask import Flask
from flask import render_template
from flask import request, redirect
from flask import render_template, flash
from flask import request, redirect, url_for
from flask import abort
from jinja2.exceptions import TemplateNotFound
from flask_socketio import SocketIO
from testing_tool_gui.utils.amqp_synch_call import publish_message
from testing_tool_gui.utils.messages import *
from testing_tool_gui.gui.amqp_sniffer import *
from testing_tool_gui.gui import *
from werkzeug.utils import secure_filename
amqp_connection = get_connection(AMQP_URL)
......@@ -28,12 +32,16 @@ app.config['SECRET_KEY'] = 'secret!'
socketio = SocketIO(app, async_mode=async_mode)
thread = None
ALLOWED_EXTENSIONS = set(['pcap'])
def start_amqp_sniffer():
amqp_listener = AmqpSniffer(amqp_connection, socketio)
amqp_listener.start()
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
# ================= WEB SOCKET EVENTS ===================== #
......@@ -86,6 +94,13 @@ def test_disconnect():
def main_page():
return render_template('index.html')
@app.route('/html/<template>')
def get_html_template(template):
print("request for %s template" % template)
try:
return render_template('%s.html' % template)
except TemplateNotFound:
abort(404)
@app.route('/amqp_msg_list')
def amqp_msg():
......@@ -125,17 +140,43 @@ def configuration():
# return ""
# @app.route('/uploadajax', methods=['POST'])
# def upload():
#
# publish_event(channel, MsgTestCaseStart())
#
# if request.method == 'POST':
# f = request.files['file']
# filename = secure_filename("upload_file.pcap")
# f.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
# #publish_event(channel, MsgPrivacyTestCaseAnalyzeUploadFile())
# return redirect("/", code=302)
@app.route('/upload', methods=['POST'])
def upload():
#publish_event(channel, MsgTestCaseStart())
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
print("FILE %s stored in %s" % (filename, app.config['UPLOAD_FOLDER']))
return redirect(url_for('uploaded_file', filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
#return redirect("/", code=302)
......@@ -172,8 +213,6 @@ def configuration():
# f = request.files['the_file']
# f.save('./tmp/demo.pcap')
#app.run(port=8080)
if __name__ == '__main__':
print("Start App listening on port 8080")
......
......@@ -48,6 +48,35 @@ $(document).ready(function() {
});
function showDetails(value){
var html = ""
if (value === 'privacy'){
// Default is gui
html = ['<h1> Privacy Testing Tool - v.1.0.0 </h1>',
'<p>Lorem ipsum dolor sit amet, consectetur adipisci elit, sed eiusmod tempor incidunt ut ' +
'labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrum exercitationem ullam ' +
'corporis suscipit laboriosam, nisi ut aliquid ex ea commodi consequatur. Quis aute iure ' +
'reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur ' +
'sint obcaecat cupiditat non proident, sunt in culpa qui officia deserunt mollit anim ' +
'id est laborum.</p>',
'<div class="raw" id="p_tc"></div>']
}
else {
// Default is gui
html = ['<h1>Demo GUI!</h1>',
'<p>This is a a simple GUI to play with <a href-="http://www.finterop.eu">F-Interop</a> ' +
'APIs and Testing Tools (TT) . It includes a Event Bus (RabbitMQ) console ' +
'and the AMQP Messages Utils. Use it as a starting point to test your component.</p>',
]
}
$("#info").html(html);
}
function change_cfg(){
console.log("send configuration to server")
socket.emit('change_config', { 'url' : $("#amqp_url").val(), "exchange": $("#amqp_exchange").val()});
......@@ -77,8 +106,6 @@ function read_configuration(cfg){
function read_message_list(data){
var old_topic = ""
$("#utils_msg_list").html("")
for (var i in data){
......@@ -179,6 +206,8 @@ function showAll(){
}
function filterByRoutingKey(){
var routing_key = $('#filter_rk').val()
......
/**
* Created by luca.lamorte on 10/05/2017.
*/
/**
* This has to be improved with some JS TEMPLATE Library...
*
* @param testcase
*/
function addTestCase(testcase){
// var index = parseInt(testcase)
// var title = ["Test Case1", "Test Case 2"]
// var descr = ["User MUST provide the PCAP file of IUTs Conversation to check if there is any privacy issue.",
// "The simplest topology to test this test case is a CoAP Client and Server running on two different" +
// " machines, connected each other with the FI-AGENT. All the traffic will be routed through the " +
// "EventBUS. When the setup is completed user must confirm it by sending Start Test Suite. " +
// "At this stage the Privacy Testing tools will enable the agent and the sniffer to capture " +
// "the conversation between the client and the server. When done, press Test Case Finished and the " +
// "PCAP file generated will be analyzed and a report will be send back to the GUI. " +
// "To check the current status of the Testing tools please use the GetStatus button."]
//
// var cmds = [
// '<div class="col-md-11">' +
// '<p style="color: #000088">'+ descr[index]+'</p>' +
// '<div class="row">' +
// '<div class="col-md-3">' +
// '<form enctype="multipart/form-data">' +
// '<span> Analyze IUT Conversation (CoAP) </span>' +
// '<span class="glyphicon glyphicon-phone" aria-hidden="true"></span>' +
// '<div style="position:relative;">' +
// '<a class="btn btn-primary" href="javascript:;">Choose File...' +
// '<input type="file" id="pcap_file" name="file_source" size="40" onchange="select_pcap()"></a>' +
// '<span class="label label-info" id="upload-file-info"></span>' +
// '</form></div> </div>' +
// '<progress></progress>'+
// '<div class="col-md-9 " id="cmq_area"></div>'+
// '</div>',
//
// // SECOND TEST CASE
// '<div class="col-md-11">'+
// '<p style="color: #000088">'+ descr[index]+'</p>' +
// '<div class="row">' +
// '<button type="button" class="btn btn-default" onclick="send_amqp_message(testcoordination.testsuite.start)">Start TestCase</button> '+
// '<button type="button" class="btn btn-primary" onclick="send_amqp_message(testcoordination.testsuite.finish)">Finish TestCase</button> '+
// '<button type="button" class="btn btn-success" onclick="send_amqp_message(privacy.geststatus)">Get Status</button> '+
// '</div>'+
// '</div>'
// ]
//
//
// var html = ['<hr>',
// '<div class="col-md-1 ">' +
// '<span class="label label-primary">' + title[index] + '</span>' +
// '</div>',
// cmds[index]
// ]
//
//
// console.log("Add testcase "+index)
//
// $("#p_tc").html(html)
$.get( "html/" + testcase, function( data ) {
$( "#p_tc").html( data );
console.log(testcase+ " added.")
});
}
$(':file').on('change', function() {
var file = this.files[0];
if (file.size > 1024) {
alert('max upload size is 1k')
}
// Also see .name, .type
});
function select_pcap(){
var filename = $("#pcap_file").val()
$("#upload-file-info").html(filename);
if (filename!=""){
var analyze = $("<button>").attr("type", "button").addClass("btn btn-danger")
analyze.attr("id", "analyze-pcap")
analyze.html("Analyze...")
analyze.click(function(){
$.ajax({
type: 'POST',
url: '/upload',
data: new FormData($('form')[0]),
enctype: 'multipart/form-data',
contentType: false,
cache: false,
processData: false,
async: false,
// // Custom XMLHttpRequest
// xhr: function() {
// var myXhr = $.ajaxSettings.xhr();
// if (myXhr.upload) {
// // For handling the progress of the upload
// myXhr.upload.addEventListener('progress', function(e) {
// if (e.lengthComputable) {
// $('progress').attr({
// value: e.loaded,
// max: e.total,
// });
// }
// } , false);
// }
// return myXhr;
// },
});
})
var cancel = $("<button>").attr("type", "button").addClass("btn btn-default")
cancel.html("Reset")
cancel.click(function(){
$("#cmq_area").html("");
$("#upload-file-info").html("");
});
$("#cmq_area").append(analyze).append(" ")
$("#cmq_area").append(cancel)
}
else{
$("#cmq_area").html("")
}
}
@charset "UTF-8";
/* Remove the navbar's default margin-bottom and rounded borders */
.navbar {
margin-bottom: 0;
......@@ -64,4 +67,32 @@ footer {
padding: 10px;
padding-bottom: 0px;
padding-top: 0px;
}
.fileinput-button {
position: relative;
overflow: hidden;
display: inline-block;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px !important;
direction: ltr;
cursor: pointer;
}
/* Fixes for IE < 8 */
@media screen\9 {
.fileinput-button input {
filter: alpha(opacity=0);
font-size: 100%;
height: 100%;
}
}
\ No newline at end of file
......@@ -11,6 +11,7 @@
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.7.3/socket.io.js"></script>
<script type="text/javascript" src="{{ url_for('static', filename='gui.js')}}"></script>
<script type="text/javascript" src="{{ url_for('static', filename='privacy.js')}}"></script>
<link rel="icon" type="image/png" sizes="16x16" href="{{ url_for('static', filename='favicon.ico')}}">
<script type=text/javascript>
......@@ -96,7 +97,7 @@
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">GUI</a>
<a class="navbar-brand" href="#" onclick="showDetails('gui')">GUI</a>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
......@@ -114,31 +115,23 @@
</li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
aria-expanded="false">Privacy TT<span class="caret"></span></a>
aria-expanded="false" onclick="showDetails('privacy')">Privacy TT <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#" >Test Case 1</a></li>
<li><a href="#" >Test Case 2</a></li>
<li><a href="#" onclick="addTestCase('privacy_tc1')">Test Case 1</a></li>
<li><a href="#" onclick="addTestCase('privacy_tc2')">Test Case 2</a></li>
<li role="separator" class="divider"></li>
<li><a href="#"">Start Session</a></li>
<li><a href="#"">Send PCAP</a></li>
<li><a href="#"">Stop Session</a></li>
<li><a href="#"">Get Configuration</a></li>
<li><a href="#"">Get Status</a></li>
<li><a href="#">Start Session</a></li>
<li><a href="#">Send PCAP</a></li>
<li><a href="#">Stop Session</a></li>
<li><a href="#">Get Configuration</a></li>
<li><a href="#">Get Status</a></li>
</ul>
</li>
<li><a href="http://finterop2:5000">Orchestrator API</a></li>
<li><a href="#">Orchestrator API</a></li>
<li><a href="http://doc.f-interop.eu/">Docs</a></li>
</ul>
<ul class="nav navbar-nav navbar-right">
<!--<li><a href="#"> <span class="glyphicon glyphicon-user"></span>-->
<!--<strong>Settings</strong>-->
<!--<span class="glyphicon glyphicon-chevron-down"></span></a>-->
<!--</li>-->
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<span class="glyphicon glyphicon-cog"></span>
......@@ -151,7 +144,7 @@
<div class="row">
<div class="col-lg-4">
<p class="text-center">
<img class="icon-size" src="http://www.f-interop.eu/images/logo480_trans.png"></img>
<img class="icon-size" src="http://www.f-interop.eu/images/logo480_trans.png">
</p>
</div>
<div class="col-lg-8">
......@@ -166,14 +159,14 @@
<li class="divider navbar-login-session-bg"></li>
<li><a href="#">Messages <span class="badge pull-right" id="total_msg"> 0 </span></a></li>
<li class="divider"></li>
<li><a href="#">RabbitMQ URL [AMQP_URL]<input type="text" class="form-control" aria-label="..." id="amqp_url"></a></li>
<li><a href="#">RabbitMQ URL [AMQP_URL]<input type="text" class="form-control" aria-label="..." id="amqp_url"></a></li>
<li class="divider"></li>
<li><a href="#"> Exchange [AMQP_EXCHANGE]</span><input type="text" class="form-control" aria-label="..." id="amqp_exchange"></a></li>
<li><a href="#"> Exchange [AMQP_EXCHANGE]<input type="text" class="form-control" aria-label="..." id="amqp_exchange"></a></li>
<li class="divider"></li>
<li><a href="#"> Orchestrator</span><input type="text" class="form-control" aria-label="..." id="orcherstrator_url"></a></li>
<li><a href="#"> Orchestrator<input type="text" class="form-control" aria-label="..." id="orcherstrator_url"></a></li>
</ul>
</li>
</li>§
</ul>
</ul>
</div>
......@@ -182,13 +175,53 @@
<div id="alerts"> </div>
<div class="jumbotron">
<div class="container">
<div class="container" id="info">
<h1>Demo GUI!</h1>
<p>This is a a simple GUI to play with <a href-="http://www.finterop.eu">F-Interop</a> APIs and
Testing Tools (TT) . It includes a Event Bus (RabbitMQ) console and the AMQP Messages Utils.
Use it as a starting point to test your component.</p>
<!--<p><a class="btn btn-primary btn-lg" href="#" role="button">Learn more »</a></p>-->
Use it as a starting point to test your component.
</p>
<!--<div class="row">-->
<!--<div class="col-md-1 ">-->
<!--<span class="label label-primary">TEST CASE 1</span>-->
<!--</div>-->
<!--<div class="col-md-11">-->
<!--<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut-->
<!--labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris-->
<!--nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit-->
<!--esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt-->
<!--in culpa qui officia deserunt mollit anim id est laborum.</p>-->
<!--<div class="row">-->
<!--<div class="col-md-3">-->
<!--<span> Analyze IUT Conversation (CoAP) </span>-->
<!--<span class="glyphicon glyphicon-phone" aria-hidden="true"></span>-->
<!--<div style="position:relative;">-->
<!--<a class='btn btn-primary' href='javascript:;'>-->
<!--Choose File...-->
<!--<input type="file" id="select_pcap" name="file_source" size="40" onchange='select_pcap()'>-->
<!--</a>-->
<!--&nbsp;-->
<!--<span class='label label-info' id="upload-file-info"></span>-->
<!--</div>-->
<!--</div>-->
<!--<div class="col-md-9 " id="cmq_area">-->
<!--</div>-->
<!--</div>-->
<!--</div>-->
<!--</div> &lt;!&ndash; END INFO DIV &ndash;&gt;-->
</div>
</div>
<!--<div class="container">-->
......
<div class="row">
<div class="col-md-1 ">
<span class="label label-primary"> Test Case 1</span>
</div>
<div class="col-md-11">
<p style="color: #000088">
User MUST provide the PCAP file of IUTs Conversation to check if there is any privacy issue.
</p>
<div class="row">
<!-- FORM -->
<!-- The file upload form used as target for the file upload widget -->
<form id="fileupload" method="POST" enctype="multipart/form-data">
<!-- Redirect browsers with JavaScript disabled to the origin page -->
<noscript><input type="hidden" name="redirect" value="/upload"></noscript>
<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="col-lg-7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="glyphicon glyphicon-plus"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple>
</span>
<button type="submit" class="btn btn-primary start">
<i class="glyphicon glyphicon-upload"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="glyphicon glyphicon-ban-circle"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="glyphicon glyphicon-trash"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
<!-- The global file processing state -->
<span class="fileupload-process"></span>
</div>
<!-- The global progress state -->
<div class="col-lg-5 fileupload-progress">
<!-- The global progress bar -->
<div class="progress progress-striped active fade" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="progress-bar progress-bar-success" style="width:0%;"></div>
</div>
<!-- The extended global progress state -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
</form>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Privacy Dumps Notes</h3>
</div>
<div class="panel-body">
<ul>
<li>The maximum file size for uploads in this demo is <strong>999 KB</strong> (default file size is unlimited).</li>
<li>Only image files (<strong>JPG, GIF, PNG</strong>) are allowed in this demo (by default there is no file type restriction).</li>
<li>Uploaded files will be deleted automatically after <strong>5 minutes or less</strong> (demo files are stored in memory).</li>
</ul>
</div>
</div>
</div>
<!-- END FORM -->
</div> <!-- col-md-3 -->
</div> <!-- row -->
</div> <!-- col-md-11 -->
</div>
......@@ -4,5 +4,7 @@ This project aims to help testing tool developer to have a simple web GUI to tes
## Requirements
- Python3
- UTILS submodule