Add support for members and permissions

Fixes #22
master
rubenwardy 2018-11-25 23:19:27 +00:00
parent 8411dfd3ff
commit f300d95b37
9 changed files with 236 additions and 22 deletions

View File

@ -76,7 +76,7 @@ describe("banking", function()
local comp = company.Company:new()
comp:set_title_calc_name("Two")
comp.owner = "testuser"
comp.ceo = "testuser"
company.add(comp)
assert.is_false(banking.transfer("a", "c:two", "c:test", 10, nil))

View File

@ -127,6 +127,50 @@ function company.get_companies_for_player(pname)
return comps
end
function company.set_perms(comp, actor, target, permission, is_grant)
if not comp:check_perm(actor, "MANAGE_MEMBERS",
{ action = "add", name = "username" }) then
return false, "Missing permission: MANAGE_MEMBERS"
end
if target == comp:get_ceo_name() then
if is_grant then
return false, "The CEO already has all permissions"
else
return false, "Permissions cannot be revoked from the CEO"
end
end
permission = permission:upper()
if permission ~= "ALL" and not company.permissions[permission] then
return false, "Unknown permission " .. permission
end
local member = comp.members[target]
if not member then
return false, target .. " is not a member of " .. comp.title
end
if permission == "ALL" then
for key in pairs(company.permissions) do
member.perms[key] = is_grant
end
else
member.perms[permission] = is_grant
end
company.dirty = true
local perms = {}
for key, value in pairs(member.perms) do
if value then
perms[#perms + 1] = key
end
end
return true, "Permissions: " .. table.concat(perms, ", ")
end
company.registered_on_creates = {}
function company.register_on_create(func)
assert(type(func) == "function")

View File

@ -2,6 +2,7 @@ local adt = audit("company.cmd")
ChatCmdBuilder.types.comp = "(c:[a-z]+)"
ChatCmdBuilder.types.owner = "(c?:?[a-z]+)"
ChatCmdBuilder.types.alpha = "([A-Za-z_]+)"
ChatCmdBuilder.new("company", function(cmd)
cmd:sub("list", function(name)
@ -17,7 +18,7 @@ ChatCmdBuilder.new("company", function(cmd)
cmd:sub("register :title:text", function(name, title)
local comp = company.Company:new()
comp:set_title_calc_name(title)
comp.owner = name
comp.ceo = name
if #title < 3 then
return false, "Company names must be at least 3 characters"
@ -59,6 +60,87 @@ ChatCmdBuilder.new("company", function(cmd)
return false, "No company by the name '" .. cname .. "' found"
end
end)
cmd:sub("member :username:username", function(name, username)
local comp = company.get_active(name)
if not comp then
return false, "Select a company by doing /company use <NAME>"
end
if comp:get_ceo_name() == username then
return false, username .. " is the CEO of " .. comp.title
end
local member = comp.members[username]
if not member then
return false, username .. " is not a member of " .. comp.title
end
local perms = {}
for key, value in pairs(member.perms) do
if value then
perms[#perms + 1] = key
end
end
return true, username .. " is a member of " .. comp.title ..
"\nPermissions: " .. table.concat(perms, ", ")
end)
cmd:sub("add :username:username", function(name, username)
local comp = company.get_active(name)
if not comp then
return false, "Select a company by doing /company use <NAME>"
end
if not comp:check_perm(name, "MANAGE_MEMBERS",
{ action = "add", name = "username" }) then
return false, "Missing permission: MANAGE_MEMBERS"
end
if comp:get_ceo_name() == username then
return false, username .. " is the CEO of " .. comp.title
end
if comp.members[username] then
return false, username .. " is already a member of " .. comp.title
end
if not minetest.player_exists(username) then
return false, username .. " doesn't exist"
end
local member = comp:add_member(username)
company.dirty = true
local perms = {}
for key, value in pairs(member.perms) do
if value then
perms[#perms + 1] = key
end
end
return true, "Added " .. username .. " to " .. comp.title ..
"\nPermissions: " .. table.concat(perms, ", ")
end)
cmd:sub("grant :username:username :permission:alpha", function(name, username, permission)
local comp = company.get_active(name)
if not comp then
return false, "Select a company by doing /company use <NAME>"
end
return company.set_perms(comp, name, username, permission:upper(), true)
end)
cmd:sub("revoke :username:username :permission:alpha", function(name, username, permission)
local comp = company.get_active(name)
if not comp then
return false, "Select a company by doing /company use <NAME>"
end
return company.set_perms(comp, name, username, permission:upper(), false)
end)
end, {
description = "Company tools"
})

View File

@ -5,7 +5,8 @@ function Company:new(obj)
obj = obj or {}
setmetatable(obj, self)
self.__index = self
self.owner = nil
self.ceo = nil
self.members = {}
return obj
end
@ -14,7 +15,8 @@ function Company:to_table()
return {
title = self.title,
name = self.name,
owner = self.owner
ceo = self.ceo,
members = self.members,
}
end
@ -24,8 +26,9 @@ function Company:from_table(t)
if self.name:sub(1, 2) ~= "c:" then
self.name = "c:" .. self.name
end
self.owner = t.owner
return self.name ~= nil and self.owner ~= nil
self.ceo = t.ceo or t.owner
self.members = t.members or {}
return self.name ~= nil and self.ceo ~= nil and type(self.members) == "table"
end
function Company:set_title_calc_name(title)
@ -36,12 +39,12 @@ function Company:set_title_calc_name(title)
end
function Company:get_ceo_name()
return self.owner
return self.ceo
end
function Company:get_ownership(username)
-- TODO: ownership
if self.owner == username then
if self.ceo == username then
return 1
else
return 0
@ -58,8 +61,26 @@ function Company:check_perm(username, permission, meta)
assert(company.permissions[permission])
assert(meta == nil or type(meta) == "table")
-- TODO: permissions
return self:get_ownership(username) > 0
if self.ceo == username then
return true
end
local member = self.members[username]
return member and member.perms[permission] and true or false
end
function Company:add_member(username)
assert(not self.members[username])
local mem = {
perms = {
SWITCH_TO = true,
INTERACT_AREA = true,
},
}
self.members[username] = mem
return mem
end
function Company:is_government()

View File

@ -21,7 +21,7 @@ company.show_company_select_dialog = lib_quickfs.register("company:set_company",
if comp:get_ceo_name() == pname then
return minetest.formspec_escape(comp.title)
else
return minetest.formspec_escape(minetest.colorize("#c0c0c0", comp.name))
return minetest.formspec_escape(minetest.colorize("#c0c0c0", comp.title))
end
end), ","),
";1;false]",
@ -151,10 +151,15 @@ company.register_panel({
})
company.register_panel({
title = "Employees",
title = "Members",
bgcolor = "#396",
get = function(_, _, _, _)
return "label[0.2,0.2;0 employees.]"
get = function(_, _, comp, _)
local memcount = 0
for username, props in pairs(comp.members) do
memcount = memcount + 1
end
return "label[0.2,0.2;" .. memcount .. " members]"
end,
})

View File

@ -10,4 +10,5 @@ company.permissions = {
SHOP_ADMIN = "Can change the settings of a shop, including prices",
SHOP_CHEST = "Can place, modify shop chests",
BUY_ITEMS = "Can buy from shops",
MANAGE_MEMBERS = "Can manage company members",
}

View File

@ -15,7 +15,7 @@ describe("company", function()
it("add", function()
local comp = company.Company:new()
comp:set_title_calc_name("Test Company")
comp.owner = "testuser"
comp.ceo = "testuser"
assert.equals (#company._companies, 0)
assert.is_true(company.add(comp))
assert.equals (#company._companies, 1)
@ -26,7 +26,7 @@ describe("company", function()
local comp = company.get_by_name("c:test_company")
assert.is_not_nil(comp)
assert.equals("c:test_company", comp.name)
assert.equals("testuser", comp.owner)
assert.equals("testuser", comp.ceo)
end)
it("active_company", function()
@ -37,7 +37,7 @@ describe("company", function()
local comp = company.get_active("testuser")
assert.is_not_nil(comp)
assert.equals("c:test_company", comp.name)
assert.equals("testuser", comp.owner)
assert.equals("testuser", comp.ceo)
end)
it("get_companies_for_player", function()

View File

@ -10,12 +10,12 @@ local Company = company.Company
describe("company.Company", function()
it("constructs", function()
local company = Company:new()
assert.is_nil(company.owner)
assert.is_nil(company.ceo)
end)
it("has ownership", function()
local company = Company:new()
company.owner = "foobar"
company.ceo = "foobar"
assert.equals(company:get_ownership("foobar"), 1)
assert.equals(company:get_ownership("foobarasas"), 0)
assert.equals(company:get_ownership("a"), 0)
@ -26,21 +26,21 @@ describe("company.Company", function()
it("has ceo", function()
local company = Company:new()
company.owner = "foobar"
company.ceo = "foobar"
assert.equals(company:get_ceo_name(), "foobar")
end)
it("can become active", function()
local company = Company:new()
assert.is_false(company:can_become_active("foobar"))
company.owner = "foobar"
company.ceo = "foobar"
assert.is_true (company:can_become_active("foobar"))
assert.is_false(company:can_become_active("sdsddd"))
end)
it("has permissions", function()
local company = Company:new()
company.owner = "foobar"
company.ceo = "foobar"
assert.is_true (company:check_perm("foobar", "SWITCH_TO"))
assert.is_false(company:check_perm("sdsddd", "SWITCH_TO"))
end)

View File

@ -218,6 +218,67 @@ land.show_buy_to = lib_quickfs.register("land:buy", {
})
sfinv.register_page("land:places", {
title = "Places",
get = function(self, player, context)
local pname = player:get_player_name()
local comp = company.get_active(pname)
-- Using an array to build a formspec is considerably faster
local formspec = {
company.get_company_header(pname, 8)
}
if comp then
local i = 0
for _, panel in pairs(company.registered_panels) do
if not panel.show_to or panel:show_to(player, comp, context) then
formspec[#formspec + 1] = "container["
formspec[#formspec + 1] = tostring((i % 2) * 4)
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = tostring(math.floor(i / 2) * 2 + 1)
formspec[#formspec + 1] = ".3]"
formspec[#formspec + 1] = "label[1.5,-0.3;"
formspec[#formspec + 1] = panel.title
formspec[#formspec + 1] = "]"
formspec[#formspec + 1] = "box[0,-0.3;3.8,1.8;"
formspec[#formspec + 1] = panel.bgcolor
formspec[#formspec + 1] = "]"
formspec[#formspec + 1] = panel:get(player, comp, context)
formspec[#formspec + 1] = "container_end[]"
i = i + 1
end
end
while i < 2*4 do
formspec[#formspec + 1] = "box["
formspec[#formspec + 1] = tostring((i % 2) * 4)
formspec[#formspec + 1] = ","
formspec[#formspec + 1] = tostring(math.floor(i / 2) * 2 + 1)
formspec[#formspec + 1] = ";3.8,1.8;#111]"
i = i + 1
end
end
-- Wrap the formspec in sfinv's layout (ie: adds the tabs and background)
return sfinv.make_formspec(player, context,
table.concat(formspec, ""), false)
end,
on_player_receive_fields = function(self, player, context, fields)
if fields.switch then
company.show_company_select_dialog(player:get_player_name(), function(player2)
sfinv.set_page_and_show(player2, "company:company")
end)
end
end,
})
company.register_panel({
title = "Land",
bgcolor = "#A0522D",