Commit 7477ce08 authored by Yadd's avatar Yadd
Browse files

Merge branch 'manager-2ndFA-module' into 'master'

Manager 2ndfa module

See merge request !25
parents 0d72ad10 14a34d85
Pipeline #1423 passed with stage
in 2 minutes and 26 seconds
......@@ -42,17 +42,17 @@ sub addRoutes {
['DELETE']
);
## ADD 2FA DEVICE
#->addRoute(
#sfa => { ':sessionType' => { ':sessionId' => 'add2FA' } },
#['PUT']
#)
## VERIFY 2FA DEVICE
#->addRoute(
#sfa => { ':sessionType' => { ':sessionId' => 'verify2FA' } },
#['POST']
#);
## ADD 2FA DEVICE
#->addRoute(
#sfa => { ':sessionType' => { ':sessionId' => 'add2FA' } },
#['PUT']
#)
## VERIFY 2FA DEVICE
#->addRoute(
#sfa => { ':sessionType' => { ':sessionId' => 'verify2FA' } },
#['POST']
#);
$self->setTypes($conf);
......@@ -75,22 +75,15 @@ sub delete2FA {
my $mod = $self->getMod($req)
or return $self->sendError( $req, undef, 400 );
my $params = $req->parameters();
my $type = $params->{type};
my $epoch = $params->{epoch};
my $params = $req->parameters();
my $type = $params->{type};
my $epoch = $params->{epoch};
if ( $type =~ /\b(?:U2F|TOTP|UBK)\b/ and $epoch ) {
$self->logger->debug("Call procedure delete2F with type=$type and epoch=$epoch");
$self->logger->debug(
"Call procedure delete2F with type=$type and epoch=$epoch");
return $self->delete2F( $req, $session, $skey );
}
#elsif ( $type =~ /\bTOTP\b/ ) {
#$self->logger->debug("Call procedure deleteTOTP");
#return $self->deleteTOTP( $req, $session, $skey );
#}
#elsif ( $type =~ /\bUBK\b/ ) {
#$self->logger->debug("Call procedure deleteUBK");
#return $self->deleteUBK( $req, $session, $skey );
#}
else {
return $self->sendError( $req, undef, 400 );
}
......@@ -98,22 +91,22 @@ sub delete2FA {
#sub add2FA {
#my ( $self, $req, $session, $skey ) = @_;
#my ( $self, $req, $session, $skey ) = @_;
#eval 'use Crypt::U2F::Server::Simple';
#if ($@) {
#$self->error("Can't load U2F library: $@");
#return 0;
#}
#eval 'use Crypt::U2F::Server::Simple';
#if ($@) {
#$self->error("Can't load U2F library: $@");
#return 0;
#}
#return $self->addU2FKey( $req, $session, $skey );
#return $self->addU2FKey( $req, $session, $skey );
#}
#sub verify2FA {
#my ( $self, $req, $session, $skey ) = @_;
#my ( $self, $req, $session, $skey ) = @_;
#return $self->addU2FKey( $req, $session, $skey );
#return $self->addU2FKey( $req, $session, $skey );
#}
########################
......@@ -141,10 +134,8 @@ sub sfa {
my $whatToTrace = Lemonldap::NG::Handler::PSGI::Main->tsv->{whatToTrace};
# 2.1 Get fields to require
my @fields = (
'_httpSessionType', $self->{ipField},
$whatToTrace, '_2fDevices'
);
my @fields =
( '_httpSessionType', $self->{ipField}, $whatToTrace, '_2fDevices' );
if ( my $groupBy = $params->{groupBy} ) {
$groupBy =~ s/^substr\((\w+)(?:,\d+(?:,\d+)?)?\)$/$1/;
$groupBy =~ s/^_whatToTrace$/$whatToTrace/o
......@@ -160,7 +151,10 @@ sub sfa {
$moduleOptions->{backend} = $mod->{module};
# Select 2FA sessions to display
if ( defined $params->{TOTPCheck} or defined $params->{U2FCheck} or defined $params->{UBKCheck}) {
if ( defined $params->{TOTPCheck}
or defined $params->{U2FCheck}
or defined $params->{UBKCheck} )
{
$self->{TOTPCheck} = delete $params->{TOTPCheck};
$self->{U2FCheck} = delete $params->{U2FCheck};
$self->{UBKCheck} = delete $params->{UBKCheck};
......@@ -313,11 +307,11 @@ qq{Use of an uninitialized attribute "$group" to group sessions},
}
# Else, $res elements will be like:
# { session => <sessionId>, date => <timestamp> }
# { session => <sessionId>, userId => <_session_uid> }
else {
$res = [
sort { $a->{date} <=> $b->{date} }
map { { session => $_, date => $res->{$_}->{_utime} } }
map { { session => $_, userId => $res->{$_}->{_session_uid} } }
keys %$res
];
}
......
......@@ -2,7 +2,6 @@
# 2ndFA Session explorer
###
setMsg = (msg, level) ->
$('#msg').html window.translate msg
$('#color').removeClass 'message-positive message-warning alert-success alert-warning'
......@@ -18,7 +17,6 @@ displayError = (j, status, err) ->
console.log 'Returned error', res
setMsg res, 'warning'
# Max number of session to display (see overScheme)
max = 25
......@@ -29,26 +27,7 @@ schemes =
(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}"
"#{t}=#{v}*"
]
overScheme =
......@@ -57,46 +36,16 @@ overScheme =
"#{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']
dateTitle: ['_utime', '_startTime', '_updateTime']
sfaTitle: ['_2fDevices']
# 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: []
###
......@@ -155,20 +104,14 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
# Delete 2FA device
$scope.delete2FA = (type, epoch) ->
item = angular.element("#data-#{epoch}")
item = angular.element(".data-#{epoch}")
item.remove()
$scope.waiting = true
$http['delete']("#{scriptname}sfa/#{sessionType}/#{$scope.currentSession.id}?type=#{type}&epoch=#{epoch}").then (response) ->
#$scope.currentSession = null
#$scope.currentScope.remove()
#$scope.data = []
$scope.waiting = false
, (resp) ->
#$scope.currentSession = null
#$scope.currentScope.remove()
$scope.waiting = false
$scope.showT = false
#$scope.data = []
## Add 2FA device
#$scope.add2FA (type) = ->
......@@ -242,7 +185,10 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
else if key.match /^(_utime|_lastAuthnUTime|_lastSeen|notification)$/
session[key] = $scope.localeDate value
else if key.match /^(_startTime|_updateTime)$/
session[key] = _stToStr value
pattern = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/
arrayDate = value.match(pattern)
session[key] = "#{arrayDate[3]}/#{arrayDate[2]}/#{arrayDate[1]} à #{arrayDate[4]}:#{arrayDate[5]}:#{arrayDate[6]}"
#session[key] = _stToStr value
res = []
# 2. Push session keys in result, grouped by categories
......@@ -254,7 +200,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
subres.push
title: "type"
value: "name"
sdate: "date"
epoch: "date"
array = JSON.parse(session[attr]);
for sfDevice in array
for key, value of sfDevice
......@@ -263,21 +209,17 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
if key == 'name'
name = value
if key == 'epoch'
epoch = value
newDate = new Date(value * 1000)
myDate = newDate.toLocaleString()
epoch = value
subres.push
title: title
value: name
epoch: epoch
sdate: myDate
delete session[attr]
else
subres.push
title: attr
value: session[attr]
delete session[attr]
delete session[attr]
if subres.length >0
res.push
title: "__#{category}__"
......@@ -331,10 +273,6 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
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
......@@ -365,18 +303,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
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
......@@ -428,17 +355,6 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
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
......@@ -464,6 +380,7 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
# Default to '_whatToTrace'
c = $location.path().match /^\/(\w+)/
$scope.type = if c then c[1] else '_whatToTrace'
#$scope.myStyle = "{color: '#ffb84d'}"
]
......
......@@ -77,13 +77,14 @@ hiddenAttributes = '_password'
categories =
dateTitle: ['_utime', '_startTime', '_updateTime', '_lastAuthnUTime', '_lastSeen']
connectionTitle: ['ipAddr', '_timezone', '_url']
authenticationTitle:['_session_id', '_user', '_password', 'authenticationLevel', '_2fDevices']
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']
sfaTitle: ['_2fDevices']
# Menu entries
menu =
......@@ -195,7 +196,11 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
else if key.match /^(_utime|_lastAuthnUTime|_lastSeen|notification)$/
session[key] = $scope.localeDate value
else if key.match /^(_startTime|_updateTime)$/
session[key] = _stToStr value
#session[key] = _stToStr value
pattern = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/
arrayDate = value.match(pattern)
session[key] = "#{arrayDate[3]}/#{arrayDate[2]}/#{arrayDate[1]} à #{arrayDate[4]}:#{arrayDate[5]}:#{arrayDate[6]}"
res = []
......@@ -203,11 +208,33 @@ llapp.controller 'SessionsExplorerCtrl', ['$scope', '$translator', '$location',
for category, attrs of categories
subres = []
for attr in attrs
if session[attr]
subres.push
title: attr
value: session[attr]
delete session[attr]
if session[attr] and session[attr].match(/\w+/)
if session[attr].match(/"type":\s*"(?:TOTP|U2F|UBK)"/)
subres.push
title: "type"
value: "name"
epoch: "date"
array = JSON.parse(session[attr]);
for sfDevice in array
for key, value of sfDevice
if key == 'type'
title = value
if key == 'name'
name = value
if key == 'epoch'
epoch = value
subres.push
title: title
value: name
epoch: epoch
delete session[attr]
else
subres.push
title: attr
value: session[attr]
epoch: ''
delete session[attr]
if subres.length >0
res.push
title: "__#{category}__"
......
......@@ -35,27 +35,7 @@
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);
return t + "=" + v + "*";
}
]
};
......@@ -67,21 +47,13 @@
} 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'],
dateTitle: ['_utime', '_startTime', '_updateTime'],
sfaTitle: ['_2fDevices']
};
......@@ -150,7 +122,7 @@
};
$scope.delete2FA = function(type, epoch) {
var item;
item = angular.element("#data-" + epoch);
item = angular.element(".data-" + epoch);
item.remove();
$scope.waiting = true;
$http['delete'](scriptname + "sfa/" + sessionType + "/" + $scope.currentSession.id + "?type=" + type + "&epoch=" + epoch).then(function(response) {
......@@ -171,7 +143,7 @@
$scope.displaySession = function(scope) {
var sessionId, transformSession;
transformSession = function(session) {
var _insert, _stToStr, array, attr, attrs, category, epoch, i, id, k, key, len, len1, myDate, name, newDate, res, sfDevice, subres, time, title, value;
var _insert, _stToStr, array, arrayDate, attr, attrs, category, epoch, i, id, k, key, len, len1, name, pattern, res, sfDevice, subres, time, title, value;
_stToStr = function(s) {
return s;
};
......@@ -212,7 +184,9 @@
} else if (key.match(/^(_utime|_lastAuthnUTime|_lastSeen|notification)$/)) {
session[key] = $scope.localeDate(value);
} else if (key.match(/^(_startTime|_updateTime)$/)) {
session[key] = _stToStr(value);
pattern = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/;
arrayDate = value.match(pattern);
session[key] = arrayDate[3] + "/" + arrayDate[2] + "/" + arrayDate[1] + " à " + arrayDate[4] + ":" + arrayDate[5] + ":" + arrayDate[6];
}
}
}
......@@ -228,7 +202,7 @@
subres.push({
title: "type",
value: "name",
sdate: "date"
epoch: "date"
});
array = JSON.parse(session[attr]);
for (k = 0, len1 = array.length; k < len1; k++) {
......@@ -243,15 +217,12 @@
}
if (key === 'epoch') {
epoch = value;
newDate = new Date(value * 1000);
myDate = newDate.toLocaleString();
}
}
subres.push({
title: title,
value: name,
epoch: epoch,
sdate: myDate
epoch: epoch
});
}
delete session[attr];
......@@ -314,7 +285,7 @@
$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;
scheme = schemes[$scope.type] ? schemes[$scope.type] : 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)) {
......@@ -341,9 +312,6 @@
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);
}
......@@ -386,9 +354,6 @@
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);
}
......
(function(){var c,d,f,g,h,a,e,i,b;b=function(j,k){$("#msg").html(window.translate(j));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+k);if(k==="positive"){k="success"}return $("#color").addClass("alert-"+k)};d=function(l,k,n){var m;console.log("Error",n);m=JSON.parse(l.responseText);if(m&&m.error){m=m.error.replace(/.* /,"");console.log("Returned error",m);return b(m,"warning")}};h=25;i={_whatToTrace:[function(k,j){return"groupBy=substr("+k+",1)"},function(k,j){return k+"="+j+"*&groupBy="+k},function(k,j){return k+"="+j}],_startTime:[function(k,j){return"groupBy=substr("+k+",8)"},function(k,j){return k+"="+j+"*&groupBy=substr("+k+",10)"},function(k,j){return k+"="+j+"*&groupBy=substr("+k+",11)"},function(k,j){return k+"="+j+"*&groupBy=substr("+k+",12)"},function(k,j){return k+"="+j+"*&groupBy=_whatToTrace"},function(k,j,l){console.log(k);console.log(j);console.log(l);return l.replace(/\&groupBy.*$/,"")+("&_whatToTrace="+j)}]};e={_whatToTrace:function(k,j,m,l){if(m===1){return k+"="+j+"*&groupBy=substr("+k+","+(m+l+1)+")"}else{return null}},ipAddr:function(k,j,m,l){if(m>0&&m<4){return k+"="+j+"*&groupBy=net("+k+","+(16*m+4*(l+1))+",2)"}else{return null}}};f="_password";c={dateTitle:["_utime","_startTime","_updateTime","_lastAuthnUTime","_lastSeen"],connectionTitle:["ipAddr","_timezone","_url"],sfaTitle:["_2fDevices"]};a={home:[]};g=angular.module("llngSessionsExplorer",["ui.tree","ui.bootstrap","llApp"]);g.controller("SessionsExplorerCtrl",["$scope","$translator","$location","$q","$http",function(r,j,k,l,o){var p,n,m,q;r.links=links;r.menulinks=menulinks;r.staticPrefix=staticPrefix;r.scriptname=scriptname;r.formPrefix=formPrefix;r.availableLanguages=availableLanguages;r.waiting=true;r.showM=false;r.showT=true;r.data=[];r.currentScope=null;r.currentSession=null;r.menu=a;r.searchString="";r.translateP=j.translateP;r.translate=j.translate;r.translateTitle=function(s){return j.translateField(s,"title")};q="global";r.menuClick=function(s){if(s.popup){window.open(s.popup)}else{if(!s.action){s.action=s.title}switch(typeof s.action){case"function":s.action(r.currentNode,r);r[s.action]();break;case"string":r[s.action]();break;default:console.log(typeof s.action)}}return r.showM=false};r.search2FA=function(s){if(s){r.searchString=""}r.currentSession=null;r.data=[];return r.updateTree2("",r.data,0,0)};r.delete2FA=function(s,u){var t;t=angular.element("#data-"+u);t.remove();r.waiting=true;o["delete"](scriptname+"sfa/"+q+"/"+r.currentSession.id+"?type="+s+"&epoch="+u).then(function(v){return r.waiting=false},function(v){return r.waiting=false});return r.showT=false};r.stoggle=function(s){var t;t=s.$modelValue;if(t.nodes.length===0){r.updateTree(t.value,t.nodes,t.level,t.over,t.query,t.count)}return s.toggle()};r.displaySession=function(t){var u,s;s=function(v){var B,D,z,H,F,I,M,K,E,J,Q,L,A,w,R,y,P,C,N,x,O,G;D=function(S){return S};B=function(V,X){var T,U,S,W;S=[];U=new RegExp(V);for(T in v){W=v[T];if(T.match(U)&&W){S.push({title:T,value:W});delete v[T]}}if(S.length>0){return P.push({title:X,nodes:S})}};x=v._utime;E=v._session_id;for(Q in v){G=v[Q];if(!G){delete v[Q]}else{if(typeof v==="string"&&G.match(/; /)){v[Q]=G.split("; ")}if(typeof v[Q]!=="object"){if(f.match(new RegExp("\b"+Q+"\b"))){v[Q]="********"}else{if(Q.match(/^(_utime|_lastAuthnUTime|_lastSeen|notification)$/)){v[Q]=r.localeDate(G)}else{if(Q.match(/^(_startTime|_updateTime)$/)){v[Q]=D(G)}}}}}}P=[];for(I in c){F=c[I];N=[];for(K=0,L=F.length;K<L;K++){H=F[K];if(v[H]&&v[H].match(/\w+/)){if(v[H].match(/"type":\s*"(?:TOTP|U2F|UBK)"/)){N.push({title:"type",value:"name",sdate:"date"});z=JSON.parse(v[H]);for(J=0,A=z.length;J<A;J++){C=z[J];for(Q in C){G=C[Q];if(Q==="type"){O=G}if(Q==="name"){R=G}if(Q==="epoch"){M=G;y=new Date(G*1000);w=y.toLocaleString()}}N.push({title:O,value:R,epoch:M,sdate:w})}delete v[H]}else{N.push({title:H,value:v[H]});delete v[H]}}}if(N.length>0){P.push({title:"__"+I+"__",nodes:N})}}return{_utime:x,id:E,nodes:P}};r.currentScope=t;u=t.$modelValue.session;o.get(scriptname+"sfa/"+q+"/"+u).then(function(v){return r.currentSession=s(v.data)});return r.showT=false};r.localeDate=function(t){var u;u=new Date(t*1000);return u.toLocaleString()};r.getLanguage=function(s){r.lang=s;r.form="white";r.init();return r.showM=false};m=function(t,s,u){var v;v=s.match(/#\/(\w+)/);q="global";if(v===null){r.type="_whatToTrace"}else{if(v[1].match(/^(persistent)$/)){q=RegExp.$1;r.type="_session_uid"}else{r.type=v[1]}}return r.init()};r.$on("$locationChangeSuccess",m);p=0;r.updateTree=function(A,u,s,x,z,w){var y,t,v;r.waiting=true;t=i[r.type]?i[r.type]:r.type==="_updateTime"?i._startTime:i._whatToTrace;y=t[s](r.type,A,z);if(w>h&&e[r.type]){if(v=e[r.type](r.type,A,s,x,z)){x++;y=v;s=s-1}else{x=0}}else{x=0}return o.get(scriptname+"sfa/"+q+"?"+y+"&U2FCheck="+r.U2FCheck+"&TOTPCheck="+r.TOTPCheck).then(function(C){var F,D,B,G,E;F=C.data;if(F.result){E=F.values;for(D=0,B=E.length;D<B;D++){G=E[D];p++;G.id="node"+p;if(s<t.length-1){G.nodes=[];G.level=s+1;G.query=y;G.over=x;if(r.type.match(/^(?:start|update)Time$/)){G.title=G.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")}}u.push(G)}if(A===""){r.total=F.total}}return r.waiting=false},function(B){return r.waiting=false})};r.updateTree2=function(A,u,s,x,z,w){var y,t,v;r.waiting=true;t=i[r.type]?i[r.type]:r.type==="_updateTime"?i._startTime:i._whatToTrace;y=t[s](r.type,A,z);if(w>h&&e[r.type]){if(v=e[r.type](r.type,A,s,x,z)){x++;y=v;s=s-1}else{x=0}}else{x=0}return o.get(scriptname+"sfa/"+q+"?_session_uid="+r.searchString+"*&groupBy=substr(_session_uid,"+r.searchString.length+")&U2FCheck="+r.U2FCheck+"&TOTPCheck="+r.TOTPCheck+"&UBKCheck="+r.UBKCheck).then(function(C){var F,D,B,G,E;F=C.data;if(F.result){E=F.values;for(D=0,B=E.length;D<B;D++){G=E[D];p++;G.id="node"+p;if(s<t.length-1){G.nodes=[];G.level=s+1;G.query=y;G.over=x;if(r.type.match(/^(?:start|update)Time$/)){G.title=G.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")}}u.push(G)}if(A===""){r.total=F.total}}return r.waiting=false},function(B){return r.waiting=false})};r.init=function(){r.waiting=true;r.data=[];return l.all([j.init(r.lang),r.updateTree("",r.data,0,0)]).then(function(){return r.waiting=false},function(s){return r.waiting=false})};n=k.path().match(/^\/(\w+)/);return r.type=n?n[1]:"_whatToTrace"}])}).call(this);
\ No newline at end of file
(function(){var c,d,f,g,h,a,e,i,b;b=function(j,k){$("#msg").html(window.translate(j));$("#color").removeClass("message-positive message-warning alert-success alert-warning");$("#color").addClass("message-"+k);if(k==="positive"){k="success"}return $("#color").addClass("alert-"+k)};d=function(l,k,n){var m;console.log("Error",n);m=JSON.parse(l.responseText);if(m&&m.error){m=m.error.replace(/.* /,"");console.log("Returned error",m);return b(m,"warning")}};h=25;i={_whatToTrace:[function(k,j){return"groupBy=substr("+k+",1)"},function(k,j){return k+"="+j+"*"}]};e={_whatToTrace:function(k,j,m,l){if(m===1){return k+"="+j+"*&groupBy=substr("+k+","+(m+l+1)+")"}else{return null}}};f="_password";c={dateTitle:["_utime","_startTime","_updateTime"],sfaTitle:["_2fDevices"]};a={home:[]};g=angular.module("llngSessionsExplorer",["ui.tree","ui.bootstrap","llApp"]);g.controller("SessionsExplorerCtrl",["$scope","$translator","$location","$q","$http",function(r,j,k,l,o){var p,n,m,q;r.links=links;r.menulinks=menulinks;r.staticPrefix=staticPrefix;r.scriptname=scriptname;r.formPrefix=formPrefix;r.availableLanguages=availableLanguages;r.waiting=true;