Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
MatrixRoom.php 6.68 KiB
<?php

/**
 * MatrixRoom.php
 * model class for mapping between Matrix rooms and Stud.IP structures (courses).
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * @author      Thomas Hackl <hackl@data-quest.de>
 * @license     http://www.gnu.org/licenses/gpl-2.0.html GPL version 2
 * @category    Matrix
 *
 * @property string range_id database column
 * @property string matrix_room_id database column
 * @property string mkdate database column
 * @property string chdate database column
 */

class MatrixRoom extends SimpleORMap
{

    const POWER_LEVEL_AUTOR = 0;
    const POWER_LEVEL_TUTOR = 50;
    const POWER_LEVEL_DOZENT = 50;
    const ROOM_POWER_LEVELS = [
        'events' => [
            'ban' => self::POWER_LEVEL_TUTOR,
            'invite' => self::POWER_LEVEL_TUTOR,
            'kick' => self::POWER_LEVEL_TUTOR,
            'm.room.name' => self::POWER_LEVEL_DOZENT,
            'm.room.power_levels' => self::POWER_LEVEL_DOZENT,
            'redact' => self::POWER_LEVEL_TUTOR
        ],
        'notifications' => [
            'room' => self::POWER_LEVEL_TUTOR
        ],
        'defaults' => [
            'events_default' => self::POWER_LEVEL_AUTOR,
            'state_default' => self::POWER_LEVEL_TUTOR,
            'users_default' => self::POWER_LEVEL_AUTOR
        ]
    ];

    protected static function configure($config = [])
    {
        $config['db_table'] = 'matrix_rooms';
        $config['belongs_to']['course'] = [
            'class_name' => 'Course',
            'foreign_key' => 'range_id'
        ];

        parent::configure($config);
    }

    /**
     * Ensures that a Matrix room exists for the given context.
     *
     * @param Context $context
     */
    public static function requireRoom($context)
    {
        if (!($room = self::find($context->getId()))) {
            $sysaccount = MatrixAccount::requireSystemAccount();
            MatrixClient::get()->login($sysaccount);

            // Invite all members with existing Matrix account to newly created room.
            $invites = [];
            // Permission levels in the room to create.
            $permissions = [
                $sysaccount->getUserId() => 100
            ];
            $accounts = [];
            // Process existing course members.
            foreach ($context->members as $member) {
                if ($mapped = MatrixAccount::find($member->user_id)) {
                    $invites[] = new Patrix\User($mapped->matrix_account_id, $member->getUserFullname(),
                        Avatar::getAvatar($member->user_id)->getURL(Avatar::NORMAL));

                    switch ($member->status) {
                        case 'dozent':
                            $power_level = MatrixRoom::POWER_LEVEL_DOZENT;
                            break;
                        case 'tutor':
                            $power_level = MatrixRoom::POWER_LEVEL_TUTOR;
                            break;
                        default:
                            $power_level = MatrixRoom::POWER_LEVEL_AUTOR;
                    }

                    // Collect permissions for setting power levels.
                    $permissions[$mapped->matrix_account_id] = $power_level;
                }
            }

            $permission_set = new Patrix\RoomPermissionSet(
                self::ROOM_POWER_LEVELS['defaults'],
                $permissions,
                self::ROOM_POWER_LEVELS['events'],
                self::ROOM_POWER_LEVELS['notifications'],
                self::POWER_LEVEL_AUTOR
            );

            $newRoom = MatrixClient::get()->createRoom($sysaccount, Context::getHeaderLine(), false, '',
                [], $permission_set);

            $mapping = new self();
            $mapping->range_id = $context->getId();
            $mapping->matrix_room_id = $newRoom->getId();
            $mapping->store();

            return $newRoom;

        } else {
            return $room->getLinkedRoom();
        }
    }

    public static function hasRoom($context_id)
    {
        return self::exists($context_id);
    }

    public function getLinkedRoom()
    {
        return new Patrix\Room($this->matrix_room_id, Context::getHeaderLine());
    }

    public function requireMembership($account)
    {
        $sysaccount = MatrixAccount::requireSystemAccount();

        $invited = MatrixClient::get()->inviteIntoRoom($sysaccount, $this->getLinkedRoom(), $account->getUserName());

        if ($invited) {
            MatrixClient::get()->login($account);
            MatrixClient::get()->joinRoom($account, $this->getLinkedRoom());
            if ($GLOBALS['perm']->have_studip_perm('dozent', $this->range_id)) {
                $perm = self::POWER_LEVEL_DOZENT;
            } else if ($GLOBALS['perm']->have_studip_perm('tutor', $this->range_id)) {
                $perm = self::POWER_LEVEL_TUTOR;
            } else {
                $perm = self::POWER_LEVEL_AUTOR;
            }

            // Get existing room permissions so that they are not completely overwritten when adding the current user.
            $permissions = MatrixClient::get()
                ->getRoomPermissionLevels($sysaccount, $this->getLinkedRoom())
                ->getUserPermissions();

            $permissions[$account->getUserName()] = $perm;

            // Set correct permission for current user.
            MatrixClient::get()->setRoomUserPermissionLevels($sysaccount, $this->getLinkedRoom(), $permissions);
        }
    }

    public function requireInvitation($account)
    {
        $sysaccount = MatrixAccount::requireSystemAccount();

        $invited = MatrixClient::get()->inviteIntoRoom($sysaccount, $this->getLinkedRoom(), $account->getUserName());

        if ($invited) {

            if ($GLOBALS['perm']->have_studip_perm('dozent', $this->range_id)) {
                $perm = self::POWER_LEVEL_DOZENT;
            } else if ($GLOBALS['perm']->have_studip_perm('tutor', $this->range_id)) {
                $perm = self::POWER_LEVEL_TUTOR;
            } else {
                $perm = self::POWER_LEVEL_AUTOR;
            }

            // Get existing room permissions so that they are not completely overwritten when adding the current user.
            $permissions = MatrixClient::get()
                ->getRoomPermissionLevels($sysaccount, $this->getLinkedRoom())
                ->getUserPermissions();

            $permissions[$account->getUserName()] = $perm;

            // Set correct permission for current user.
            MatrixClient::get()->setRoomUserPermissionLevels($sysaccount, $this->getLinkedRoom(), $permissions);
        }
    }

}