Skip to content

Commit

Permalink
Disable Chatting for excluded users
Browse files Browse the repository at this point in the history
Signed-off-by: Tobia De Koninck <[email protected]>
  • Loading branch information
LEDfan committed Oct 3, 2017
1 parent 1903151 commit c42ca77
Show file tree
Hide file tree
Showing 11 changed files with 142 additions and 42 deletions.
4 changes: 3 additions & 1 deletion appinfo/application.php
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,9 @@ public function __construct(array $urlParams=array()){
return new ContactsStoreUserProvider(
$c->query('OCP\Contacts\ContactsMenu\IContactsStore'),
$c->query('ServerContainer')->getUserSession(),
$c->query('ServerContainer')->getUserManager()
$c->query('ServerContainer')->getUserManager(),
$c->query('OCP\IGroupManager'),
$c->query('OCP\IConfig')
);
} else {
return new UserManagerUserProvider(
Expand Down
2 changes: 1 addition & 1 deletion js/jsxc
12 changes: 12 additions & 0 deletions js/ojsxc.js
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,16 @@
jsxc.storage.removeUserItem('defaultAvatars');
});

$(document).on('connfail.jsxc', function(ev, condition) {
if (condition === 'x-nc-not_allowed_to_chat') {
jsxc.gui.roster.toggle(jsxc.CONST.HIDDEN);
$('.jsxc_chatIcon').remove();
jsxc.storage.removeItem('jid');
jsxc.storage.removeItem('sid');
jsxc.storage.removeItem('rid');
}
});

$(document).on('status.contacts.count status.contact.updated', function() {
if (jsxc.restoreCompleted) {
setTimeout(function() {
Expand Down Expand Up @@ -388,5 +398,7 @@
if ($('#contactsmenu').length > 0) {
observeContactsMenu();
}

});

}(jQuery));
34 changes: 33 additions & 1 deletion lib/ContactsStoreUserProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace OCA\OJSXC;

use OCP\IConfig;
use OCP\IGroup;
use OCP\IGroupManager;
use OCP\IUserManager;
use OCP\IUserSession;

Expand All @@ -28,11 +31,23 @@ class ContactsStoreUserProvider implements IUserProvider
*/
private $userManager;

public function __construct($contactsStore, IUserSession $userSession, IUserManager $userManager)
/**
* @var IGroupManager
*/
private $groupManager;

/**
* @var IConfig
*/
private $config;

public function __construct($contactsStore, IUserSession $userSession, IUserManager $userManager, IGroupManager $groupManager, IConfig $config)
{
$this->contactsStore = $contactsStore;
$this->userSession = $userSession;
$this->userManager = $userManager;
$this->groupManager = $groupManager;
$this->config = $config;
}

public function getAllUsers()
Expand Down Expand Up @@ -87,4 +102,21 @@ public function hasUserForUserByUID($uid1, $uid2)
{
return !is_null($this->contactsStore->findOne($this->userManager->get($uid1), 0, $uid2));
}

public function isUserExcluded($userId)
{
if ($this->config->getAppValue('core', 'shareapi_exclude_groups', 'no') === 'yes') {
$user = $this->userManager->get($userId);
$user_groups = $this->groupManager->getUserGroupIds($user);
$excludedGroups = $this->config->getAppValue('core', 'shareapi_exclude_groups_list', '');
$decodedExcludeGroups = json_decode($excludedGroups, true);
$excludeGroupsList = ($decodedExcludeGroups !== null) ? $decodedExcludeGroups : [];

if (count(array_intersect($excludeGroupsList, $user_groups)) !== 0) {
// a group of the current user is excluded -> filter all local users
return true;
}
}
return false;
}
}
82 changes: 44 additions & 38 deletions lib/Controller/HttpBindController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use OCA\OJSXC\Db\Presence;
use OCA\OJSXC\Db\PresenceMapper;
use OCA\OJSXC\Db\StanzaMapper;
use OCA\OJSXC\Exceptions\TerminateException;
use OCA\OJSXC\Http\XMPPResponse;
use OCA\OJSXC\ILock;
use OCA\OJSXC\NewContentContainer;
Expand Down Expand Up @@ -162,51 +163,56 @@ public function index()
$input = $this->body;
$longpoll = true; // set to false when the response should directly be returned and no polling should be done
$longpollStart = true; // start the first long poll cycle
if (!empty($input)) {
// replace invalid XML by valid XML one
$input = str_replace("<vCard xmlns='vcard-temp'/>", "<vCard xmlns='jabber:vcard-temp'/>", $input);
$reader = new Reader();
$reader->xml($input);
$reader->elementMap = [
'{jabber:client}message' => 'Sabre\Xml\Element\KeyValue',
'{jabber:client}presence' => function (Reader $reader) {
return Presence::createFromXml($reader, $this->userId);
try {
if (!empty($input)) {
// replace invalid XML by valid XML one
$input = str_replace("<vCard xmlns='vcard-temp'/>", "<vCard xmlns='jabber:vcard-temp'/>", $input);
$reader = new Reader();
$reader->xml($input);
$reader->elementMap = [
'{jabber:client}message' => 'Sabre\Xml\Element\KeyValue',
'{jabber:client}presence' => function (Reader $reader) {
return Presence::createFromXml($reader, $this->userId);
}
];
$stanzas = null;
try {
$stanzas = $reader->parse();
} catch (LibXMLException $e) {
}
];
$stanzas = null;
try {
$stanzas = $reader->parse();
} catch (LibXMLException $e) {
}
if (!is_null($stanzas) && count($stanzas['value']) > 0) {
$this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING);
}
if (!is_null($stanzas)) {
$stanzas = $stanzas['value'];
if (is_array($stanzas)) {
foreach ($stanzas as $stanza) {
$stanzaType = $this->getStanzaType($stanza);
if ($stanzaType === self::MESSAGE) {
$this->messageHandler->handle($stanza);
} elseif ($stanzaType === self::IQ) {
$result = $this->iqHandler->handle($stanza);
if (!is_null($result)) {
$longpoll = false;
$this->response->write($result);
}
} elseif ($stanza['value'] instanceof Presence) {
$results = $this->presenceHandler->handle($stanza['value']);
if (!is_null($results) && is_array($results)) {
$longpoll = false;
$longpollStart = false;
foreach ($results as $r) {
$this->response->write($r);
if (!is_null($stanzas) && count($stanzas['value']) > 0) {
$this->stanzaLogger->logRaw($input, StanzaLogger::RECEIVING);
}
if (!is_null($stanzas)) {
$stanzas = $stanzas['value'];
if (is_array($stanzas)) {
foreach ($stanzas as $stanza) {
$stanzaType = $this->getStanzaType($stanza);
if ($stanzaType === self::MESSAGE) {
$this->messageHandler->handle($stanza);
} elseif ($stanzaType === self::IQ) {
$result = $this->iqHandler->handle($stanza);
if (!is_null($result)) {
$longpoll = false;
$this->response->write($result);
}
} elseif ($stanza['value'] instanceof Presence) {
$results = $this->presenceHandler->handle($stanza['value']);
if (!is_null($results) && is_array($results)) {
$longpoll = false;
$longpollStart = false;
foreach ($results as $r) {
$this->response->write($r);
}
}
}
}
}
}
}
} catch (TerminateException $e) {
$this->response->terminate();
return $this->response;
}

// Start long polling
Expand Down
8 changes: 8 additions & 0 deletions lib/Exceptions/TerminateException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

namespace OCA\OJSXC\Exceptions;

// TODO
class TerminateException extends Exception
{
}
6 changes: 6 additions & 0 deletions lib/IUserProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,10 @@ public function hasUserForUser(User $user1, User $user2);
* @return bool
*/
public function hasUserForUserByUID($uid1, $uid2);

/**
* @param string $userId
* @return bool
*/
public function isUserExcluded($userId);
}
6 changes: 6 additions & 0 deletions lib/UserManagerUserProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,10 @@ public function hasUserForUserByUID($uid1, $uid2)
// since we don't have access to the ContactsStore, we don't apply the enhancement privacy rules.
$this->hasUserByUID($uid2);
}

public function isUserExcluded($userId)
{
// to limit inconsistency we only support the settings in NC > 13.0.0
return false;
}
}
13 changes: 13 additions & 0 deletions lib/http/xmppresponse.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,17 @@ public function render()
$this->writer->endElement();
return $this->writer->outputMemory();
}

/**
* Terminates the Chat connection with the `x-nc-not_allowed_to_chat` condition.
*/
public function terminate()
{
$this->writer = new Writer();
$this->writer->openMemory();
$this->writer->startElement('body');
$this->writer->writeAttribute('xmlns', 'http://jabber.org/protocol/httpbind');
$this->writer->writeAttribute('type', 'terminate');
$this->writer->writeAttribute('condition', 'x-nc-not_allowed_to_chat');
}
}
13 changes: 12 additions & 1 deletion lib/stanzahandlers/iq.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace OCA\OJSXC\StanzaHandlers;

use OCA\OJSXC\Db\IQRoster;
use OCA\OJSXC\Exceptions\TerminateException;
use OCA\OJSXC\IUserProvider;
use OCA\OJSXC\NewContentContainer;
use OCP\IConfig;
use OCP\IUserManager;
use Sabre\Xml\Reader;
Expand Down Expand Up @@ -39,6 +41,8 @@ class IQ extends StanzaHandler
* @param string $host
* @param IUserManager $userManager
* @param IConfig $config
* @param IUserProvider $userProvider
* @param NewContentContainer $newContentContainer
*/
public function __construct($userId, $host, IUserManager $userManager, IConfig $config, IUserProvider $userProvider)
{
Expand All @@ -52,6 +56,7 @@ public function __construct($userId, $host, IUserManager $userManager, IConfig $
/**
* @param array $stanza
* @return IQRoster
* @throws TerminateException TODO
*/
public function handle(array $stanza)
{
Expand All @@ -60,7 +65,13 @@ public function handle(array $stanza)
// if in debug mode we show the own username in the roster for testing
$debugMode = $this->config->getSystemValue("debug");

if ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') {
if ($stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#items}query' || $stanza['value'][0]['name'] === '{http://jabber.org/protocol/disco#info}query') {
// the disco queries are currently not implemented but these are the first stanzas send to the server so
// they are ideal to terminate the connection if a user is excluded from chatting.
if ($this->userProvider->isUserExcluded($this->userId)) {
throw new TerminateException();
}
} elseif ($stanza['value'][0]['name'] === '{jabber:iq:roster}query') {
$id = $stanza['attributes']['id'];
$iqRoster = new IQRoster();
$iqRoster->setType('result');
Expand Down
4 changes: 4 additions & 0 deletions lib/stanzahandlers/presence.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use OCA\OJSXC\Db\MessageMapper;
use OCA\OJSXC\Db\PresenceMapper;
use OCA\OJSXC\Exceptions\TerminateException;
use Sabre\Xml\Reader;
use Sabre\Xml\Writer;
use OCA\OJSXC\Db\Presence as PresenceEntity;
Expand Down Expand Up @@ -47,11 +48,14 @@ public function __construct($userId, $host, PresenceMapper $presenceMapper, Mess
* - update the presence in the database
* - broadcast the presence
* - return the active presence if the type isn't equal to unavailable
*
* @param PresenceEntity $presence
* @return PresenceEntity[]
* @throws TerminateException
*/
public function handle(PresenceEntity $presence)
{

// update the presence
$this->presenceMapper->setPresence($presence);

Expand Down

0 comments on commit c42ca77

Please sign in to comment.