Started support of organisation trophies

pull/7/head
Sami Mokaddem 2017-11-13 12:57:05 +01:00
parent 1b9f9bd452
commit 0bc0683924
6 changed files with 185 additions and 6 deletions

View File

@ -65,6 +65,25 @@ regularlyDays=7
[HonorBadge]
1=Has made at least one pull request on the MISP project
2=Is a donator for the MISP project
3=Has published content upvoted by the community
4=Has published valuable content for the community
5=Has published loads of valuable content for the community
[HonorTrophy]
0=No trophy
1=Novice
2=Beginner
3=Intermediate
4=Competent
5=Experienced
6=Talented
7=Skilled
8=Advanced
9=Expert
10=Master
[HonorTrophyCateg]
categ=["internal_reference", "targeting_data", "antivirus_detection", "payload_delivery", "artifacts_dropped", "payload_installation", "persistence_mechanism", "network_activity", "payload_type", "attribution", "external_analysis", "financial_fraud", "support_Tool", "social_network", "person", "other" ]
[additionalInfo]
textsArray=["Proposals means either edition, acceptation or rejection", "Recent events means event aged of one month at max", "Regularly means at least one per week" ,"Heavily means at least 10 per week", "Classification means correct tagging", "The contribution rank is set such that it equals to: rank=requirement_fulfilled-requirement_not_fulfilled"]

View File

@ -22,6 +22,12 @@ class Contributor_helper:
for badgeNum in range(1, self.honorBadgeNum+1): #get Num of honorBadge
self.org_honor_badge_title[badgeNum] = self.cfg_org_rank.get('HonorBadge', str(badgeNum))
self.trophyNum = len(self.cfg_org_rank.options('HonorTrophyCateg'))
self.categories_in_trophy = json.loads(self.cfg_org_rank.get('HonorTrophyCateg', 'categ'))
self.trophy_title = {}
for trophyNum in range(0, len(self.cfg_org_rank.options('HonorTrophy'))): #get Num of trophy
self.trophy_title[trophyNum] = self.cfg_org_rank.get('HonorTrophy', str(trophyNum))
#GLOBAL RANKING
self.org_rank_maxLevel = self.cfg_org_rank.getint('rankTitle', 'maxLevel')
self.org_rank = {}
@ -218,6 +224,17 @@ class Contributor_helper:
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
self.serv_redis_db.delete(keyname.format(org=org, orgCateg='BADGE_'+str(badgeNum)))
''' TROPHIES '''
def getOrgTrophies(self, org):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
trophy = []
for i in range(1, self.trophyNum+1):
key = keyname.format(org=org, orgCateg='TROPHY_'+str(i))
trophy_Pnts = self.serv_redis_db.get(key)
if trophy_Pnts is not None: #existing
trophy.append(trophy_Pnts)
return trophy
''' MONTHLY CONTRIBUTION '''
def getOrgPntFromRedis(self, org, date):
keyCateg = 'CONTRIB_DAY'
@ -583,3 +600,12 @@ class Contributor_helper:
else:
honorBadge.append(0)
return honorBadge
def TEST_getOrgTrophies(self, org):
keyname = 'CONTRIB_ORG:{org}:{orgCateg}'
trophy = []
for categ in self.categories_in_trophy:
key = keyname.format(org=org, orgCateg='TROPHY_'+categ)
trophy_Pnts = random.randint(0,10)
trophy.append({'categName': categ, 'rank': trophy_Pnts})
return trophy

View File

@ -149,7 +149,7 @@ def geo():
@app.route("/contrib")
def contrib():
categ_list = contributor_helper.categories_in_datatable
categ_list_str = [ s[0].upper() + s[1:].replace('_', ' ') for s in contributor_helper.categories_in_datatable]
categ_list_str = [ s[0].upper() + s[1:].replace('_', ' ') for s in categ_list]
categ_list_points = [contributor_helper.DICO_PNTS_REWARD[categ] for categ in categ_list]
org_rank = contributor_helper.org_rank
@ -163,6 +163,10 @@ def contrib():
org_honor_badge_title_list = [ [num, text] for num, text in contributor_helper.org_honor_badge_title.items()]
org_honor_badge_title_list.sort(key=lambda x: x[0])
trophy_categ_list = contributor_helper.categories_in_trophy
trophy_categ_list_str = [ s[0].upper() + s[1:].replace('_', ' ') for s in trophy_categ_list]
trophy_title = contributor_helper.trophy_title
currOrg = request.args.get('org')
if currOrg is None:
currOrg = ""
@ -179,6 +183,10 @@ def contrib():
org_rank_additional_text=org_rank_additional_text,
org_honor_badge_title=json.dumps(org_honor_badge_title),
org_honor_badge_title_list=org_honor_badge_title_list,
trophy_categ_list=json.dumps(trophy_categ_list),
trophy_categ_list_id=trophy_categ_list,
trophy_categ_list_str=trophy_categ_list_str,
trophy_title=json.dumps(trophy_title),
min_between_reload=cfg.getint('CONTRIB', 'min_between_reload')
)
@ -376,5 +384,13 @@ def getHonorBadges():
org = ''
return jsonify(contributor_helper.getOrgHonorBadges(org))
@app.route("/_getTrophies")
def getTrophies():
try:
org = request.args.get('org')
except:
org = ''
return jsonify(contributor_helper.TEST_getOrgTrophies(org))
if __name__ == '__main__':
app.run(host='localhost', port=8001, threaded=True)

View File

@ -3,6 +3,12 @@
height: auto;
}
tr > td > label > input.radioTrophy {
margin: auto;
margin-bottom: 5px;
display: block;
}
.successCell {
background-color: #dff0d8 !important
}
@ -16,8 +22,24 @@
border: 1px solid #caccce;
}
.circleBadgeSmall {
width: 40px;
height: 40px;
text-align: center;
border-radius: 25px;
background-color: #e1e1e1;
border: 1px solid #caccce;
vertical-align: middle;
margin-left: auto;
margin-right: auto;
}
.grayscale { filter: grayscale(100%); }
.circlBadgeAcquired {
box-shadow: 0px 0px 15px #0000ff
/*box-shadow: 0px 0px 15px #0000ff*/
box-shadow: 0px 0px 3px #1b6a92, 0px 0px 10px #2fa1db;
}
.questionBadgeText {

View File

@ -452,6 +452,23 @@ function updateProgressHeader(org) {
}
});
// set trophies if acquired
$.getJSON( url_getTrophies+'?org='+org, function( data ) {
var source = url_baseTrophyLogo+0+'.png'
for(var i=0; i<trophy_categ_list.length; i++) { // remove
categ = trophy_categ_list[i];
$('#trophy_'+categ).attr('src', source);
$('#trophy_'+categ).attr('title', "");
}
for(var i=0; i<data.length; i++) { // add
categ = data[i].categName;
rank = data[i].rank;
source = url_baseTrophyLogo+rank+'.png'
$('#trophy_'+categ).attr('src', source);
$('#trophy_'+categ).attr('title', trophy_title[rank]);
}
});
//update overtake points
updateOvertakePnts();
@ -565,6 +582,10 @@ $(document).ready(function() {
//FIXME: timeout used to wait that all datatables are draw.
setTimeout( function() { updateProgressHeader(currOrg); }, 500);
$('#trophyForm input').on('change', function() {
alert($('input[name=radioTrophyName]:checked', '#trophyForm').val());
});
source_lastContrib = new EventSource(url_eventStreamLastContributor);
source_lastContrib.onmessage = function(event) {
var json = jQuery.parseJSON( event.data );

View File

@ -46,8 +46,8 @@
</head>
<body>
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<!-- Modal Rank -->
<div id="myModalRank" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg" style="width: 1500px;">
<!-- Modal content-->
@ -159,10 +159,78 @@
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<!-- Modal trophy -->
<div id="myModalTrophy" class="modal fade" role="dialog">
<div class="modal-dialog modal-lg" style="width: 1500px;">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" style="float: left;">Trophies and badges</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<h4>Badges:</h4>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Badge</th>
<th>Requirement</th>
</tr>
</thead>
<tbody id='bodyTableBadgeModal'>
{% for item in org_honor_badge_title_list %}
<tr>
<td>
<div id="divBadge_{{ loop.index }}" class="circleBadgeSmall circlBadgeAcquired">
<img height='32px' width='32px' class="" style="margin-top: 3px;" src="{{ url_for('static', filename='pics/MISPHonorableIcons/1.svg')[:-5]}}{{ item[0] }}.svg" type='image/svg' style="margin: auto;"</img>
</div>
</td>
<td style="padding-left: 15px;">{{ item[1] }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<p style="font-size: 18px; display: inline;">Trophies: </p><p style="display: inline;">Shows your skills in information sharing </p><i> (earned via upvotes or sightings from other organisation)</i>
<div class="table-responsive">
<table class="table table-striped table-bordered">
<thead>
<tr>
{% for categ in trophy_categ_list_str %}
<th>{{ categ }}</th>
{% endfor %}
</tr>
</thead>
<tbody id='bodyTableTrophyModal'>
<form id="trophyForm">
<tr>
{% for categ in trophy_categ_list_id %}
<td>
<label style="cursor: pointer; display: block; margin-left: auto; margin-right: auto;">
<input class="radioTrophy" type="radio" name="radioTrophyName" value="{{categ}}"/>
<img id='trophy_{{categ}}' style="display: block; margin-left: auto; margin-right: auto;" height="64" width="64" src="{{ url_for('static', filename='pics/MISPTrophy/0.png') }}" type='image/png'>
</label>
</td>
{% endfor %}
</tr>
</from>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<div id="wrapper">
<!-- Navigation -->
@ -190,7 +258,8 @@
<div class='textTopHeader' style="padding-top: 9px;">
<input type="text" id="orgName" data-provide="typeahead" size="20" style="margin-bottom: 5px;">
</div>
<button type="button" class="questionBadgeDiv fa fa-question-circle" data-toggle="modal" data-target="#myModal"></button>
<button type="button" class="questionBadgeDiv fa fa-question-circle" title="Ranking information" data-toggle="modal" data-target="#myModalRank"></button>
<button type="button" class="questionBadgeDiv fa fa-trophy" title="Trophies and badges" data-toggle="modal" data-target="#myModalTrophy"></button>
<button id="btnCurrRank" class='btn btn-default popOverBtn' data-container='body' data-toggle='popover' style="display: none; margin-left: 20px;" onclick="showOnlyOrg()">
<object id='orgContributionRank' height=32 width=64 class="centerInBtn"></object>
<strong id="orgText" class="centerInBtn"></strong>
@ -384,12 +453,16 @@
var url_getOrgRank = "{{ url_for('getOrgRank') }}";
var url_getContributionOrgStatus = "{{ url_for('getContributionOrgStatus') }}";
var url_getHonorBadges = "{{ url_for('getHonorBadges') }}";
var url_getTrophies = "{{ url_for('getTrophies')}}"
var url_baseRankMonthlyLogo = "{{ url_for('static', filename='pics/rankingMISPMonthly/1.svg') }}";
url_baseRankMonthlyLogo = url_baseRankMonthlyLogo.substring(0, url_baseRankMonthlyLogo.length-5);
var url_baseOrgRankLogo = "{{ url_for('static', filename='pics/rankingMISPOrg/1.svg') }}";
url_baseOrgRankLogo = url_baseOrgRankLogo.substring(0, url_baseOrgRankLogo.length-5);
var url_baseHonorLogo = "{{ url_for('static', filename='pics/MISPHonorableIcons/1.svg') }}";
url_baseHonorLogo = url_baseHonorLogo.substring(0, url_baseHonorLogo.length-5);
var url_baseTrophyLogo = "{{ url_for('static', filename='pics/MISPTrophy/1.png') }}";
url_baseTrophyLogo = url_baseTrophyLogo.substring(0, url_baseTrophyLogo.length-5);
/* DATA FROM CONF */
var currOrg = "{{ currOrg }}";
@ -399,6 +472,8 @@
var org_rank_obj = JSON.parse('{{ org_rank_json|safe }}');
var org_honor_badge_title = JSON.parse('{{ org_honor_badge_title|safe }}');
var numberOfBadges = {{ org_honor_badge_title_list|length }};
var trophy_categ_list = JSON.parse('{{ trophy_categ_list|safe }}');
var trophy_title = JSON.parse('{{ trophy_title|safe }}');
</script>
<script src="{{ url_for('static', filename='js/contrib.js') }}"></script>