plugins/muc/muc.lib.lua
changeset 6187 c0b4b5d41e55
parent 6186 85f7cd91dc31
child 6188 f47268c8a8d0
equal deleted inserted replaced
6186:85f7cd91dc31 6187:c0b4b5d41e55
    57 end
    57 end
    58 
    58 
    59 function room_mt:get_occupant_jid(real_jid)
    59 function room_mt:get_occupant_jid(real_jid)
    60 	return self._jid_nick[real_jid]
    60 	return self._jid_nick[real_jid]
    61 end
    61 end
       
    62 
       
    63 local valid_affiliations = {
       
    64 	outcast = 0;
       
    65 	none = 1;
       
    66 	member = 2;
       
    67 	admin = 3;
       
    68 	owner = 4;
       
    69 };
       
    70 
       
    71 local valid_roles = {
       
    72 	none = 0;
       
    73 	visitor = 1;
       
    74 	participant = 2;
       
    75 	moderator = 3;
       
    76 };
    62 
    77 
    63 function room_mt:get_default_role(affiliation)
    78 function room_mt:get_default_role(affiliation)
    64 	if affiliation == "owner" or affiliation == "admin" then
    79 	if affiliation == "owner" or affiliation == "admin" then
    65 		return "moderator";
    80 		return "moderator";
    66 	elseif affiliation == "member" then
    81 	elseif affiliation == "member" then
  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