123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- -- Licensed to the public under the Apache License 2.0.
- local rad2 = luci.controller.radicale2
- local fs = require("nixio.fs")
- local util = require("luci.util")
- local m = Map("radicale2", translate("Radicale 2.x"),
- translate("A lightweight CalDAV/CardDAV server"))
- local s = m:section(NamedSection, "auth", "section", translate("Authentication"))
- s.addremove = true
- s.anonymous = false
- local at = s:option(ListValue, "type", translate("Authentication Type"))
- at:value("", translate("Default (htpasswd file from users below)"))
- at:value("htpasswd", translate("htpasswd file (manually populated)"))
- at:value("none", translate("No authentication"))
- at:value("remote_user", translate("REMOTE_USER from web server"))
- at:value("http_x_remote_user", translate("X-Remote-User from web server"))
- at.default = ""
- at.rmempty = true
- local o = s:option(Value, "htpasswd_filename", translate("Filename"), translate("htpasswd-formatted file filename"))
- o:depends("type", "htpasswd")
- o.rmempty = true
- o.placeholder = "/etc/radicale2/users"
- o.default = ""
- local hte = s:option(ListValue, "htpasswd_encryption", translate("Encryption"), translate("Password encryption method"))
- hte:depends("type", "htpasswd")
- hte:depends("type", "")
- hte:value("plain", translate("Plaintext"))
- hte:value("sha1", translate("SHA1"))
- hte:value("ssha", translate("SSHA"))
- hte:value("crypt", translate("crypt"))
- if rad2.pymodexists("passlib") then
- hte:value("md5", translate("md5"))
- if rad2.pymodexists("bcrypt") then
- hte:value("bcrypt", translate("bcrypt"))
- end
- end
- hte.default = "plain"
- hte.rmempty = true
- if not rad2.pymodexists("bcrypt") then
- o = s:option(DummyValue, "nobcrypt", translate("Insecure hashes"), translate("Install python3-passlib and python3-bcrypt to enable a secure hash"))
- else
- o = s:option(DummyValue, "nobcrypt", translate("Insecure hashes"), translate("Select bcrypt above to enable a secure hash"))
- o:depends("htpasswd_encrypt","")
- o:depends("htpasswd_encrypt","plain")
- o:depends("htpasswd_encrypt","sha1")
- o:depends("htpasswd_encrypt","ssha")
- o:depends("htpasswd_encrypt","crypt")
- o:depends("htpasswd_encrypt","md5")
- end
- o = s:option(Value, "delay", translate("Retry Delay"), translate("Required time between a failed authentication attempt and trying again"))
- o.rmempty = true
- o.default = 1
- o.datatype = "uinteger"
- o:depends("type", "")
- o:depends("type", "htpasswd")
- o:depends("type", "remote_user")
- o:depends("type", "http_x_remote_user")
- s = m:section(TypedSection, "user", translate("User"), translate("Users and Passwords"))
- s.addremove = true
- s.anonymous = true
- o = s:option(Value, "name", translate("Username"))
- o.rmempty = true
- o.placeholder = "johndoe"
- if rad2.pymodexists("passlib") then
- local plainpass = s:option(Value, "plain_pass", translate("Plaintext Password"))
- plainpass.placeholder = "Example password"
- plainpass.password = true
- local ppconfirm = s:option(Value, "plain_pass_confirm", translate("Confirm Plaintext Password"))
- ppconfirm.placeholder = "Example password"
- ppconfirm.password = true
- plainpass.cfgvalue = function(self, section)
- return self:formvalue(section)
- end
- plainpass.write = function(self, section)
- return true
- end
- ppconfirm.cfgvalue = plainpass.cfgvalue
- ppconfirm.write = plainpass.write
- plainpass.validate = function(self, value, section)
- if self:cfgvalue(section) ~= ppconfirm:cfgvalue(section) then
- return nil, translate("Password and confirmation do not match")
- end
- return AbstractValue.validate(self, value, section)
- end
- ppconfirm.validate = function(self, value, section)
- if self:cfgvalue(section) ~= plainpass:cfgvalue(section) then
- return nil, translate("Password and confirmation do not match")
- end
- return AbstractValue.validate(self, value, section)
- end
- local pass = s:option(Value, "password", translate("Encrypted Password"), translate("If 'Plaintext Password' filled and matches 'Confirm Plaintext Password' then this field becomes of hash of that password, otherwise this field remains the existing hash (you can also put your own hash value for the type of hash listed above)."))
- pass.password = true
- pass.rmempty = false
- function encpass(self, section)
- local plainvalue = plainpass:cfgvalue(section)
- local pvc = ppconfirm:cfgvalue(section)
- local encvalue, err
- if not plainvalue or not pvc or plainvalue == "" or pvc == "" or plainvalue ~= pvc then
- return nil
- end
- local enctype = hte:formvalue("auth")
- if not enctype then
- enctype = hte:cfgvalue("auth")
- end
- if not enctype or enctype == "" or enctype == "plain" then
- return plainvalue
- end
- encvalue, err = util.ubus("rad2-enc", "encrypt", { type = enctype, plainpass = plainvalue })
- if not encvalue then
- return nil
- end
- return encvalue and encvalue.encrypted_password
- end
- pass.cfgvalue = function(self, section)
- if not plainpass:formvalue(section) then
- return Value.cfgvalue(self, section)
- else
- return Value.formvalue(self, section)
- end
- end
- pass.formvalue = function(self, section)
- if not plainpass:formvalue(section) then
- return Value.formvalue(self, section)
- else
- return encpass(self, section) or Value.formvalue(self, section)
- end
- end
- else
- local pass = s:option(Value, "password", translate("Encrypted Password"), translate("Generate this field using an generator for Apache htpasswd-style authentication files (for the hash format you have chosen above), or install python3-passlib to enable the ability to create the hash by entering the plaintext in a field that will appear on this page if python3-passlib is installed."))
- pass.password = true
- pass.rmempty = false
- end -- python3-passlib installed
- -- TODO: Allow configuration of rights file from this page
- local s = m:section(NamedSection, "section", "rights", translate("Rights"), translate("User-based ACL Settings"))
- s.addremove = true
- s.anonymous = false
- o = s:option(ListValue, "type", translate("Rights Type"))
- o:value("", translate("Default (owner only)"))
- o:value("owner_only", translate("RO: None, RW: Owner"))
- o:value("authenticated", translate("RO: None, RW: Authenticated Users"))
- o:value("owner_write", translate("RO: Authenticated Users, RW: Owner"))
- o:value("from_file", translate("Based on settings in 'Rights File'"))
- o:value("none", translate("RO: All, RW: All"))
- o.default = ""
- o.rmempty = true
- rights_file = s:option(FileUpload, "file", translate("Rights File"))
- rights_file.rmempty = true
- rights_file:depends("type", "from_file")
- o = s:option(Button, "remove_conf",
- translate("Remove configuration for rights file"),
- translate("This permanently deletes the rights file and configuration to use same."))
- o.inputstyle = "remove"
- o:depends("type", "from_file")
- function o.write(self, section)
- if cert_file:cfgvalue(section) and fs.access(o:cfgvalue(section)) then fs.unlink(rights_file:cfgvalue(section)) end
- self.map:del(section, "file")
- self.map:del(section, "rights_file")
- luci.http.redirect(luci.dispatcher.build_url("admin", "services", "radicale2", "auth"))
- end
- -- TODO: Allow configuration rights file from this page
- return m
|