rename SFA tpl + coffee to 2ndFA & fix merge mistake in vi lang

environments/ppa-mbqj77/deployments/1
Christophe Maudoux 7 years ago
parent 7284d0308f
commit 71b4c96ef5
  1. 8
      lemonldap-ng-manager/MANIFEST
  2. 4
      lemonldap-ng-manager/lib/Lemonldap/NG/Manager/2ndFA.pm
  3. 473
      lemonldap-ng-manager/site/coffee/sfa.coffee
  4. 511
      lemonldap-ng-manager/site/htdocs/static/js/sfa.js
  5. 1
      lemonldap-ng-manager/site/htdocs/static/js/sfa.min.js
  6. 4
      lemonldap-ng-manager/site/htdocs/static/languages/vi.json
  7. 150
      lemonldap-ng-manager/site/templates/sfa.tpl

@ -28,13 +28,13 @@ README
REST-API.md
scripts/lmConfigEditor
scripts/testConfBackend.pl
site/coffee/2ndfa.coffee
site/coffee/diff.coffee
site/coffee/filterFunctions.coffee
site/coffee/llApp.coffee
site/coffee/manager.coffee
site/coffee/notifications.coffee
site/coffee/sessions.coffee
site/coffee/sfa.coffee
site/htdocs/manager.fcgi
site/htdocs/manager.psgi
site/htdocs/static/bwr/angular-animate/angular-animate.js
@ -136,6 +136,8 @@ site/htdocs/static/forms/trool.html
site/htdocs/static/forms/virtualHost.html
site/htdocs/static/forms/virtualHostContainer.html
site/htdocs/static/forms/white.html
site/htdocs/static/js/2ndfa.js
site/htdocs/static/js/2ndfa.min.js
site/htdocs/static/js/conftree.js
site/htdocs/static/js/conftree.min.js
site/htdocs/static/js/diff.js
@ -150,8 +152,6 @@ site/htdocs/static/js/notifications.js
site/htdocs/static/js/notifications.min.js
site/htdocs/static/js/sessions.js
site/htdocs/static/js/sessions.min.js
site/htdocs/static/js/sfa.js
site/htdocs/static/js/sfa.min.js
site/htdocs/static/languages/ar.json
site/htdocs/static/languages/en.json
site/htdocs/static/languages/fr.json
@ -172,6 +172,7 @@ site/htdocs/static/logos/pastel.png
site/htdocs/static/logos/vi.png
site/htdocs/static/reverseTree.json
site/htdocs/static/struct.json
site/templates/2ndfa.tpl
site/templates/diff.tpl
site/templates/footer.tpl
site/templates/header.tpl
@ -180,7 +181,6 @@ site/templates/menubar.tpl
site/templates/notifications.tpl
site/templates/scripts.tpl
site/templates/sessions.tpl
site/templates/sfa.tpl
site/templates/tree.tpl
t/02-HTML-template.t
t/03-HTML-forms.t

@ -22,14 +22,14 @@ our $VERSION = '2.0.0';
# I. INITIALIZATION METHODS #
#############################
use constant defaultRoute => 'sfa.html#/persistent?U2FCheck=1&TOTPCheck=1';
use constant defaultRoute => '2ndfa.html#/persistent?U2FCheck=1&TOTPCheck=1';
sub addRoutes {
my ( $self, $conf ) = @_;
# Remote Procedure Call are defined in Lemonldap::NG::Common::Session::REST
# HTML template
$self->addRoute( 'sfa.html', undef, ['GET'] )
$self->addRoute( '2ndfa.html', undef, ['GET'] )
->addRoute(
sfa => { ':sessionType' => 'sfa' },

@ -1,473 +0,0 @@
###
# 2ndFA Session explorer
###
setMsg = (msg, level) ->
$('#msg').html window.translate msg
$('#color').removeClass 'message-positive message-warning alert-success alert-warning'
$('#color').addClass "message-#{level}"
level = 'success' if level == 'positive'
$('#color').addClass "alert-#{level}"
displayError = (j, status, err) ->
console.log 'Error', err
res = JSON.parse j.responseText
if res and res.error
res = res.error.replace /.* /, ''
console.log 'Returned error', res
setMsg res, 'warning'
# Max number of session to display (see overScheme)
max = 25
# Queries to do each type of display: each array item corresponds to the depth
# of opened nodes in the tree
schemes =
_whatToTrace: [
(t,v) ->
"groupBy=substr(#{t},1)"
(t,v) ->
"#{t}=#{v}*&groupBy=#{t}"
(t,v) ->
"#{t}=#{v}"
]
_startTime: [
(t,v) ->
"groupBy=substr(#{t},8)"
(t,v) ->
"#{t}=#{v}*&groupBy=substr(#{t},10)"
(t,v) ->
"#{t}=#{v}*&groupBy=substr(#{t},11)"
(t,v) ->
"#{t}=#{v}*&groupBy=substr(#{t},12)"
(t,v) ->
"#{t}=#{v}*&groupBy=_whatToTrace"
(t,v,q) ->
console.log t
console.log v
console.log q
q.replace(/\&groupBy.*$/, '') + "&_whatToTrace=#{v}"
]
overScheme =
_whatToTrace: (t,v,level,over) ->
if level == 1
"#{t}=#{v}*&groupBy=substr(#{t},#{(level+over+1)})"
else
null
ipAddr: (t,v,level,over) ->
if level > 0 and level < 4
"#{t}=#{v}*&groupBy=net(#{t},#{16*level+4*(over+1)},2)"
else
null
hiddenAttributes = '_password'
# Attributes to group in session display
categories =
dateTitle: ['_utime', '_startTime', '_updateTime', '_lastAuthnUTime', '_lastSeen']
connectionTitle: ['ipAddr', '_timezone', '_url']
authenticationTitle:['_session_id', '_user', '_password', 'authenticationLevel']
modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti']
saml: ['_idp', '_idpConfKey', '_samlToken', '_lassoSessionDump', '_lassoIdentityDump']
groups: ['groups', 'hGroups']
ldap: ['dn']
BrowserID: ['_browserIdAnswer', '_browserIdAnswerRaw']
OpenIDConnect: ['_oidc_id_token', '_oidc_OP', '_oidc_access_token']
# Menu entries
menu =
delU2FKey: [
title: 'deleteU2FKey'
icon: 'trash'
]
addU2FKey: [
title: 'addU2FKey'
icon: 'plus'
]
verifyU2FKey: [
title: 'verifyU2FKey'
icon: 'check'
]
delTOTPKey: [
title: 'deleteTOTPKey'
icon: 'trash'
]
addTOTPKey: [
title: 'addTOTPKey'
icon: 'plus'
]
verifyTOTPKey: [
title: 'verifyTOTPKey'
icon: 'check'
]
home: []
###
# AngularJS applications
###
llapp = angular.module 'llngSessionsExplorer', ['ui.tree', 'ui.bootstrap', 'llApp']
# Filter 2FA sessions controller
llapp.controller 'SessionsExplorerFilter', ['$scope', '$location', '$q', '$http', ($scope, $location, $q, $http) ->
$scope.U2FCheck = 1
$scope.TOTPCheck = 1
$scope.filter2FA = ->
$http.get("#{scriptname}sfa/persistent?groupBy=substr(_session_uid,1)&U2FCheck=#{$scope.U2FCheck}&TOTPCheck=#{$scope.TOTPCheck}").then (response) ->
$scope.waiting = true
, (resp) ->
$scope.waiting = false
$scope.updateTree '', $scope.data, 0, 0
]
# Main controller
llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location', '$q', '$http', ($scope, $translator, $location, $q, $http) ->
$scope.links = links
$scope.menulinks = menulinks
$scope.staticPrefix = staticPrefix
$scope.scriptname = scriptname
$scope.formPrefix = formPrefix
$scope.availableLanguages = availableLanguages
$scope.waiting = true
$scope.showM = false
$scope.showT = true
$scope.data = []
$scope.currentScope = null
$scope.currentSession = null
$scope.menu = menu
# Import translations functions
$scope.translateP = $translator.translateP
$scope.translate = $translator.translate
$scope.translateTitle = (node) ->
$translator.translateField node, 'title'
sessionType = 'global'
# Handle menu items
$scope.menuClick = (button) ->
if button.popup
window.open button.popup
else
button.action = button.title unless button.action
switch typeof button.action
when 'function'
button.action $scope.currentNode, $scope
when 'string'
$scope[button.action]()
else
console.log typeof button.action
$scope.showM = false
# SESSIONS MANAGEMENT
# Delete U2F key
$scope.deleteU2FKey = ->
$scope.waiting = true
$http['delete']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=U2F").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = false
# Delete TOTP key
$scope.deleteTOTPKey = ->
$scope.waiting = true
$http['delete']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=TOTP").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = false
# Add U2F key
$scope.addU2FKey = ->
$scope.waiting = true
$http['put']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=U2F").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = false
# Add TOTP key
$scope.addTOTPKey = ->
$scope.waiting = true
$http['put']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=TOTP").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = false
# Verify U2F key
$scope.verifyU2FKey = ->
$scope.waiting = true
$http['post']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=U2F").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = true
# Verify TOTP key
$scope.verifyTOTPKey = ->
$scope.waiting = true
$http['post']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?Key=TOTP").then (response) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
, (resp) ->
$scope.currentSession = null
$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = true
# Open node
$scope.stoggle = (scope) ->
node = scope.$modelValue
if node.nodes.length == 0
$scope.updateTree node.value, node.nodes, node.level, node.over, node.query, node.count
scope.toggle()
# Display selected session
$scope.displaySession = (scope) ->
# Private functions
# Session preparation
transformSession = (session) ->
_stToStr = (s) ->
s
_insert = (re, title) ->
tmp = []
reg = new RegExp(re)
for key,value of session
if key.match(reg) and value
tmp.push
title: key
value: value
delete session[key]
if tmp.length > 0
res.push
title: title
nodes: tmp
time = session._utime
id = session._session_id
# 1. Replace values if needed
for key, value of session
unless value
delete session[key]
else
if typeof session == 'string' and value.match(/; /)
session[key] = value.split '; '
if typeof session[key] != 'object'
if hiddenAttributes.match(new RegExp('\b' + key + '\b'))
session[key] = '********'
else if key.match /^(_utime|_lastAuthnUTime|_lastSeen|notification)$/
session[key] = $scope.localeDate value
else if key.match /^(_startTime|_updateTime)$/
session[key] = _stToStr value
else if key.match /^(_u2fKeyHandle|_u2fUserKey|_totp2fSecret)$/
session[key] = '##########'
res = []
# 2. Push session keys in result, grouped by categories
for category, attrs of categories
subres = []
for attr in attrs
if session[attr]
subres.push
title: attr
value: session[attr]
delete session[attr]
if subres.length >0
res.push
title: "__#{category}__"
nodes: subres
# 3. Add OpenID and notifications already notified
_insert '^openid', 'OpenID'
_insert '^notification_(.+)', '__notificationsDone__'
# 4. Add session history if exists
if session._loginHistory
tmp = []
if session._loginHistory.successLogin
for l in session._loginHistory.successLogin
tmp.push
t: l._utime
title: $scope.localeDate l._utime
value: "Success (IP #{l.ipAddr})"
if session._loginHistory.failedLogin
for l in session._loginHistory.failedLogin
tmp.push
t: l._utime
title: $scope.localeDate l._utime
value: "#{l.error} (IP #{l.ipAddr})"
delete session._loginHistory
tmp.sort (a,b) ->
a.t - b.t
res.push
title: '__loginHistory__'
nodes: tmp
# 5. Other keys (attributes and macros)
tmp = []
for key, value of session
tmp.push
title: key
value: value
tmp.sort (a,b) ->
if a.title > b.title then 1
else if a.title < b.title then -1
else 0
res.push
title: '__attributesAndMacros__'
nodes: tmp
return {
_utime: time
id: id
nodes: res
}
$scope.currentScope = scope
sessionId = scope.$modelValue.session
$http.get("#{scriptname}sfa/#{sessionType}/#{sessionId}").then (response) ->
$scope.currentSession = transformSession response.data
$scope.showT = false
$scope.localeDate = (s) ->
d = new Date(s * 1000)
return d.toLocaleString()
# Function to change interface language
$scope.getLanguage = (lang) ->
$scope.lang = lang
$scope.form = 'white'
$scope.init()
$scope.showM = false
# URI local path management
pathEvent = (event, next, current) ->
n = next.match /#\/(\w+)/
sessionType = 'global'
if n == null
$scope.type = '_whatToTrace'
else if n[1].match /^(persistent)$/
sessionType = RegExp.$1
$scope.type = '_session_uid'
else
$scope.type = n[1]
$scope.init()
$scope.$on '$locationChangeSuccess', pathEvent
# Function to update tree: download value of opened subkey
autoId = 0
$scope.updateTree = (value, node, level, over, currentQuery, count) ->
$scope.waiting = true
# Query scheme selection:
# - if defined above
scheme = if schemes[$scope.type]
schemes[$scope.type]
# - _updateTime must be displayed as startDate
else if $scope.type == '_updateTime'
schemes._startTime
# - default to _whatToTrace scheme
else
schemes._whatToTrace
# Build query using schemes
query = scheme[level] $scope.type, value, currentQuery
# If number of session exceeds "max" and overScheme exists, call it
if count > max and overScheme[$scope.type]
if tmp = overScheme[$scope.type] $scope.type, value, level, over, currentQuery
over++
query = tmp
level = level - 1
else
over = 0
else
over = 0
# Launch HTTP query
$http.get("#{scriptname}sfa/#{sessionType}?#{query}").then (response) ->
data = response.data
if data.result
for n in data.values
autoId++
n.id = "node#{autoId}"
if level < scheme.length - 1
n.nodes = []
n.level = level + 1
n.query = query
n.over = over
# Date display in tree
if $scope.type.match /^(?:start|update)Time$/
n.title = n.value
# 12 digits -> 12:34
.replace(/^(\d{8})(\d{2})(\d{2})$/,'$2:$3')
# 11 digits -> 12:30
.replace(/^(\d{8})(\d{2})(\d)$/,'$2:$30')
# 10 digits -> 12h
.replace(/^(\d{8})(\d{2})$/,'$2h')
# 8 digits -> 2016-03-15
.replace(/^(\d{4})(\d{2})(\d{2})/,'$1-$2-$3')
node.push n
$scope.total = data.total if value == ''
$scope.waiting = false
, (resp) ->
$scope.waiting = false
# Intialization function
# Simply set $scope.waiting to false during $translator and tree root
# initialization
$scope.init = ->
$scope.waiting = true
$scope.data = []
$q.all [
$translator.init $scope.lang
$scope.updateTree '', $scope.data, 0, 0
]
.then ->
$scope.waiting = false
, (resp) ->
$scope.waiting = false
# Query scheme initialization
# Default to '_whatToTrace'
c = $location.path().match /^\/(\w+)/
$scope.type = if c then c[1] else '_whatToTrace'
]

@ -1,511 +0,0 @@
// Generated by CoffeeScript 1.9.3
/*
* 2ndFA Session explorer
*/
(function() {
var categories, displayError, hiddenAttributes, llapp, max, menu, overScheme, schemes, setMsg;
setMsg = function(msg, level) {
$('#msg').html(window.translate(msg));
$('#color').removeClass('message-positive message-warning alert-success alert-warning');
$('#color').addClass("message-" + level);
if (level === 'positive') {
level = 'success';
}
return $('#color').addClass("alert-" + level);
};
displayError = function(j, status, err) {
var res;
console.log('Error', err);
res = JSON.parse(j.responseText);
if (res && res.error) {
res = res.error.replace(/.* /, '');
console.log('Returned error', res);
return setMsg(res, 'warning');
}
};
max = 25;
schemes = {
_whatToTrace: [
function(t, v) {
return "groupBy=substr(" + t + ",1)";
}, function(t, v) {
return t + "=" + v + "*&groupBy=" + t;
}, function(t, v) {
return t + "=" + v;
}
],
_startTime: [
function(t, v) {
return "groupBy=substr(" + t + ",8)";
}, function(t, v) {
return t + "=" + v + "*&groupBy=substr(" + t + ",10)";
}, function(t, v) {
return t + "=" + v + "*&groupBy=substr(" + t + ",11)";
}, function(t, v) {
return t + "=" + v + "*&groupBy=substr(" + t + ",12)";
}, function(t, v) {
return t + "=" + v + "*&groupBy=_whatToTrace";
}, function(t, v, q) {
console.log(t);
console.log(v);
console.log(q);
return q.replace(/\&groupBy.*$/, '') + ("&_whatToTrace=" + v);
}
]
};
overScheme = {
_whatToTrace: function(t, v, level, over) {
if (level === 1) {
return t + "=" + v + "*&groupBy=substr(" + t + "," + (level + over + 1) + ")";
} else {
return null;
}
},
ipAddr: function(t, v, level, over) {
if (level > 0 && level < 4) {
return t + "=" + v + "*&groupBy=net(" + t + "," + (16 * level + 4 * (over + 1)) + ",2)";
} else {
return null;
}
}
};
hiddenAttributes = '_password';
categories = {
dateTitle: ['_utime', '_startTime', '_updateTime', '_lastAuthnUTime', '_lastSeen'],
connectionTitle: ['ipAddr', '_timezone', '_url'],
authenticationTitle: ['_session_id', '_user', '_password', 'authenticationLevel'],
modulesTitle: ['_auth', '_userDB', '_passwordDB', '_issuerDB', '_authChoice', '_authMulti', '_userDBMulti'],
saml: ['_idp', '_idpConfKey', '_samlToken', '_lassoSessionDump', '_lassoIdentityDump'],
groups: ['groups', 'hGroups'],
ldap: ['dn'],
BrowserID: ['_browserIdAnswer', '_browserIdAnswerRaw'],
OpenIDConnect: ['_oidc_id_token', '_oidc_OP', '_oidc_access_token']
};
menu = {
delU2FKey: [
{
title: 'deleteU2FKey',
icon: 'trash'
}
],
addU2FKey: [
{
title: 'addU2FKey',
icon: 'plus'
}
],
verifyU2FKey: [
{
title: 'verifyU2FKey',
icon: 'check'
}
],
delTOTPKey: [
{
title: 'deleteTOTPKey',
icon: 'trash'
}
],
addTOTPKey: [
{
title: 'addTOTPKey',
icon: 'plus'
}
],
verifyTOTPKey: [
{
title: 'verifyTOTPKey',
icon: 'check'
}
],
home: []
};
/*
* AngularJS applications
*/
llapp = angular.module('llngSessionsExplorer', ['ui.tree', 'ui.bootstrap', 'llApp']);
llapp.controller('SessionsExplorerFilter', [
'$scope', '$location', '$q', '$http', function($scope, $location, $q, $http) {
$scope.U2FCheck = 1;
$scope.TOTPCheck = 1;
return $scope.filter2FA = function() {
$http.get(scriptname + "sfa/persistent?groupBy=substr(_session_uid,1)&U2FCheck=" + $scope.U2FCheck + "&TOTPCheck=" + $scope.TOTPCheck).then(function(response) {
return $scope.waiting = true;
}, function(resp) {
return $scope.waiting = false;
});
return $scope.updateTree('', $scope.data, 0, 0);
};
}
]);
llapp.controller('SessionsExplorerCtrl', [
'$scope', '$translator', '$location', '$q', '$http', function($scope, $translator, $location, $q, $http) {
var autoId, c, pathEvent, sessionType;
$scope.links = links;
$scope.menulinks = menulinks;
$scope.staticPrefix = staticPrefix;
$scope.scriptname = scriptname;
$scope.formPrefix = formPrefix;
$scope.availableLanguages = availableLanguages;
$scope.waiting = true;
$scope.showM = false;
$scope.showT = true;
$scope.data = [];
$scope.currentScope = null;
$scope.currentSession = null;
$scope.menu = menu;
$scope.translateP = $translator.translateP;
$scope.translate = $translator.translate;
$scope.translateTitle = function(node) {
return $translator.translateField(node, 'title');
};
sessionType = 'global';
$scope.menuClick = function(button) {
if (button.popup) {
window.open(button.popup);
} else {
if (!button.action) {
button.action = button.title;
}
switch (typeof button.action) {
case 'function':
button.action($scope.currentNode, $scope);
break;
case 'string':
$scope[button.action]();
break;
default:
console.log(typeof button.action);
}
}
return $scope.showM = false;
};
$scope.deleteU2FKey = function() {
$scope.waiting = true;
$http['delete'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=U2F").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = false;
};
$scope.deleteTOTPKey = function() {
$scope.waiting = true;
$http['delete'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=TOTP").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = false;
};
$scope.addU2FKey = function() {
$scope.waiting = true;
$http['put'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=U2F").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = false;
};
$scope.addTOTPKey = function() {
$scope.waiting = true;
$http['put'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=TOTP").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = false;
};
$scope.verifyU2FKey = function() {
$scope.waiting = true;
$http['post'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=U2F").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = true;
};
$scope.verifyTOTPKey = function() {
$scope.waiting = true;
$http['post'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?Key=TOTP").then(function(response) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
}, function(resp) {
$scope.currentSession = null;
$scope.currentScope.remove();
return $scope.waiting = false;
});
return $scope.showT = true;
};
$scope.stoggle = function(scope) {
var node;
node = scope.$modelValue;
if (node.nodes.length === 0) {
$scope.updateTree(node.value, node.nodes, node.level, node.over, node.query, node.count);
}
return scope.toggle();
};
$scope.displaySession = function(scope) {
var sessionId, transformSession;
transformSession = function(session) {
var _insert, _stToStr, attr, attrs, category, i, id, k, key, l, len, len1, len2, m, ref, ref1, res, subres, time, tmp, value;
_stToStr = function(s) {
return s;
};
_insert = function(re, title) {
var key, reg, tmp, value;
tmp = [];
reg = new RegExp(re);
for (key in session) {
value = session[key];
if (key.match(reg) && value) {
tmp.push({
title: key,
value: value
});
delete session[key];
}
}
if (tmp.length > 0) {
return res.push({
title: title,
nodes: tmp
});
}
};
time = session._utime;
id = session._session_id;
for (key in session) {
value = session[key];
if (!value) {
delete session[key];
} else {
if (typeof session === 'string' && value.match(/; /)) {
session[key] = value.split('; ');
}
if (typeof session[key] !== 'object') {
if (hiddenAttributes.match(new RegExp('\b' + key + '\b'))) {
session[key] = '********';
} else if (key.match(/^(_utime|_lastAuthnUTime|_lastSeen|notification)$/)) {
session[key] = $scope.localeDate(value);
} else if (key.match(/^(_startTime|_updateTime)$/)) {
session[key] = _stToStr(value);
} else if (key.match(/^(_u2fKeyHandle|_u2fUserKey|_totp2fSecret)$/)) {
session[key] = '##########';
}
}
}
}
res = [];
for (category in categories) {
attrs = categories[category];
subres = [];
for (i = 0, len = attrs.length; i < len; i++) {
attr = attrs[i];
if (session[attr]) {
subres.push({
title: attr,
value: session[attr]
});
delete session[attr];
}
}
if (subres.length > 0) {
res.push({
title: "__" + category + "__",
nodes: subres
});
}
}
_insert('^openid', 'OpenID');
_insert('^notification_(.+)', '__notificationsDone__');
if (session._loginHistory) {
tmp = [];
if (session._loginHistory.successLogin) {
ref = session._loginHistory.successLogin;
for (k = 0, len1 = ref.length; k < len1; k++) {
l = ref[k];
tmp.push({
t: l._utime,
title: $scope.localeDate(l._utime),
value: "Success (IP " + l.ipAddr + ")"
});
}
}
if (session._loginHistory.failedLogin) {
ref1 = session._loginHistory.failedLogin;
for (m = 0, len2 = ref1.length; m < len2; m++) {
l = ref1[m];
tmp.push({
t: l._utime,
title: $scope.localeDate(l._utime),
value: l.error + " (IP " + l.ipAddr + ")"
});
}
}
delete session._loginHistory;
tmp.sort(function(a, b) {
return a.t - b.t;
});
res.push({
title: '__loginHistory__',
nodes: tmp
});
}
tmp = [];
for (key in session) {
value = session[key];
tmp.push({
title: key,
value: value
});
}
tmp.sort(function(a, b) {
if (a.title > b.title) {
return 1;
} else if (a.title < b.title) {
return -1;
} else {
return 0;
}
});
res.push({
title: '__attributesAndMacros__',
nodes: tmp
});
return {
_utime: time,
id: id,
nodes: res
};
};
$scope.currentScope = scope;
sessionId = scope.$modelValue.session;
$http.get(scriptname + "sfa/" + sessionType + "/" + sessionId).then(function(response) {
return $scope.currentSession = transformSession(response.data);
});
return $scope.showT = false;
};
$scope.localeDate = function(s) {
var d;
d = new Date(s * 1000);
return d.toLocaleString();
};
$scope.getLanguage = function(lang) {
$scope.lang = lang;
$scope.form = 'white';
$scope.init();
return $scope.showM = false;
};
pathEvent = function(event, next, current) {
var n;
n = next.match(/#\/(\w+)/);
sessionType = 'global';
if (n === null) {
$scope.type = '_whatToTrace';
} else if (n[1].match(/^(persistent)$/)) {
sessionType = RegExp.$1;
$scope.type = '_session_uid';
} else {
$scope.type = n[1];
}
return $scope.init();
};
$scope.$on('$locationChangeSuccess', pathEvent);
autoId = 0;
$scope.updateTree = function(value, node, level, over, currentQuery, count) {
var query, scheme, tmp;
$scope.waiting = true;
scheme = schemes[$scope.type] ? schemes[$scope.type] : $scope.type === '_updateTime' ? schemes._startTime : schemes._whatToTrace;
query = scheme[level]($scope.type, value, currentQuery);
if (count > max && overScheme[$scope.type]) {
if (tmp = overScheme[$scope.type]($scope.type, value, level, over, currentQuery)) {
over++;
query = tmp;
level = level - 1;
} else {
over = 0;
}
} else {
over = 0;
}
return $http.get(scriptname + "sfa/" + sessionType + "?" + query).then(function(response) {
var data, i, len, n, ref;
data = response.data;
if (data.result) {
ref = data.values;
for (i = 0, len = ref.length; i < len; i++) {
n = ref[i];
autoId++;
n.id = "node" + autoId;
if (level < scheme.length - 1) {
n.nodes = [];
n.level = level + 1;
n.query = query;
n.over = over;
if ($scope.type.match(/^(?:start|update)Time$/)) {
n.title = n.value.replace(/^(\d{8})(\d{2})(\d{2})$/, '$2:$3').replace(/^(\d{8})(\d{2})(\d)$/, '$2:$30').replace(/^(\d{8})(\d{2})$/, '$2h').replace(/^(\d{4})(\d{2})(\d{2})/, '$1-$2-$3');
}
}
node.push(n);
}
if (value === '') {
$scope.total = data.total;
}
}
return $scope.waiting = false;
}, function(resp) {
return $scope.waiting = false;
});
};
$scope.init = function() {
$scope.waiting = true;
$scope.data = [];
return $q.all([$translator.init($scope.lang), $scope.updateTree('', $scope.data, 0, 0)]).then(function() {
return $scope.waiting = false;
}, function(resp) {
return $scope.waiting = false;
});
};
c = $location.path().match(/^\/(\w+)/);
return $scope.type = c ? c[1] : '_whatToTrace';
}
]);
}).call(this);

File diff suppressed because one or more lines are too long

@ -736,12 +736,8 @@
"u2fActivation":"Kích hoạt",
"u2fAuthnLevel":"Mức xác thực U2F",
"u2fUserCanRemoveKey":"Authorize user to remove U2F key",
<<<<<<< HEAD
"u2fSelfRegistration":"Tự đăng ký ",
=======
"u2fSelfRegistration":"Tự đăng ký",
"u2fSessions":"U2F sessions explorer",
>>>>>>> master
"uid":"Trình định danh",
"unknownAttrOrMacro":"Thuộc tính hoặc macro chưa xác định",
"unknownError":"Lỗi không xác định",

@ -1,150 +0,0 @@
<TMPL_INCLUDE NAME="header.tpl">
<title>LemonLDAP::NG 2nd Factor sessions explorer</title>
</head>
<body ng-app="llngSessionsExplorer" ng-controller="SessionsExplorerCtrl" ng-csp>
<TMPL_INCLUDE NAME="menubar.tpl">
<div id="content" class="row container-fluid">
<div id="pleaseWait" ng-show="waiting"><span trspan="waitingForDatas"></span></div>
<!-- Tree -->
<aside id="left" class="col-lg-4 col-md-4 col-sm-5 col-xs-12 scrollable " ng-class="{'hidden-xs':!showT}" role="complementary">
<div class="navbar navbar-default">
<div class="navbar-collapse">
<ul class="nav navbar-nav" role="grid">
<li><a id="a-persistent" role="row"><i class="glyphicon glyphicon-exclamation-sign"></i> {{translate('2faSessions')}}</a></li>
<form name="filterForm" ng-controller="SessionsExplorerFilter">
<div class="form-check ">&nbsp;&nbsp;&nbsp;
<input type="checkbox" ng-model="U2FCheck" class="form-check-input" ng-true-value="'2'" ng-false-value="'1'" ng-change="filter2FA()"/>
<label class="form-check-label" for="U2FCheck">U2F</label>&nbsp;&nbsp;
<input type="checkbox" ng-model="TOTPCheck" class="form-check-input" ng-true-value="'2'" ng-false-value="'1'" ng-change="filter2FA()"/>
<label class="form-check-label" for="TOTPCheck">TOTP</label>
</div>
</form>
</ul>
</div>
</div>
<div class="text-center"><p class="badge">{{total}} <span trspan="session_s"></span></p></div>
<div class="region region-sidebar-first">
<section id="block-superfish-1" class="block block-superfish clearfix">
<div ui-tree data-drag-enabled="false" id="tree-root">
<div ng-show="data.length==0" class="center">
<span class="label label-warning" trspan="noDatas"></span>
</div>
<ol ui-tree-nodes="" ng-model="data">
<li ng-repeat="node in data track by node.id" ui-tree-node ng-include="'nodes_renderer.html'" collapsed="true"></li>
</ol>
</div>
</section>
</div>
<div class="hresizer hidden-xs" resizer="vertical" resizer-left="#left" resizer-right="#right"></div>
</aside>
<!-- Right(main) div -->
<div id="right" class="col-lg-8 col-md-8 col-sm-7 col-xs-12 scrollable" ng-class="{'hidden-xs':showT&&!showM}">
<!-- Menu buttons -->
<div ng-if="currentSession" class="lmmenu navbar navbar-default" ng-class="{'hidden-xs':!showM}">
<div class="navbar-collapse" ng-class="{'collapse':!showM}" id="formmenu">
<ul class="nav navbar-nav">
<li ng-if="currentSession" ng-repeat="button in menu.delU2FKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession" ng-repeat="button in menu.verifyU2FKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession" ng-repeat="button in menu.addU2FKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession===null" ng-repeat="button in menu.home" ng-include="'menubutton.html'"></li>
<li uib-dropdown class="visible-xs">
<a id="langmenu" name="menu" uib-dropdown-toggle data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Menu <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelled-by="langmenu" role="grid">
<li ng-repeat="link in links"><a href="{{link.target}}" role="row"><i ng-if="link.icon" class="glyphicon glyphicon-{{link.icon}}"></i> {{translate(link.title)}}</a></li>
<li ng-repeat="menulink in menulinks"><a href="{{menulink.target}}" role="row"><i ng-if="menulink.icon" class="glyphicon glyphicon-{{menulink.icon}}"></i> {{translate(menulink.title)}}</a></li>
<li ng-include="'languages.html'"></li>
</ul>
</li>
</ul>
</div>
</div>
<div ng-if="currentSession" class="lmmenu navbar navbar-default" ng-class="{'hidden-xs':!showM}">
<div class="navbar-collapse" ng-class="{'collapse':!showM}" id="formmenu">
<ul class="nav navbar-nav">
<li ng-if="currentSession" ng-repeat="button in menu.delTOTPKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession" ng-repeat="button in menu.verifyTOTPKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession" ng-repeat="button in menu.addTOTPKey" ng-include="'menubutton.html'"></li>
<li ng-if="currentSession===null" ng-repeat="button in menu.home" ng-include="'menubutton.html'"></li>
<li uib-dropdown class="visible-xs">
<a id="langmenu" name="menu" uib-dropdown-toggle data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Menu <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelled-by="langmenu" role="grid">
<li ng-repeat="link in links"><a href="{{link.target}}" role="row"><i ng-if="link.icon" class="glyphicon glyphicon-{{link.icon}}"></i> {{translate(link.title)}}</a></li>
<li ng-repeat="menulink in menulinks"><a href="{{menulink.target}}" role="row"><i ng-if="menulink.icon" class="glyphicon glyphicon-{{menulink.icon}}"></i> {{translate(menulink.title)}}</a></li>
<li ng-include="'languages.html'"></li>
</ul>
</li>
</ul>
</div>
</div>
<div class="panel panel-default" ng-hide="currentSession===null">
<div class="panel-heading">
<h1 class="panel-title text-center">{{translate("sessionTitle")}} {{currentSession.id}}</h1>
</div>
<div class="panel-body">
<div class="alert alert-info">
<strong>{{translate("sessionStartedAt")}}</strong>
{{localeDate(currentSession._utime)}}
</div>
<div ng-model="currentSession.nodes">
<div ng-repeat="node in currentSession.nodes" ng-include="'session_attr.html'"></div>
</div>
</div>
</div>
</div>
</div>
<script type="text/ng-template" id="session_attr.html">
<div class="panel panel-default" ng-if="node.nodes">
<div class="panel-heading">
<h2 class="panel-title text-center">{{translateP(node.title)}}</h2>
</div>
<table class="table table-striped" ng-model="node.nodes">
<tr ng-repeat="node in node.nodes" ng-include="'session_attr.html'"></tr>
</table>
</div>
<div ng-if="!node.nodes">
<th>{{translate(node.title)}}</th>
<td><tt>${{node.title}}</tt></td>
<td><span id="v-{{node.title}}">{{node.value}}</td>
</div>
</script>
<script type="text/ng-template" id="nodes_renderer.html">
<div ui-tree-handle class="tree-node tree-node-content panel-info" ng-class="{'bg-info':this.$modelValue===currentScope.$modelValue,'tree-node-default':this.$modelValue!==currentScope.$modelValue}">
<span ng-if="node.value">
<a id="a-{{node.value}}" class="btn btn-node btn-sm" ng-click="stoggle(this)">
<span class="glyphicon" ng-class="{'glyphicon-chevron-right': collapsed,'glyphicon-chevron-down': !collapsed}"></span>
</a>
<span id="s-{{node.value}}" ng-click="stoggle(this)">{{node.title || node.value}} <span class="badge">{{node.count}}</span></span>
</span>
<span ng-if="node.session">
<a class="btn btn-node btn-sm" ng-click="displaySession(this)">
<span class="glyphicon glyphicon-eye-open"></span>
</a>
<span id="s-{{node.session}}" ng-click="displaySession(this)">{{localeDate(node.date)}}</span>
</span>
</div>
<ol ui-tree-nodes="" ng-model="node.nodes" ng-class="{hidden: collapsed}">
<li ng-repeat="node in node.nodes track by node.id" ui-tree-node ng-include="'nodes_renderer.html'" collapsed="true"></li>
</ol>
</script>
<TMPL_INCLUDE NAME="scripts.tpl">
<!-- //if:jsminified
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/sfa.min.js"></script>
//else -->
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/sfa.js"></script>
<!-- //endif -->
<TMPL_INCLUDE NAME="footer.tpl">
Loading…
Cancel
Save