Search code examples
authenticationluaopenwrt

OpenWrt: LuCI: how to implement limited user access


Goal: two users root and user. Root can access everything via web-interface, but user should see only some parts of the menus.

One option would be to pass "sysauth" option to every module in question. That is not very practical, because the user would see every menu entry and would get login page for every menu he is not allowed to.

My idea is to figure out who is logged on and then do nothing in the index() function of each restricted module. So far I couldn't find such a function in LuCI API (http://luci.subsignal.org/api/luci/), that would return a current logged user.

I know how to add additional users in OpenWrt/LuCI (https://forum.openwrt.org/viewtopic.php?pid=163013#p163013). But it is only a part of the solution.

Any idea, how to achieve my goal?


Solution

  • I ended up creating a Lua function like described here: http://lua-users.org/wiki/SaveTableToFile, to find and remove unneeded keys from the table.

    function remove_idx(  tbl, index )
    
       -- initiate variables for save procedure
       local tables,lookup = { tbl },{ [tbl] = 1 }
    
       for idx,t in ipairs( tables ) do
          local thandled = {}
    
          for i,v in ipairs( t ) do
         thandled[i] = true
         local stype = type( v )
         -- only handle value
         if stype == "table" then
            if not lookup[v] then
               table.insert( tables, v )
               lookup[v] = #tables
            end
         else
            if i == index then
               t[i] = nil
               return
            end
         end
          end
    
          for i,v in pairs( t ) do
         -- escape handled values
         if (not thandled[i]) then
    
            local flag = 0
            local stype = type( i )
            -- handle index
            if stype == "table" then
               if not lookup[i] then
              table.insert( tables,i )
              lookup[i] = #tables
               end
            else
               flag = 1
               if i == index then
              t[i] = nil
              return
               end
            end
    
            if flag == 1 then
               stype = type( v )
               -- handle value
               if stype == "table" then
              if not lookup[v] then
                 table.insert( tables,v )
                 lookup[v] = #tables
              end
               else
              if i == index then
                 t[i] = nil
                 return
              end
               end
            end
    
         end
          end
       end
    end 
    

    And then inserted my user check and page delete after in libs/web/luasrc/dispatcher.lua dispatch():

    if c and c.index then
        local tpl = require "luci.template"
    
        if util.copcall(tpl.render, "indexer", {}) then
            return true
        end
     end
    

    That's how I remove unneeded pages depending on who is logged in:

        if ctx.authuser == "user" then
                remove_idx(ctx.tree, "packages")
                remove_idx(ctx.tree, "leds")
        end
    

    It is a little bit quick and dirty, but it works. Please note, that direct access by manipulating the URL is still possible.

    Update

    LuCI2 will provide ACL support und multi-user environment: http://git.openwrt.org/?p=project/luci2/ui.git;a%3Dsummary