local h=require("datamodel")require("web.web")local e=ngx
local f,n,i=ipairs,pairs,type
local E=string.format
local o,r=string.match,string.untaint
local m=require("web.sessionmgr")local t={}local l={}local a={}local d={}local _=false
local c={}local function g(o,n)if o then
return
end
local o,r=n:cleanup()if o>0 then
local n,o=e.timer.at(r,g,n)if not n then
e.log(e.ERR,"failed to create timer: ",o)return
end
else
n.timerset=false
end
end
local function s(e)local n={}for e,l in f(e)do
local o,i,t=o(l.path,"uci%.web%.([^%.]+)%.@([^%.]+)%.([^%.]*)")if o then
local r=r(l.value)local e=n[o]if not e then
e={}n[o]=e
end
e=e[i]if not e then
e={}n[o][i]=e
end
if#t==0 then
e[l.param]=r
else
local n=e[t]if not n then
n={}e[t]=n
end
n[r]=r
end
end
end
return n
end
local function R(n)local n,o=h.get(n)if not n then
e.log(e.ERR,"failed to retrieve config: ",o)e.exit(e.HTTP_INTERNAL_SERVER_ERROR)end
return s(n)end
local function s(e,o)for n in n(e)do
e[n]=nil
end
for n,o in n(o)do
e[n]=o
end
end
local function w()for r,o in n(a)do
for e in n(o)do
if e~="rules"then
o[e]=nil
end
end
if i(o.rules)=="table"then
for r,t in n(o.rules)do
local r=d[t]if r then
if not o[r.target]then
o[r.target]={}end
if i(r.roles)~="table"then
e.log(e.ERR,"Option 'roles' for the rule "..t.." is invalid")e.exit(e.HTTP_INTERNAL_SERVER_ERROR)end
for n,e in n(r.roles)do
o[r.target][e]=true
end
end
end
end
end
end
local o={}local function f(e)return e==l[e.sectionname]end
o.is_real_user=f
local function u(e)return e._lock and(e._lock>0)end
function o.user_locked(e)if f(e)then
return u(e)end
end
function o.user_lock(e)if f(e)then
e._lock=(e._lock or 0)+1
end
end
function o.user_unlock(e)if f(e)then
if u(e)then
e._lock=e._lock-1
if(e._lock==0)and e._new_config then
s(e,e._new_config)end
end
end
end
local function f(n)local e
if n and n~=""then
e={}for n in n:gmatch("(%S+)")do
e[#e+1]=n
end
end
return e
end
local function p(e)e.interface=f(e.interface)return e
end
local function f(e,n)if not u(e)then
s(e,n)else
e._new_config=n
end
end
local function u(n,e)e.sectionname=n
l[n]=e
end
local function T(n,e)e=p(e)local o=l[n]if o then
f(o,e)else
u(n,e)end
end
local function f(e)if e.rule and i(e.rule)=="table"then
local o={}for e in n(d)do
o[e]=true
end
for e,n in n(e.rule)do
if d[e]then
s(d[e],n)o[e]=nil
else
d[e]=n
end
end
for e in n(o)do
d[e]=nil
end
end
if e.ruleset and i(e.ruleset)=="table"then
for n,e in n(a)do
s(e,{})end
for e,n in n(e.ruleset)do
if a[e]then
a[e].rules=n.rules
else
a[e]={rules=n.rules}end
end
end
w()if e.user and i(e.user)=="table"then
local o={}for e in n(l)do
o[e]=true
end
for e,n in n(e.user)do
T(e,n)o[e]=nil
l[e].sectionname=e
end
for e in n(o)do
l[e]=nil
end
end
if e.sessionmgr and i(e.sessionmgr)=="table"then
local r={}for e in n(t)do
r[e]=true
end
for e,n in n(e.sessionmgr)do
if t[e]then
t[e]:reloadConfig(n)r[e]=nil
else
t[e]=m.new(e,n,o)end
end
for e in n(r)do
t[e]=nil
end
end
end
local function d()if _ then
return
end
local e=R("uci.web.")f(e)_=true
end
local function i(o)local n=t[o]if not n then
d()n=t[o]if not n then
e.log(e.ERR,"no config found for sessionmgr ",o)e.exit(e.HTTP_INTERNAL_SERVER_ERROR)end
end
return n
end
function o.loadmgr(e)return i(e)end
function o.reloadUsers()f(R("uci.web.user."))for n,e in n(t)do
e:reloadUsers()end
end
function o.setManagerForPort(n,e)c[e]=n
end
function o.mgrport(o)for n,e in n(c)do
if e==o then
return n
end
end
end
function o.getmgr(n)local o=r(e.var.server_port)local n=n or c[o]if not n then
e.log(e.ERR,"no manager for this server")e.exit(e.HTTP_NOT_FOUND)end
if e.get_phase()~="access"then
e.log(e.ERR,"web.session.getmgr() called outside access phase")e.exit(e.HTTP_INTERNAL_SERVER_ERROR)end
local n=i(n)if not n.timerset then
local o,r=e.timer.at(n["timeout"],g,n)if not o then
e.log(e.ERR,"failed to create timer: ",r)return
end
n.timerset=true
end
return n
end
function o.getruleset(e)return a[e]end
function o.getuser(e)return l[e]end
function o.changePassword(e,n,o,t)local l={["uci.web.user.@"..e.sectionname..".srp_salt"]=n,["uci.web.user.@"..e.sectionname..".srp_verifier"]=o,}if t and h.getPN("rpc.user.@"..e.name..".pwcrypt",false)then
l["rpc.user.@"..e.name..".pwcrypt"]=t
end
local l,t=h.set(l)if not l then
return nil,t[1].errmsg
end
e.srp_salt=r(n)e.srp_verifier=r(o)return true
end
local d=e.redirect
e.redirect=function(n,a)local o
local t="^[^/]*://"if not n:match(t)then
local e=r(e.var.server_port)local e=c[e]if e then
o=i(e)end
end
if o then
local l=r(e.var.scheme)local o,t=o:getExternalAddress()o=o or r(e.var.server_addr)t=t or r(e.var.server_port)n=E('%s://%s:%s%s',l,o,t,n)end
return d(n,a or e.HTTP_MOVED_TEMPORARILY)end
return o