1310 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID. |
1325 local result = self._affiliations[bare]; -- Affiliations are granted, revoked, and maintained based on the user's bare JID. |
1311 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned |
1326 if not result and self._affiliations[host] == "outcast" then result = "outcast"; end -- host banned |
1312 return result; |
1327 return result; |
1313 end |
1328 end |
1314 |
1329 |
1315 local valid_affiliations = { |
|
1316 outcast = true; |
|
1317 none = true; |
|
1318 member = true; |
|
1319 admin = true; |
|
1320 owner = true; |
|
1321 }; |
|
1322 function room_mt:set_affiliation(actor, jid, affiliation, reason) |
1330 function room_mt:set_affiliation(actor, jid, affiliation, reason) |
1323 if not actor then return nil, "modify", "not-acceptable"; end; |
1331 if not actor then return nil, "modify", "not-acceptable"; end; |
1324 |
1332 |
1325 jid = jid_bare(jid); |
1333 jid = jid_bare(jid); |
1326 |
1334 |
1327 if valid_affiliations[affiliation or "none"] == nil then |
1335 if valid_affiliations[affiliation or "none"] == nil then |
1328 return nil, "modify", "not-acceptable"; |
1336 return nil, "modify", "not-acceptable"; |
1329 end |
1337 end |
1330 affiliation = affiliation ~= "none" and affiliation or nil; -- coerces `affiliation == false` to `nil` |
1338 affiliation = affiliation ~= "none" and affiliation or nil; -- coerces `affiliation == false` to `nil` |
1331 |
1339 |
|
1340 local target_affiliation = self._affiliations[jid]; -- Raw; don't want to check against host |
|
1341 local is_downgrade = valid_affiliations[target_affiliation or "none"] > valid_affiliations[affiliation or "none"]; |
|
1342 |
1332 if actor ~= true then |
1343 if actor ~= true then |
1333 local actor_affiliation = self:get_affiliation(actor); |
1344 local actor_bare = jid_bare(actor); |
1334 local target_affiliation = self:get_affiliation(jid); |
1345 local actor_affiliation = self._affiliations[actor_bare]; |
1335 if target_affiliation == affiliation then -- no change, shortcut |
1346 if actor_affiliation == "owner" then |
1336 return true; |
1347 if actor_bare == jid then -- self change |
1337 end |
1348 -- need at least one owner |
1338 if actor_affiliation ~= "owner" then |
1349 local is_last = true; |
1339 if affiliation == "owner" or affiliation == "admin" or actor_affiliation ~= "admin" or target_affiliation == "owner" or target_affiliation == "admin" then |
1350 for j, aff in pairs(self._affiliations) do if j ~= jid and aff == "owner" then is_last = false; break; end end |
1340 return nil, "cancel", "not-allowed"; |
1351 if is_last then |
1341 end |
1352 return nil, "cancel", "conflict"; |
1342 elseif target_affiliation == "owner" and jid_bare(actor) == jid then -- self change |
1353 end |
1343 local is_last = true; |
1354 end |
1344 for j, aff in pairs(self._affiliations) do if j ~= jid and aff == "owner" then is_last = false; break; end end |
1355 -- owners can do anything else |
1345 if is_last then |
1356 elseif affiliation == "owner" or affiliation == "admin" |
1346 return nil, "cancel", "conflict"; |
1357 or actor_affiliation ~= "admin" |
1347 end |
1358 or target_affiliation == "owner" or target_affiliation == "admin" then |
1348 end |
1359 -- Can't demote owners or other admins |
1349 end |
1360 return nil, "cancel", "not-allowed"; |
|
1361 end |
|
1362 end |
|
1363 |
|
1364 -- Set in 'database' |
1350 self._affiliations[jid] = affiliation; |
1365 self._affiliations[jid] = affiliation; |
|
1366 |
|
1367 -- Update roles |
1351 local role = self:get_default_role(affiliation); |
1368 local role = self:get_default_role(affiliation); |
1352 local occupants_updated = {}; |
1369 local role_rank = valid_roles[role or "none"]; |
|
1370 local occupants_updated = {}; -- Filled with old roles |
1353 for nick, occupant in self:each_occupant() do |
1371 for nick, occupant in self:each_occupant() do |
1354 if occupant.bare_jid == jid then |
1372 if occupant.bare_jid == jid then |
1355 occupant.role = role; |
1373 -- need to publcize in all cases; as affiliation in <item/> has changed. |
1356 self:save_occupant(occupant); |
1374 occupants_updated[occupant] = occupant.role; |
1357 occupants_updated[occupant] = true; |
1375 if occupant.role ~= role and ( |
1358 end |
1376 is_downgrade or |
1359 end |
1377 valid_roles[occupant.role or "none"] < role_rank -- upgrade |
|
1378 ) then |
|
1379 occupant.role = role; |
|
1380 self:save_occupant(occupant); |
|
1381 end |
|
1382 end |
|
1383 end |
|
1384 |
|
1385 -- Tell the room of the new occupant affiliations+roles |
1360 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}); |
1386 local x = st.stanza("x", {xmlns = "http://jabber.org/protocol/muc#user"}); |
1361 if not role then -- getting kicked |
1387 if not role then -- getting kicked |
1362 if affiliation == "outcast" then |
1388 if affiliation == "outcast" then |
1363 x:tag("status", {code="301"}):up(); -- banned |
1389 x:tag("status", {code="301"}):up(); -- banned |
1364 else |
1390 else |
1365 x:tag("status", {code="321"}):up(); -- affiliation change |
1391 x:tag("status", {code="321"}):up(); -- affiliation change |
1366 end |
1392 end |
1367 end |
1393 end |
1368 for occupant in pairs(occupants_updated) do |
1394 local is_semi_anonymous = self:get_whois() == "moderators"; |
|
1395 for occupant, old_role in pairs(occupants_updated) do |
1369 self:publicise_occupant_status(occupant, x, actor, reason); |
1396 self:publicise_occupant_status(occupant, x, actor, reason); |
1370 end |
1397 if is_semi_anonymous and |
|
1398 (old_role == "moderator" and occupant.role ~= "moderator") or |
|
1399 (old_role ~= "moderator" and occupant.role == "moderator") then -- Has gained or lost moderator status |
|
1400 -- Send everyone else's presences (as jid visibility has changed) |
|
1401 for real_jid in occupant:each_session() do |
|
1402 self:send_occupant_list(real_jid, function(occupant_jid, occupant) |
|
1403 return occupant.bare_jid ~= jid; |
|
1404 end); |
|
1405 end |
|
1406 end |
|
1407 end |
|
1408 |
1371 if self.save then self:save(); end |
1409 if self.save then self:save(); end |
1372 return true; |
1410 return true; |
1373 end |
1411 end |
1374 |
1412 |
1375 function room_mt:get_role(nick) |
1413 function room_mt:get_role(nick) |
1376 local occupant = self:get_occupant_by_nick(nick); |
1414 local occupant = self:get_occupant_by_nick(nick); |
1377 return occupant and occupant.role or nil; |
1415 return occupant and occupant.role or nil; |
1378 end |
1416 end |
1379 |
1417 |
1380 local valid_roles = { |
|
1381 none = true; |
|
1382 visitor = true; |
|
1383 participant = true; |
|
1384 moderator = true; |
|
1385 } |
|
1386 function room_mt:set_role(actor, occupant_jid, role, reason) |
1418 function room_mt:set_role(actor, occupant_jid, role, reason) |
1387 if not actor then return nil, "modify", "not-acceptable"; end |
1419 if not actor then return nil, "modify", "not-acceptable"; end |
1388 |
1420 |
1389 local occupant = self:get_occupant_by_nick(occupant_jid); |
1421 local occupant = self:get_occupant_by_nick(occupant_jid); |
1390 if not occupant then return nil, "modify", "not-acceptable"; end |
1422 if not occupant then return nil, "modify", "not-acceptable"; end |