spec/scansion/muc_show_offline.scs
author Matthew Wild <mwild1@gmail.com>
Wed, 27 Mar 2024 15:35:15 +0000
branch0.12
changeset 13469 54a936345aaa
parent 12033 631b2afa7bc1
permissions -rw-r--r--
prosodyctl check: Warn about invalid domain names in the config file This ensures that domain names of virtual hosts and components are valid in XMPP, and that they are encoded correctly.

# MUC: Room registration and presence broadcast of unavailable members

[Client] Romeo
	jid: user@localhost
	password: password

[Client] Juliet
	jid: user2@localhost
	password: password

[Client] Rosaline
	jid: user3@localhost
	password: password

-----

Romeo connects

Romeo sends:
	<presence to="room@conference.localhost/Romeo">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Romeo receives:
	<presence from='room@conference.localhost/Romeo'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<status code='201'/>
			<item jid="${Romeo's full JID}" affiliation='owner' role='moderator'/>
			<status code='110'/>
		</x>
	</presence>

Romeo receives:
	<message type='groupchat' from='room@conference.localhost'><subject/></message>

# Submit config form
Romeo sends:
	<iq id='config1' to='room@conference.localhost' type='set'>
		<query xmlns='http://jabber.org/protocol/muc#owner'>
			<x xmlns='jabber:x:data' type='submit'>
				<field var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#roomconfig</value>
				</field>
				<field var='muc#roomconfig_presencebroadcast'>
					<value>none</value>
					<value>participant</value>
					<value>moderator</value>
				</field>
			</x>
		</query>
	</iq>

Romeo receives:
	<iq id="config1" from="room@conference.localhost" type="result">
	</iq>

Romeo sends:
	<iq id='member1' to='room@conference.localhost' type='set'>
		<query xmlns='http://jabber.org/protocol/muc#admin'>
			<item affiliation='member' jid="${Juliet's JID}" />
		</query>
	</iq>

Romeo receives:
	<message from='room@conference.localhost'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item jid="${Juliet's JID}" affiliation='member' />
		</x>
	</message>

Romeo receives:
	<iq from='room@conference.localhost' id='member1' type='result'/>

# Juliet connects, and joins the room
Juliet connects

Juliet sends:
	<presence to="room@conference.localhost/Juliet">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Juliet receives:
	<presence from="room@conference.localhost/Romeo" />

Juliet receives:
	<presence from="room@conference.localhost/Juliet" />

Juliet receives:
	<message type='groupchat' from='room@conference.localhost'><subject/></message>

Romeo receives:
	<presence from="room@conference.localhost/Juliet" />

# Juliet retrieves the registration form

Juliet sends:
	<iq id='jw81b36f' to='room@conference.localhost' type='get'>
		<query xmlns='jabber:iq:register'/>
	</iq>

Juliet receives:
	<iq type='result' from='room@conference.localhost' id='jw81b36f'>
		<query xmlns='jabber:iq:register'>
			<x type='form' xmlns='jabber:x:data'>
				<field type='hidden' var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#register</value>
				</field>
				<field type='text-single' label='Nickname' var='muc#register_roomnick'>
					<required/>
				</field>
			</x>
		</query>
	</iq>

Juliet sends:
	<iq id='nv71va54' to='room@conference.localhost' type='set'>
		<query xmlns='jabber:iq:register'>
			<x xmlns='jabber:x:data' type='submit'>
				<field var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#register</value>
				</field>
				<field var='muc#register_roomnick'>
					<value>Juliet</value>
				</field>
			</x>
		</query>
	</iq>

Juliet receives:
	<presence from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='member' jid="${Juliet's full JID}" role='participant'/>
			<status code='110'/>
		</x>
	</presence>

Juliet receives:
	<iq type='result' from='room@conference.localhost' id='nv71va54'/>

# Juliet discovers her reserved nick

Juliet sends:
	<iq id='getnick1' to='room@conference.localhost' type='get'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/>
	</iq>

Juliet receives:
	<iq type='result' from='room@conference.localhost' id='getnick1'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'>
			<identity category='conference' name='Juliet' type='text'/>
		</query>
	</iq>

# Juliet leaves the room:

Juliet sends:
	<presence type="unavailable" to="room@conference.localhost/Juliet" />

Juliet receives:
	<presence type='unavailable' from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item jid="${Juliet's full JID}" affiliation='member' role='none'/>
			<status code='110'/>
		</x>
	</presence>

Romeo receives:
	<presence from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item jid="${Juliet's full JID}" affiliation='member' role='participant'/>
		</x>
	</presence>

# Rosaline connect and tries to join the room as Juliet

Rosaline connects

Rosaline sends:
	<presence to="room@conference.localhost/Juliet">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Rosaline receives:
	<presence type='error' from='room@conference.localhost/Juliet'>
		<error type='cancel' by='room@conference.localhost'>
			<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
		</error>
	</presence>

# In a heated moment, Juliet unregisters from the room

Juliet sends:
	<iq type='set' to='room@conference.localhost' id='unreg1'>
		<query xmlns='jabber:iq:register'>
			<remove/>
		</query>
	</iq>

Juliet receives:
	<iq type='result' from='room@conference.localhost' id='unreg1'/>

# Romeo is notified of Juliet's sad decision

Romeo receives:
	<message from='room@conference.localhost'>
		<x xmlns='http://jabber.org/protocol/muc#user' scansion:strict='true'>
			<item jid="${Juliet's JID}" affiliation='none' />
		</x>
	</message>

# Rosaline attempts once more to sneak into the room, disguised as Juliet

Rosaline sends:
	<presence to="room@conference.localhost/Juliet">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Rosaline receives:
	<presence from='room@conference.localhost/Romeo'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='owner' role='moderator'/>
		</x>
	</presence>

Rosaline receives:
	<presence from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='none' jid="${Rosaline's full JID}" role='participant'/>
			<status code='110'/>
		</x>
	</presence>

Romeo receives:
	<presence from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='none' jid="${Rosaline's full JID}" role='participant'/>
		</x>
	</presence>

# On discovering the ruse, Romeo restores Juliet's nick and status within the room

Romeo sends:
	<iq id='member1' to='room@conference.localhost' type='set'>
		<query xmlns='http://jabber.org/protocol/muc#admin'>
			<item affiliation='member' jid="${Juliet's JID}" nick='Juliet' />
		</query>
	</iq>

# Rosaline is evicted from the room

Romeo receives:
	<presence from='room@conference.localhost/Juliet' type='unavailable'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<status code='307'/>
			<item affiliation='none' role='none' jid="${Rosaline's full JID}">
				<reason>This nickname is reserved</reason>
			</item>
		</x>
	</presence>

# An out-of-room affiliation change is received for Juliet

Romeo receives:
	<message from='room@conference.localhost'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item jid="${Juliet's JID}" affiliation='member' />
		</x>
	</message>

Romeo receives:
	<iq type='result' id='member1' from='room@conference.localhost' />

Rosaline receives:
	<presence type='unavailable' from='room@conference.localhost/Juliet'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<status code='307'/>
			<item affiliation='none' jid="${Rosaline's full JID}" role='none'>
				<reason>This nickname is reserved</reason>
			</item>
			<status code='110'/>
		</x>
	</presence>

# Rosaline, frustrated, attempts to get back into the room...

Rosaline sends:
	<presence to="room@conference.localhost/Juliet">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

# ...but once again, is denied

Rosaline receives:
	<presence type='error' from='room@conference.localhost/Juliet'>
		<error type='cancel' by='room@conference.localhost'>
			<conflict xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
		</error>
	</presence>

# Juliet, however, quietly joins the room with success

Juliet sends:
	<presence to="room@conference.localhost/Juliet">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Juliet receives:
	<presence from="room@conference.localhost/Romeo" />

Juliet receives:
	<presence from="room@conference.localhost/Juliet" />

Juliet receives:
	<message type='groupchat' from='room@conference.localhost'><subject/></message>

Romeo receives:
	<presence from="room@conference.localhost/Juliet" />

# Romeo checks whether he has reserved his own nick yet

Romeo sends:
	<iq id='getnick1' to='room@conference.localhost' type='get'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/>
	</iq>

# But no nick is returned, as he hasn't registered yet!

Romeo receives:
	<iq type='result' from='room@conference.localhost' id='getnick1'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item' scansion:strict='true' />
	</iq>

# Romeo updates his own registration

Romeo sends:
	<iq id='jw81b36f' to='room@conference.localhost' type='get'>
		<query xmlns='jabber:iq:register'/>
	</iq>

Romeo receives:
	<iq type='result' from='room@conference.localhost' id='jw81b36f'>
		<query xmlns='jabber:iq:register'>
			<x type='form' xmlns='jabber:x:data'>
				<field type='hidden' var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#register</value>
				</field>
				<field type='text-single' label='Nickname' var='muc#register_roomnick'>
					<required/>
				</field>
			</x>
		</query>
	</iq>

Romeo sends:
	<iq id='nv71va54' to='room@conference.localhost' type='set'>
		<query xmlns='jabber:iq:register'>
			<x xmlns='jabber:x:data' type='submit'>
				<field var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#register</value>
				</field>
				<field var='muc#register_roomnick'>
					<value>Romeo</value>
				</field>
			</x>
		</query>
	</iq>

Romeo receives:
	<presence from='room@conference.localhost/Romeo'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='owner' jid="${Romeo's full JID}" role='moderator'/>
			<status code='110'/>
		</x>
	</presence>

Romeo receives:
	<iq type='result' from='room@conference.localhost' id='nv71va54'/>

Juliet receives:
	<presence from='room@conference.localhost/Romeo'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item role='moderator' xmlns='http://jabber.org/protocol/muc#user' affiliation='owner'/>
		</x>
	</presence>

# Romeo discovers his reserved nick

Romeo sends:
	<iq id='getnick1' to='room@conference.localhost' type='get'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'/>
	</iq>

Romeo receives:
	<iq type='result' from='room@conference.localhost' id='getnick1'>
		<query xmlns='http://jabber.org/protocol/disco#info' node='x-roomuser-item'>
			<identity category='conference' name='Romeo' type='text'/>
		</query>
	</iq>

# To check the status of the room is as expected, Romeo requests the member list

Romeo sends:
	<iq id='member3' to='room@conference.localhost' type='get'>
		<query xmlns='http://jabber.org/protocol/muc#admin'>
			<item affiliation='member'/>
		</query>
	</iq>

Romeo receives:
	<iq from='room@conference.localhost' type='result' id='member3'>
		<query xmlns='http://jabber.org/protocol/muc#admin'>
			<item jid="${Juliet's JID}" affiliation='member' nick='Juliet'/>
		</query>
	</iq>

Juliet sends:
	<presence type="unavailable" to="room@conference.localhost/Juliet" />

Juliet receives:
	<presence from='room@conference.localhost/Juliet' type='unavailable' />

Romeo receives:
	<presence type='unavailable' from='room@conference.localhost/Juliet' />

# Rosaline joins as herself

Rosaline sends:
	<presence to="room@conference.localhost/Rosaline">
		<x xmlns="http://jabber.org/protocol/muc"/>
	</presence>

Rosaline receives:
	<presence from="room@conference.localhost/Romeo" />

Rosaline receives:
	<presence from='room@conference.localhost/Juliet' type='unavailable'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='member' role='none' nick='Juliet' xmlns='http://jabber.org/protocol/muc#user'/>
		</x>
	</presence>

Rosaline receives:
	<presence from="room@conference.localhost/Rosaline" />

Rosaline receives:
	<message type='groupchat' from='room@conference.localhost'><subject/></message>

Romeo receives:
	<presence from='room@conference.localhost/Rosaline'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item jid="${Rosaline's full JID}" affiliation='none' role='participant'/>
		</x>
	</presence>

# Rosaline tries to register her own nickname, but unaffiliated
# registration is disabled by default

Rosaline sends:
	<iq id='reg990' to='room@conference.localhost' type='get'>
		<query xmlns='jabber:iq:register'/>
	</iq>

Rosaline receives:
	<iq type='error' from='room@conference.localhost' id='reg990'>
		<error type='auth'>
			<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
		</error>
	</iq>

Rosaline sends:
	<iq id='reg991' to='room@conference.localhost' type='set'>
		<query xmlns='jabber:iq:register'>
			<x xmlns='jabber:x:data' type='submit'>
				<field var='FORM_TYPE'>
					<value>http://jabber.org/protocol/muc#register</value>
				</field>
				<field var='muc#register_roomnick'>
					<value>Romeo</value>
				</field>
			</x>
		</query>
	</iq>

Rosaline receives:
	<iq id='reg991' type='error'>
		<error type='auth'>
			<registration-required xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/>
		</error>
	</iq>

# Romeo reserves her nickname for her

Romeo sends:
	<iq id='member2' to='room@conference.localhost' type='set'>
		<query xmlns='http://jabber.org/protocol/muc#admin'>
			<item affiliation='member' jid="${Rosaline's JID}" nick='Rosaline' />
		</query>
	</iq>

Romeo receives:
	<presence from='room@conference.localhost/Rosaline'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='member' role='participant' jid="${Rosaline's full JID}">
				<actor jid="${Romeo's full JID}" nick='Romeo'/>
			</item>
		</x>
	</presence>

Romeo receives:
	<iq type='result' id='member2' from='room@conference.localhost' />

Rosaline receives:
	<presence from='room@conference.localhost/Rosaline'>
		<x xmlns='http://jabber.org/protocol/muc#user'>
			<item affiliation='member' role='participant' jid="${Rosaline's full JID}">
				<actor nick='Romeo' />
			</item>
			<status xmlns='http://jabber.org/protocol/muc#user' code='110'/>
		</x>
	</presence>

# Romeo sets their their own nickname via admin query (see #1273)
Romeo sends:
	<iq to="room@conference.localhost" id="reserve" type="set">
		<query xmlns="http://jabber.org/protocol/muc#admin">
			<item nick="Romeo" affiliation="owner" jid="${Romeo's JID}"/>
		</query>
	</iq>

Romeo receives:
	<presence from="room@conference.localhost/Romeo">
		<x xmlns="http://jabber.org/protocol/muc#user">
			<item xmlns="http://jabber.org/protocol/muc#user" role="moderator" jid="${Romeo's full JID}" affiliation="owner">
				<actor xmlns="http://jabber.org/protocol/muc#user" nick="Romeo"/>
			</item>
			<status xmlns="http://jabber.org/protocol/muc#user" code="110"/>
		</x>
	</presence>

Romeo receives:
	<iq from="room@conference.localhost" id="reserve" type="result"/>