WIP - Viewer SPA (#1661)

This commit is contained in:
Christophe Maudoux 2019-03-12 22:59:15 +01:00
parent 4201fe25d8
commit c06ea5d5f1
8 changed files with 883 additions and 349 deletions

View File

@ -119,10 +119,6 @@
"namespace" : "lemonldap-ng-sessions"
},
"locationRules" : {
"auth.__DNSDOMAIN__" : {
"(?#checkUser)/checkuser" : "$uid eq \"dwho\"",
"default" : "deny"
},
"manager.__DNSDOMAIN__" : {
"(?#Configuration)^/(manager\\.html|conf/)" : "$uid eq \"dwho\"",
"(?#Notifications)/notifications" : "$uid eq \"dwho\" or $uid eq \"rtyler\"",

View File

@ -38,7 +38,7 @@ useRedirectOnError = 0
[manager]
enabledModules = conf, sessions, notifications, 2ndFA
enabledModules = conf, sessions, notifications, 2ndFA, viewer
protection = manager
staticPrefix = /static
languages = fr, en, vi, ar, de, it, zh

View File

@ -94,7 +94,8 @@ sub init {
'conf' => 'cog',
'sessions' => 'duplicate',
'notifications' => 'bell',
'2ndFA' => 'wrench'
'2ndFA' => 'wrench',
'viewer' => 'eye-open',
};
$self->links( [] );

View File

@ -39,7 +39,7 @@ sub addRoutes {
# READ
# Special keys
->addRoute(
confs => {
view => {
':cfgNum' => [
qw(virtualHosts samlIDPMetaDataNodes samlSPMetaDataNodes
applicationList oidcOPMetaDataNodes oidcRPMetaDataNodes
@ -52,20 +52,13 @@ sub addRoutes {
)
# Other keys
->addRoute( confs => { ':cfgNum' => { '*' => 'getKey' } }, ['GET'] )
->addRoute( view => { ':cfgNum' => { '*' => 'getKey' } }, ['GET'] )
# Difference between confs
->addRoute( diff => { ':conf1' => { ':conf2' => 'diff' } } )
->addRoute( 'diff.html', undef, ['GET'] )
}
# 35 - New RSA key pair on demand
# --------------------------
# 36 - URL File loader
# ---------------
##@method public PSGI-JSON-response prx()
# Load file using posted URL and return its content
#

View File

@ -138,71 +138,71 @@ llapp.controller 'TreeCtrl', [
# SAVE FUNCTIONS
# Private method called by $scope.save()
_checkSaveResponse = (data) ->
$scope.message =
title: ''
message: ''
items: []
$scope.confirmNeeded = true if data.needConfirm
$scope.message.message = data.message if data.message
if data.details
for m of data.details when m != '__changes__'
if m == '__needConfirmation__'
$scope.message.items.unshift
message: m
items: data.details[m]
else
$scope.message.items.push
message: m
items: data.details[m]
$scope.waiting = false
if data.result == 1
# Force reloading page
$location.path '/confs/'
$scope.message.title = 'successfullySaved'
else
$scope.message.title = 'saveReport'
$scope.showModal 'message.html'
# # Private method called by $scope.save()
# _checkSaveResponse = (data) ->
# $scope.message =
# title: ''
# message: ''
# items: []
# $scope.confirmNeeded = true if data.needConfirm
# $scope.message.message = data.message if data.message
# if data.details
# for m of data.details when m != '__changes__'
# if m == '__needConfirmation__'
# $scope.message.items.unshift
# message: m
# items: data.details[m]
# else
# $scope.message.items.push
# message: m
# items: data.details[m]
# $scope.waiting = false
# if data.result == 1
# # Force reloading page
# $location.path '/confs/'
# $scope.message.title = 'successfullySaved'
# else
# $scope.message.title = 'saveReport'
# $scope.showModal 'message.html'
# Download raw conf
$scope.downloadConf = () ->
window.open $scope.confPrefix + $scope.currentCfg.cfgNum + '?full=1'
# Main save function
$scope.save = ->
$scope.showModal('save.html').then ->
$scope.waiting = true
$scope.data.push
id: "cfgLog"
title: "cfgLog"
data: if $scope.result then $scope.result else ''
$http.post("#{window.confPrefix}?cfgNum=#{$scope.currentCfg.cfgNum}#{if $scope.forceSave then "&force=1" else ''}", $scope.data).then (response) ->
$scope.data.pop()
_checkSaveResponse response.data
,(response) ->
readError response
$scope.data.pop()
, ->
console.log 'Saving canceled'
$scope.showM = false
# Raw save function
$scope.saveRawConf = ($fileContent) ->
$scope.waiting = true
$http.post("#{window.confPrefix}/raw", $fileContent).then (response) ->
_checkSaveResponse(response.data)
, readError
# Restore raw conffunction
$scope.restore = ->
$scope.currentNode = null
$scope.form = 'restore'
# Cancel save function
$scope.cancel = ->
$scope.currentNode.data = null
$scope.getKey($scope.currentNode)
# # Main save function
# $scope.save = ->
# $scope.showModal('save.html').then ->
# $scope.waiting = true
# $scope.data.push
# id: "cfgLog"
# title: "cfgLog"
# data: if $scope.result then $scope.result else ''
# $http.post("#{window.confPrefix}?cfgNum=#{$scope.currentCfg.cfgNum}#{if $scope.forceSave then "&force=1" else ''}", $scope.data).then (response) ->
# $scope.data.pop()
# _checkSaveResponse response.data
# ,(response) ->
# readError response
# $scope.data.pop()
# , ->
# console.log 'Saving canceled'
# $scope.showM = false
#
# # Raw save function
# $scope.saveRawConf = ($fileContent) ->
# $scope.waiting = true
# $http.post("#{window.confPrefix}/raw", $fileContent).then (response) ->
# _checkSaveResponse(response.data)
# , readError
#
# # Restore raw conffunction
# $scope.restore = ->
# $scope.currentNode = null
# $scope.form = 'restore'
#
# # Cancel save function
# $scope.cancel = ->
# $scope.currentNode.data = null
# $scope.getKey($scope.currentNode)
# NODES MANAGEMENT
id = 1
@ -219,202 +219,202 @@ llapp.controller 'TreeCtrl', [
cs = cs.$parentNodeScope
return cs
# Add grant rule entry
$scope.newGrantRule = ->
node = $scope._findContainer()
l = node.nodes.length
n = if l > 0 then l - 1 else 0
node.nodes.push
id: "#{node.id}/n#{id++}"
title: 'New rule'
re: 'Message'
comment: 'New rule'
data: '1'
type: "grant"
# # Add grant rule entry
# $scope.newGrantRule = ->
# node = $scope._findContainer()
# l = node.nodes.length
# n = if l > 0 then l - 1 else 0
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: 'New rule'
# re: 'Message'
# comment: 'New rule'
# data: '1'
# type: "grant"
#
# # Add rules entry
# $scope.newRule = ->
# node = $scope._findContainer()
# l = node.nodes.length
# n = if l > 0 then l - 1 else 0
# node.nodes.splice n, 0,
# id: "#{node.id}/n#{id++}"
# title: 'New rule'
# re: '^/new'
# comment: 'New rule'
# data: 'accept'
# type: "rule"
#
# # Add form replay
# $scope.newPost = ->
# node = $scope._findContainer()
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: "/absolute/path/to/form"
# data: {}
# type: "post"
#
# $scope.newPostVar = ->
# $scope.currentNode.data.vars = [] unless $scope.currentNode.data.vars?
# $scope.currentNode.data.vars.push ['var1', '$uid']
#
# # Add auth chain entry to authChoice
# $scope.newAuthChoice = ->
# node = $scope._findContainer()
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: "1_Key"
# data: ['Null', 'Null', 'Null']
# type: "authChoice"
# $scope.execFilters $scope._findScopeByKey 'authParams'
#
# # Add hash entry
# $scope.newHashEntry = ->
# node = $scope._findContainer()
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: 'new'
# data: ''
# type: "keyText"
#
# # Menu cat entry
# $scope.newCat = ->
# cs = $scope.currentScope
# if cs.$modelValue.type == 'menuApp'
# cs = cs.$parentNodeScope
# cs.$modelValue.nodes.push
# id: "#{cs.$modelValue.id}/n#{id++}"
# title: "New category"
# type: "menuCat"
# nodes: []
#
# # Menu app entry
# $scope.newApp = ->
# cs = $scope.currentScope
# if cs.$modelValue.type == 'menuApp'
# cs = cs.$parentNodeScope
# cs.$modelValue.nodes.push
# id: "#{cs.$modelValue.id}/n#{id++}"
# title: "New application"
# type: "menuApp"
# data:
# description: "New app description"
# uri: "https://test.example.com/"
# logo: "network.png"
# display: "auto"
#
# # Combination module
# $scope.newCmbMod = ->
# node = $scope._findContainer()
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: 'new'
# type: 'cmbModule'
# data:
# type: 'LDAP'
# for: '0'
# over: []
# $scope.execFilters $scope._findScopeByKey 'authParams'
#
# $scope.newCmbOver = ->
# d = $scope.currentNode.data
# d.over = [] unless d.over
# d.over.push ["new#{id++}", '']
#
# $scope.newChoiceOver = ->
# d = $scope.currentNode.data
# console.log "data", d
# d[5] = [] unless d[5]
# d[5].push ["new#{id++}", '']
#
# # Add host
# $scope.addHost = () ->
# cn = $scope.currentNode
# cn.data=[] unless cn.data
# cn.data.push
# k: "newHost"
# h: [{"k":"key","v":"uid"}]
#
# # SAML attribute entry
# $scope.addSamlAttribute = ->
# node = $scope._findContainer()
# node.nodes.push
# id: "#{node.id}/n#{id++}"
# title: 'new'
# type: 'samlAttribute'
# data: ['0', 'New', '', '']
#
# # Nodes with template
# $scope.addVhost = ->
# name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
# $scope.message =
# title: 'virtualHostName'
# field: 'hostname'
# $scope.showModal('prompt.html', name).then ->
# n= $scope.result
# if n
# $scope.addTemplateNode n, 'virtualHost'
#
# $scope.duplicateVhost = ->
# name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
# $scope.message =
# title: 'virtualHostName',
# field: 'hostname'
# $scope.showModal('prompt.html', name).then ->
# n = $scope.result
# return $scope.duplicateNode n, 'virtualHost', $scope.currentNode.title
#
# $scope.addSamlIDP = ->
# $scope.newTemplateNode 'samlIDPMetaDataNode', 'samlPartnerName', 'idp-example'
#
# $scope.addSamlSP = ->
# $scope.newTemplateNode 'samlSPMetaDataNode', 'samlPartnerName', 'sp-example'
#
# $scope.addOidcOp = ->
# $scope.newTemplateNode 'oidcOPMetaDataNode', 'oidcOPName', 'op-example'
#
# $scope.addOidcRp = ->
# $scope.newTemplateNode 'oidcRPMetaDataNode', 'oidcRPName', 'rp-example'
#
# $scope.addCasSrv = ->
# $scope.newTemplateNode 'casSrvMetaDataNode', 'casPartnerName', 'srv-example'
#
# $scope.addCasApp = ->
# $scope.newTemplateNode 'casAppMetaDataNode', 'casPartnerName', 'app-example'
#
# $scope.newTemplateNode = (type, title, init) ->
# $scope.message =
# title: title
# field: 'name'
# $scope.showModal('prompt.html', init).then ->
# name = $scope.result
# if (name)
# $scope.addTemplateNode name, type
#
# $scope.addTemplateNode = (name, type) ->
# cs = $scope.currentScope
# while cs.$modelValue.title != "#{type}s"
# cs = cs.$parentNodeScope
# t =
# id: "#{type}s/new__#{name}"
# title: name
# type: type
# nodes: templates type, "new__#{name}"
# setDefault t.nodes
# cs.$modelValue.nodes.push t
# cs.expand()
# return t
# Add rules entry
$scope.newRule = ->
node = $scope._findContainer()
l = node.nodes.length
n = if l > 0 then l - 1 else 0
node.nodes.splice n, 0,
id: "#{node.id}/n#{id++}"
title: 'New rule'
re: '^/new'
comment: 'New rule'
data: 'accept'
type: "rule"
# Add form replay
$scope.newPost = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: "/absolute/path/to/form"
data: {}
type: "post"
$scope.newPostVar = ->
$scope.currentNode.data.vars = [] unless $scope.currentNode.data.vars?
$scope.currentNode.data.vars.push ['var1', '$uid']
# Add auth chain entry to authChoice
$scope.newAuthChoice = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: "1_Key"
data: ['Null', 'Null', 'Null']
type: "authChoice"
$scope.execFilters $scope._findScopeByKey 'authParams'
# Add hash entry
$scope.newHashEntry = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: 'new'
data: ''
type: "keyText"
# Menu cat entry
$scope.newCat = ->
cs = $scope.currentScope
if cs.$modelValue.type == 'menuApp'
cs = cs.$parentNodeScope
cs.$modelValue.nodes.push
id: "#{cs.$modelValue.id}/n#{id++}"
title: "New category"
type: "menuCat"
nodes: []
# Menu app entry
$scope.newApp = ->
cs = $scope.currentScope
if cs.$modelValue.type == 'menuApp'
cs = cs.$parentNodeScope
cs.$modelValue.nodes.push
id: "#{cs.$modelValue.id}/n#{id++}"
title: "New application"
type: "menuApp"
data:
description: "New app description"
uri: "https://test.example.com/"
logo: "network.png"
display: "auto"
# Combination module
$scope.newCmbMod = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: 'new'
type: 'cmbModule'
data:
type: 'LDAP'
for: '0'
over: []
$scope.execFilters $scope._findScopeByKey 'authParams'
$scope.newCmbOver = ->
d = $scope.currentNode.data
d.over = [] unless d.over
d.over.push ["new#{id++}", '']
$scope.newChoiceOver = ->
d = $scope.currentNode.data
console.log "data", d
d[5] = [] unless d[5]
d[5].push ["new#{id++}", '']
# Add host
$scope.addHost = () ->
cn = $scope.currentNode
cn.data=[] unless cn.data
cn.data.push
k: "newHost"
h: [{"k":"key","v":"uid"}]
# SAML attribute entry
$scope.addSamlAttribute = ->
node = $scope._findContainer()
node.nodes.push
id: "#{node.id}/n#{id++}"
title: 'new'
type: 'samlAttribute'
data: ['0', 'New', '', '']
# Nodes with template
$scope.addVhost = ->
name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
$scope.message =
title: 'virtualHostName'
field: 'hostname'
$scope.showModal('prompt.html', name).then ->
n= $scope.result
if n
$scope.addTemplateNode n, 'virtualHost'
$scope.duplicateVhost = ->
name = if $scope.domain then ".#{$scope.domain.data}" else '.example.com'
$scope.message =
title: 'virtualHostName',
field: 'hostname'
$scope.showModal('prompt.html', name).then ->
n = $scope.result
return $scope.duplicateNode n, 'virtualHost', $scope.currentNode.title
$scope.addSamlIDP = ->
$scope.newTemplateNode 'samlIDPMetaDataNode', 'samlPartnerName', 'idp-example'
$scope.addSamlSP = ->
$scope.newTemplateNode 'samlSPMetaDataNode', 'samlPartnerName', 'sp-example'
$scope.addOidcOp = ->
$scope.newTemplateNode 'oidcOPMetaDataNode', 'oidcOPName', 'op-example'
$scope.addOidcRp = ->
$scope.newTemplateNode 'oidcRPMetaDataNode', 'oidcRPName', 'rp-example'
$scope.addCasSrv = ->
$scope.newTemplateNode 'casSrvMetaDataNode', 'casPartnerName', 'srv-example'
$scope.addCasApp = ->
$scope.newTemplateNode 'casAppMetaDataNode', 'casPartnerName', 'app-example'
$scope.newTemplateNode = (type, title, init) ->
$scope.message =
title: title
field: 'name'
$scope.showModal('prompt.html', init).then ->
name = $scope.result
if (name)
$scope.addTemplateNode name, type
$scope.addTemplateNode = (name, type) ->
cs = $scope.currentScope
while cs.$modelValue.title != "#{type}s"
cs = cs.$parentNodeScope
t =
id: "#{type}s/new__#{name}"
title: name
type: type
nodes: templates type, "new__#{name}"
setDefault t.nodes
cs.$modelValue.nodes.push t
cs.expand()
return t
setDefault = (node) ->
for n in node
if n.cnodes and n.default
delete n.cnodes
n._nodes = n.default
if n._nodes
setDefault n._nodes
else if n.default or n.default == 0
n.data = n.default
node
# setDefault = (node) ->
# for n in node
# if n.cnodes and n.default
# delete n.cnodes
# n._nodes = n.default
# if n._nodes
# setDefault n._nodes
# else if n.default or n.default == 0
# n.data = n.default
# node
_getAll = (node) ->
d = $q.defer()
@ -439,24 +439,24 @@ llapp.controller 'TreeCtrl', [
d2.resolve()
return d2.promise
$scope.duplicateNode = (name, type, idkey) ->
cs = $scope.currentScope
_getAll($scope.currentNode).then ->
while cs.$modelValue.title != "#{type}s"
cs = cs.$parentNodeScope
t = JSON.parse JSON.stringify($scope.currentNode).replace(new RegExp(idkey, 'g'), 'new__' + name)
t.id = "#{type}s/new__#{name}"
t.title = name
cs.$modelValue.nodes.push(t)
return t
# $scope.duplicateNode = (name, type, idkey) ->
# cs = $scope.currentScope
# _getAll($scope.currentNode).then ->
# while cs.$modelValue.title != "#{type}s"
# cs = cs.$parentNodeScope
# t = JSON.parse JSON.stringify($scope.currentNode).replace(new RegExp(idkey, 'g'), 'new__' + name)
# t.id = "#{type}s/new__#{name}"
# t.title = name
# cs.$modelValue.nodes.push(t)
# return t
$scope.del = (a, i) ->
a.splice(i, 1)
# $scope.del = (a, i) ->
# a.splice(i, 1)
$scope.deleteEntry = ->
p = $scope.currentScope.$parentNodeScope
$scope.currentScope.remove()
$scope.displayForm p
# $scope.deleteEntry = ->
# p = $scope.currentScope.$parentNodeScope
# $scope.currentScope.remove()
# $scope.displayForm p
$scope.down = ->
id = $scope.currentNode.id
@ -608,44 +608,44 @@ llapp.controller 'TreeCtrl', [
$scope.showT = false
setHelp scope
$scope.keyWritable = (scope) ->
node = scope.$modelValue
# regexp-assemble of:
# authChoice
# keyText
# cmbModule
# virtualHost
# rule
# menuCat
# menuApp
# samlAttribute
# samlIDPMetaDataNode
# samlSPMetaDataNode
return if node.type and node.type.match /^(?:(?:saml(?:(?:ID|S)PMetaDataNod|Attribut)|(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/ then true else false
# $scope.keyWritable = (scope) ->
# node = scope.$modelValue
# # regexp-assemble of:
# # authChoice
# # keyText
# # cmbModule
# # virtualHost
# # rule
# # menuCat
# # menuApp
# # samlAttribute
# # samlIDPMetaDataNode
# # samlSPMetaDataNode
# return if node.type and node.type.match /^(?:(?:saml(?:(?:ID|S)PMetaDataNod|Attribut)|(?:cmbMod|r)ul|authChoic)e|(?:virtualHos|keyTex)t|menu(?:App|Cat))$/ then true else false
#
# RSA keys generation
$scope.newRSAKey = ->
$scope.showModal('password.html').then ->
$scope.waiting = true
currentNode = $scope.currentNode
password = $scope.result
$http.post("#{window.confPrefix}/newRSAKey", {"password": password}).then (response) ->
currentNode.data[0].data = response.data.private
currentNode.data[1].data = password
currentNode.data[2].data = response.data.public
$scope.waiting = false
, readError
, ->
console.log('New key cancelled')
# $scope.newRSAKey = ->
# $scope.showModal('password.html').then ->
# $scope.waiting = true
# currentNode = $scope.currentNode
# password = $scope.result
# $http.post("#{window.confPrefix}/newRSAKey", {"password": password}).then (response) ->
# currentNode.data[0].data = response.data.private
# currentNode.data[1].data = password
# currentNode.data[2].data = response.data.public
# $scope.waiting = false
# , readError
# , ->
# console.log('New key cancelled')
$scope.newRSAKeyNoPassword = ->
$scope.waiting = true
currentNode = $scope.currentNode
$http.post("#{window.confPrefix}/newRSAKey", {"password": ''}).then (response) ->
currentNode.data[0].data = response.data.private
currentNode.data[1].data = response.data.public
$scope.waiting = false
, readError
# $scope.newRSAKeyNoPassword = ->
# $scope.waiting = true
# currentNode = $scope.currentNode
# $http.post("#{window.confPrefix}/newRSAKey", {"password": ''}).then (response) ->
# currentNode.data[0].data = response.data.private
# currentNode.data[1].data = response.data.public
# $scope.waiting = false
# , readError
# method `getKey()`:
# - return a promise with the data:
@ -679,7 +679,7 @@ llapp.controller 'TreeCtrl', [
node.data = data.value
# Cast int as int (remember that booleans are int for Perl)
if node.type and node.type.match /^int$/
node.data = parseInt(node.data, 10)
node.data = parseInt(node.data, 10)
# Split SAML types
else if node.type and node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) and not (typeof node.data == 'object')
node.data = node.data.split ';'
@ -696,9 +696,9 @@ llapp.controller 'TreeCtrl', [
# Called when $location.path() change, launch getCfg() with the new
# configuration number
pathEvent = (event, next, current) ->
n = next.match(new RegExp('#!?/confs/(latest|[0-9]+)'))
n = next.match(new RegExp('#!?/view/(latest|[0-9]+)'))
if n == null
$location.path '/confs/latest'
$location.path '/view/latest'
else
console.log "Trying to get cfg number #{n[1]}"
$scope.getCfg n[1]
@ -713,7 +713,7 @@ llapp.controller 'TreeCtrl', [
d = new Date $scope.currentCfg.cfgDate * 1000
$scope.currentCfg.date = d.toLocaleString()
console.log "Metadatas of cfg #{n} loaded"
$location.path "/confs/#{n}"
$location.path "/view/#{n}"
$scope.init()
, (response) ->
readError(response).then ->
@ -763,31 +763,31 @@ llapp.controller 'TreeCtrl', [
$scope.waiting = false
, readError
# Colorized link
$scope.activeModule = "conf"
$scope.activeModule = "viewer"
$scope.myStyle = {color: '#ffb84d'}
c = $location.path().match(new RegExp('^/confs/(latest|[0-9]+)'))
c = $location.path().match(new RegExp('^/view/(latest|[0-9]+)'))
unless c
console.log "Redirecting to /confs/latest"
$location.path '/confs/latest'
console.log "Redirecting to /view/latest"
$location.path '/view/latest'
# File form function
$scope.replaceContentByUrl = (node, url) ->
$scope.waiting = true
$http.post(window.scriptname + "prx", {url: url}).then (response) ->
node.data = response.data.content
$scope.waiting = false
, readError
$scope.replaceContent = (node, $fileContent) ->
node.data = $fileContent
#$scope.replaceContentByUrl = (node, url) ->
# $scope.waiting = true
# $http.post(window.scriptname + "prx", {url: url}).then (response) ->
# node.data = response.data.content
# $scope.waiting = false
# , readError
#$scope.replaceContent = (node, $fileContent) ->
# node.data = $fileContent
# Import Filesaver.js saveAs()
$scope.saveAs = (content, type, filename) ->
saveAs(new Blob([content], {"type": type}), filename)
## Import Filesaver.js saveAs()
#$scope.saveAs = (content, type, filename) ->
# saveAs(new Blob([content], {"type": type}), filename)
# Save as pem, text,...
$scope.saveAsPem = (cs,scope) ->
scope.saveAs "#{cs.data[0].data}\n#{cs.data[2].data}", 'application/x-pem-file', "#{cs.title}.pem"
$scope.saveAsText = (cs,scope) ->
scope.saveAs cs.data, 'text/plain', "#{cs.title}.txt"
## Save as pem, text,...
#$scope.saveAsPem = (cs,scope) ->
# scope.saveAs "#{cs.data[0].data}\n#{cs.data[2].data}", 'application/x-pem-file', "#{cs.title}.pem"
#$scope.saveAsText = (cs,scope) ->
# scope.saveAs cs.data, 'text/plain', "#{cs.title}.txt"
]

View File

@ -0,0 +1,539 @@
// Generated by CoffeeScript 1.12.7
/*
LemonLDAP::NG Manager client
This is the main app file. Other are:
- struct.json and js/confTree.js that contains the full tree
- translate.json that contains the keywords translation
This file contains:
- the AngularJS controller
*/
(function() {
var llapp;
llapp = angular.module('llngManager', ['ui.tree', 'ui.bootstrap', 'llApp', 'ngCookies']);
/*
Main AngularJS controller
*/
llapp.controller('TreeCtrl', [
'$scope', '$http', '$location', '$q', '$uibModal', '$translator', '$cookies', '$htmlParams', function($scope, $http, $location, $q, $uibModal, $translator, $cookies, $htmlParams) {
var _download, _getAll, _stoggle, c, id, pathEvent, readError, setHelp;
$scope.links = window.links;
$scope.menu = $htmlParams.menu;
$scope.menulinks = window.menulinks;
$scope.staticPrefix = window.staticPrefix;
$scope.formPrefix = window.formPrefix;
$scope.availableLanguages = window.availableLanguages;
$scope.waiting = true;
$scope.showM = false;
$scope.showT = false;
$scope.form = 'home';
$scope.currentCfg = {};
$scope.confPrefix = window.confPrefix;
$scope.message = {};
$scope.result = '';
$scope.translateTitle = function(node) {
return $translator.translateField(node, 'title');
};
$scope.translateP = $translator.translateP;
$scope.translate = $translator.translate;
$scope.helpUrl = 'start.html#configuration';
$scope.setShowHelp = function(val) {
var d;
if (val == null) {
val = !$scope.showH;
}
$scope.showH = val;
d = new Date(Date.now());
d.setFullYear(d.getFullYear() + 1);
return $cookies.put('showhelp', (val ? 'true' : 'false'), {
"expires": d
});
};
$scope.showH = $cookies.get('showhelp') === 'false' ? false : true;
if ($scope.showH == null) {
$scope.setShowHelp(true);
}
readError = function(response) {
var e, j;
e = response.status;
j = response.statusLine;
$scope.waiting = false;
if (e === 403) {
$scope.message = {
title: 'forbidden',
message: '',
items: []
};
} else if (e === 401) {
console.log('Authentication needed');
$scope.message = {
title: 'authenticationNeeded',
message: '__waitOrF5__',
items: []
};
} else if (e === 400) {
$scope.message = {
title: 'badRequest',
message: j,
items: []
};
} else if (e > 0) {
$scope.message = {
title: 'badRequest',
message: j,
items: []
};
} else {
$scope.message = {
title: 'networkProblem',
message: '',
items: []
};
}
return $scope.showModal('message.html');
};
$scope.showModal = function(tpl, init) {
var d, modalInstance;
modalInstance = $uibModal.open({
templateUrl: tpl,
controller: 'ModalInstanceCtrl',
size: 'lg',
resolve: {
elem: function() {
return function(s) {
return $scope[s];
};
},
set: function() {
return function(f, s) {
return $scope[f] = s;
};
},
init: function() {
return init;
}
}
});
d = $q.defer();
modalInstance.result.then(function(msgok) {
$scope.message = {
title: '',
message: '',
items: []
};
return d.resolve(msgok);
}, function(msgnok) {
$scope.message = {
title: '',
message: '',
items: []
};
return d.reject(msgnok);
});
return d.promise;
};
$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.home = function() {
$scope.form = 'home';
return $scope.showM = false;
};
$scope.downloadConf = function() {
return window.open($scope.confPrefix + $scope.currentCfg.cfgNum + '?full=1');
};
id = 1;
$scope._findContainer = function() {
return $scope._findScopeContainer().$modelValue;
};
$scope._findScopeContainer = function() {
var cs;
cs = $scope.currentScope;
while (!cs.$modelValue.type.match(/Container$/)) {
cs = cs.$parentNodeScope;
}
return cs;
};
$scope._findScopeByKey = function(k) {
var cs;
cs = $scope.currentScope;
while (!(cs.$modelValue.title === k)) {
cs = cs.$parentNodeScope;
}
return cs;
};
_getAll = function(node) {
var d, d2;
d = $q.defer();
d2 = $q.defer();
if (node._nodes) {
_stoggle(node);
d.resolve();
} else if (node.cnodes) {
_download(node).then(function() {
return d.resolve();
});
} else if (node.nodes || node.data) {
d.resolve();
} else {
$scope.getKey(node).then(function() {
return d.resolve();
});
}
d.promise.then(function() {
var l, len, n, ref, t;
t = [];
if (node.nodes) {
ref = node.nodes;
for (l = 0, len = ref.length; l < len; l++) {
n = ref[l];
t.push(_getAll(n));
}
}
return $q.all(t).then(function() {
return d2.resolve();
});
});
return d2.promise;
};
$scope.down = function() {
var i, ind, l, len, n, p, ref, tmp;
id = $scope.currentNode.id;
p = $scope.currentScope.$parentNodeScope.$modelValue;
ind = p.nodes.length;
ref = p.nodes;
for (i = l = 0, len = ref.length; l < len; i = ++l) {
n = ref[i];
if (n.id === id) {
ind = i;
}
}
if (ind < p.nodes.length - 1) {
tmp = p.nodes[ind];
p.nodes[ind] = p.nodes[ind + 1];
p.nodes[ind + 1] = tmp;
}
return ind;
};
$scope.up = function() {
var i, ind, l, len, n, p, ref, tmp;
id = $scope.currentNode.id;
p = $scope.currentScope.$parentNodeScope.$modelValue;
ind = -1;
ref = p.nodes;
for (i = l = 0, len = ref.length; l < len; i = ++l) {
n = ref[i];
if (n.id === id) {
ind = i;
}
}
if (ind > 0) {
tmp = p.nodes[ind];
p.nodes[ind] = p.nodes[ind - 1];
p.nodes[ind - 1] = tmp;
}
return ind;
};
$scope.inSelect = function(value) {
var l, len, n, ref;
ref = $scope.currentNode.select;
for (l = 0, len = ref.length; l < len; l++) {
n = ref[l];
if (n.k === value) {
return true;
}
}
return false;
};
$scope.changeRuleTitle = function(node) {
return node.title = node.comment.length > 0 ? node.comment : node.re;
};
$scope.filters = {};
$scope.execFilters = function(scope) {
var filter, func, ref;
scope = scope ? scope : $scope;
ref = $scope.filters;
for (filter in ref) {
func = ref[filter];
if ($scope.filters.hasOwnProperty(filter)) {
return window.filterFunctions[filter](scope, $q, func);
}
}
return false;
};
$scope.stoggle = function(scope) {
var node;
node = scope.$modelValue;
_stoggle(node);
return scope.toggle();
};
_stoggle = function(node) {
var a, l, len, len1, len2, m, n, o, ref, ref1, ref2;
ref = ['nodes', 'nodes_cond'];
for (l = 0, len = ref.length; l < len; l++) {
n = ref[l];
if (node["_" + n]) {
node[n] = [];
ref1 = node["_" + n];
for (m = 0, len1 = ref1.length; m < len1; m++) {
a = ref1[m];
node[n].push(a);
}
delete node["_" + n];
}
}
if (node._nodes_filter) {
if (node.nodes) {
ref2 = node.nodes;
for (o = 0, len2 = ref2.length; o < len2; o++) {
n = ref2[o];
n.onChange = $scope.execFilters;
}
}
$scope.filters[node._nodes_filter] = node;
return $scope.execFilters();
}
};
$scope.toggle = function(scope) {
return scope.toggle();
};
$scope.download = function(scope) {
var node;
node = scope.$modelValue;
return _download(node);
};
_download = function(node) {
var d;
d = $q.defer();
d.notify('Trying to get datas');
$scope.waiting = true;
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + node.cnodes).then(function(response) {
var a, data, l, len;
data = response.data;
if (!data) {
d.reject('Empty response from server');
} else if (data.error) {
if (data.error.match(/setDefault$/)) {
if (node['default']) {
node.nodes = node['default'].slice(0);
} else {
node.nodes = [];
}
delete node.cnodes;
d.resolve('Set data to default value');
} else {
d.reject("Server return an error: " + data.error);
}
} else {
delete node.cnodes;
if (!node.type) {
node.type = 'keyTextContainer';
}
node.nodes = [];
for (l = 0, len = data.length; l < len; l++) {
a = data[l];
if (a.template) {
a._nodes = templates(a.template, a.title);
}
node.nodes.push(a);
}
d.resolve('OK');
}
return $scope.waiting = false;
}, function(response) {
readError(response);
return d.reject('');
});
return d.promise;
};
$scope.openCnode = function(scope) {
return $scope.download(scope).then(function() {
return scope.toggle();
});
};
setHelp = function(scope) {
while (!scope.$modelValue.help && scope.$parentNodeScope) {
scope = scope.$parentNodeScope;
}
return $scope.helpUrl = scope.$modelValue.help || 'start.html#configuration';
};
$scope.displayForm = function(scope) {
var f, l, len, n, node, ref;
node = scope.$modelValue;
if (node.cnodes) {
$scope.download(scope);
}
if (node._nodes) {
$scope.stoggle(scope);
}
$scope.currentNode = node;
$scope.currentScope = scope;
f = node.type ? node.type : 'text';
if (node.nodes || node._nodes || node.cnodes) {
$scope.form = f !== 'text' ? f : 'mini';
} else {
$scope.form = f;
$scope.getKey(node);
}
if (node.type && node.type === 'simpleInputContainer') {
ref = node.nodes;
for (l = 0, len = ref.length; l < len; l++) {
n = ref[l];
$scope.getKey(n);
}
}
$scope.showT = false;
return setHelp(scope);
};
$scope.getKey = function(node) {
var d, i, l, len, n, ref, tmp;
d = $q.defer();
if (!node.data) {
$scope.waiting = true;
if (node.get && typeof node.get === 'object') {
node.data = [];
tmp = [];
ref = node.get;
for (i = l = 0, len = ref.length; l < len; i = ++l) {
n = ref[i];
node.data[i] = {
title: n,
id: n
};
tmp.push($scope.getKey(node.data[i]));
}
$q.all(tmp).then(function() {
return d.resolve(node.data);
}, function(response) {
d.reject(response.statusLine);
return $scope.waiting = false;
});
} else {
$http.get("" + window.confPrefix + $scope.currentCfg.cfgNum + "/" + (node.get ? node.get : node.title)).then(function(response) {
var data;
data = response.data;
if ((data.value === null || (data.error && data.error.match(/setDefault$/))) && node['default'] !== null) {
node.data = node['default'];
} else {
node.data = data.value;
}
if (node.type && node.type.match(/^int$/)) {
node.data = parseInt(node.data, 10);
} else if (node.type && node.type.match(/^(saml(Service|Assertion)|blackWhiteList)$/) && !(typeof node.data === 'object')) {
node.data = node.data.split(';');
}
$scope.waiting = false;
return d.resolve(node.data);
}, function(response) {
readError(response);
return d.reject(response.status);
});
}
} else {
d.resolve(node.data);
}
return d.promise;
};
pathEvent = function(event, next, current) {
var n;
n = next.match(new RegExp('#!?/view/(latest|[0-9]+)'));
if (n === null) {
return $location.path('/view/latest');
} else {
console.log("Trying to get cfg number " + n[1]);
return $scope.getCfg(n[1]);
}
};
$scope.$on('$locationChangeSuccess', pathEvent);
$scope.getCfg = function(n) {
if ($scope.currentCfg.cfgNum !== n) {
return $http.get("" + window.confPrefix + n).then(function(response) {
var d;
$scope.currentCfg = response.data;
d = new Date($scope.currentCfg.cfgDate * 1000);
$scope.currentCfg.date = d.toLocaleString();
console.log("Metadatas of cfg " + n + " loaded");
$location.path("/view/" + n);
return $scope.init();
}, function(response) {
return readError(response).then(function() {
$scope.currentCfg.cfgNum = 0;
return $scope.init();
});
});
} else {
return $scope.waiting = false;
}
};
$scope.getLanguage = function(lang) {
$scope.lang = lang;
$scope.form = 'white';
$scope.init();
return $scope.showM = false;
};
$scope.init = function() {
var tmp;
tmp = null;
$scope.waiting = true;
$scope.data = [];
$scope.confirmNeeded = false;
$scope.forceSave = false;
$q.all([
$translator.init($scope.lang), $http.get(window.staticPrefix + "struct.json").then(function(response) {
tmp = response.data;
return console.log("Structure loaded");
})
]).then(function() {
console.log("Starting structure binding");
$scope.data = tmp;
tmp = null;
if ($scope.currentCfg.cfgNum !== 0) {
setScopeVars($scope);
} else {
$scope.message = {
title: 'emptyConf',
message: '__zeroConfExplanations__'
};
$scope.showModal('message.html');
}
$scope.form = 'home';
return $scope.waiting = false;
}, readError);
$scope.activeModule = "viewer";
return $scope.myStyle = {
color: '#ffb84d'
};
};
c = $location.path().match(new RegExp('^/view/(latest|[0-9]+)'));
if (!c) {
console.log("Redirecting to /view/latest");
return $location.path('/view/latest');
}
}
]);
}).call(this);

File diff suppressed because one or more lines are too long

View File

@ -22,6 +22,7 @@
<div class="navbar-collapse" ng-class="{'collapse':!showM}" id="formmenu">
<ul class="nav navbar-nav">
<li><a class="link" ng-click="home()"><i class="glyphicon glyphicon-home"></i></a></li>
<!--
<li>
<a id="save" class="link" ng-click="save()" tabIndex="-1">
<i class="glyphicon glyphicon-cloud-upload"></i>
@ -31,6 +32,7 @@
<li >
<input id="forcesave" type="checkbox" ng-model="forceSave" uib-tooltip="{{translate('forceSave')}}" tooltip-placement="right" ng-show="confirmNeeded||currentCfg.next" role="checkbox" aria-label="Force save">
</li>
-->
<li uib-dropdown>
<a id="navmenu" name="menu" uib-dropdown-toggle data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false"><i class="glyphicon glyphicon-cog"></i> {{translate('browse')}} <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelled-by="navmenu">
@ -40,7 +42,9 @@
</ul>
</li>
<li><a class="link hidden-xs" ng-click="setShowHelp()"><i class="glyphicon" ng-class="{'glyphicon-eye-close': showH,'glyphicon-eye-open': !showH}" ></i> {{ translate((showH ? 'hideHelp' : 'showHelp')) }}</a></li>
<!--
<li ng-repeat="button in menu()" 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">{{translate('menu')}} <span class="caret"></span></a>
<ul uib-dropdown-menu aria-labelled-by="langmenu" role="grid">
@ -190,11 +194,11 @@
<!-- //if:jsminified
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/conftree.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/filterFunctions.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/manager.min.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/viewer.min.js"></script>
//else -->
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/conftree.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/filterFunctions.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/manager.js"></script>
<script type="text/javascript" src="<TMPL_VAR NAME="STATIC_PREFIX">js/viewer.js"></script>
<!-- //endif -->
<TMPL_INCLUDE NAME="footer.tpl">