Ejemplo n.º 1
0
class Folder(RESTDispatch):
    def __init__(self):
        self._session = SessionManagement()
        self._access = AccessManagement()
        self._user = UserManagement()

    def GET(self, request, **kwargs):
        folder_id = kwargs.get('folder_id')
        if (folder_id):
            return self._get_folder_details(space_id)
        else:
            params = {}
            for q in request.GET:
                params[q] = request.GET.get(q)

            return self._list_folders(params)

    def _get_folder_details(self, space_id):
        return self.json_response('{}')

    def _list_folders(self, args):
        folders = []
        if 'search' in args:
            search = args['search'].strip()
            if len(search) > 3:
                for folder in self._session.getFoldersList(search_query=search):
                    creators = []
                    viewers = []
                    deets = self._access.getFolderAccessDetails(folder['Id'])
                    if deets.UsersWithCreatorAccess:
                        response = self._user.getUsers(deets.UsersWithCreatorAccess.guid)
                        if response and response.User:
                            for user in response.User:
                                match = re.match(r'^%s\\(.+)$' % (settings.PANOPTO_API_APP_ID), user.UserKey)
                                creators.append({
                                    'key': match.group(1) if match else user.UserKey,
                                    'id': user.UserId
                                })

                    if deets.UsersWithViewerAccess:
                        response = self._user.getUsers(deets.UsersWithCreatorAccess.guid)
                        if response and response.User:
                            for user in response.User:
                                match = re.match(r'^%s\\(.+)$' % (settings.PANOPTO_API_APP_ID), user.UserKey)
                                viewers.append({
                                    'key': match.group(1) if match else user.UserKey,
                                    'id': user.UserId
                                })

                    folders.append({
                        'name': folder.Name,
                        'id': folder.Id,
                        'auth' : {
                            'creators': creators,
                            'viewers': viewers
                        }
                    })

        return self.json_response(folders)
Ejemplo n.º 2
0
class Folder(RESTDispatch):
    def __init__(self):
        self._session = SessionManagement()
        self._access = AccessManagement()
        self._user = UserManagement()

    def GET(self, request, **kwargs):
        folder_id = kwargs.get("folder_id")
        if folder_id:
            return self._get_folder_details(space_id)
        else:
            params = {}
            for q in request.GET:
                params[q] = request.GET.get(q)

            return self._list_folders(params)

    def _get_folder_details(self, space_id):
        return self.json_response("{}")

    def _list_folders(self, args):
        folders = []
        if "search" in args:
            search = args["search"].strip()
            if len(search) > 3:
                for folder in self._session.getFoldersList(search_query=search):
                    creators = []
                    viewers = []
                    deets = self._access.getFolderAccessDetails(folder["Id"])
                    if deets.UsersWithCreatorAccess:
                        response = self._user.getUsers(deets.UsersWithCreatorAccess.guid)
                        if response and response.User:
                            for user in response.User:
                                match = re.match(r"^%s\\(.+)$" % (settings.PANOPTO_API_APP_ID), user.UserKey)
                                creators.append({"key": match.group(1) if match else user.UserKey, "id": user.UserId})

                    if deets.UsersWithViewerAccess:
                        response = self._user.getUsers(deets.UsersWithCreatorAccess.guid)
                        if response and response.User:
                            for user in response.User:
                                match = re.match(r"^%s\\(.+)$" % (settings.PANOPTO_API_APP_ID), user.UserKey)
                                viewers.append({"key": match.group(1) if match else user.UserKey, "id": user.UserId})

                    folders.append(
                        {"name": folder.Name, "id": folder.Id, "auth": {"creators": creators, "viewers": viewers}}
                    )

        return self.json_response(folders)
Ejemplo n.º 3
0
def get_panopto_folder_creators(folder_id):
    user_api = UserManagement()
    access_api = AccessManagement()
    creators = []
    folder_access = access_api.getFolderAccessDetails(folder_id)

    if len(folder_access['UsersWithCreatorAccess']):
        guids = folder_access['UsersWithCreatorAccess'][0]
        if len(guids):
            users = user_api.getUsers(guids)
            for user in users[0]:
                match = re.match(r'^%s\\(.+)$' % (settings.PANOPTO_API_APP_ID), user['UserKey'])
                if match:
                    creators.append(match.group(1) if match else user['UserKey'])

    return creators
Ejemplo n.º 4
0
def get_panopto_folder_creators(folder_id):
    user_api = UserManagement()
    access_api = AccessManagement()
    creators = []
    folder_access = access_api.getFolderAccessDetails(folder_id)

    if len(folder_access['UsersWithCreatorAccess']):
        guids = folder_access['UsersWithCreatorAccess'][0]
        if len(guids):
            users = user_api.getUsers(guids)
            for user in users[0]:
                match = re.match(r'^%s\\(.+)$' % (settings.PANOPTO_API_APP_ID),
                                 user['UserKey'])
                if match:
                    creators.append(
                        match.group(1) if match else user['UserKey'])

    return creators
Ejemplo n.º 5
0
 def __init__(self):
     self._session_api = SessionManagement()
     self._recorder_api = RemoteRecorderManagement()
     self._access_api = AccessManagement()
     self._user_api = UserManagement()
     self._audit_log = logging.getLogger('audit')
Ejemplo n.º 6
0
class Session(RESTDispatch):
    def __init__(self):
        self._session_api = SessionManagement()
        self._recorder_api = RemoteRecorderManagement()
        self._access_api = AccessManagement()
        self._user_api = UserManagement()
        self._audit_log = logging.getLogger('audit')

    def GET(self, request, **kwargs):
        session_id = kwargs.get('session_id')
        if session_id:
            raw_session = self._session_api.getSessionsById(
                [session_id])[0][0]
            raw_access = self._access_api.getSessionAccessDetails(
                session_id)
            start_utc = pytz.utc.localize(
                raw_session['StartTime']).astimezone(tz.tzutc())
            session = {
                'creator_id': raw_session['CreatorId'],
                'description': raw_session['Description'],
                'duration': raw_session['Duration'],
                'external_id': raw_session['ExternalId'],
                'folder_id': raw_session['FolderId'],
                'folder_name': raw_session['FolderName'],
                'folder_creators': [],
                'id': raw_session['Id'],
                'is_video_url': raw_session['IosVideoUrl'],
                'is_broadcast': raw_session['IsBroadcast'],
                'is_public': raw_access['IsPublic'],
                'is_downloadable': raw_session['IsDownloadable'],
                'name': raw_session['Name'],
                'remote_recorder_ids': raw_session['RemoteRecorderIds'].get(
                    'guid', None),
                'share_page_url': raw_session['SharePageUrl'],
                'start_time': start_utc.isoformat(),
                'state': raw_session['State'],
                'status_message': raw_session['StatusMessage'],
                'thumb_url': raw_session['ThumbUrl'],
                'viewer_url': raw_session['ViewerUrl'],
            }
        else:
            session = {}

        return self.json_response(session)

    def POST(self, request, **kwargs):
        try:
            new_session = self._validate_session(request.body)

            session = self._recorder_api.scheduleRecording(new_session.get('name'),
                                                           new_session.get('folder_id'),
                                                           new_session.get('is_broadcast'),
                                                           new_session.get('start_time'),
                                                           new_session.get('end_time'),
                                                           new_session.get('recorder_id'))
            if session.ConflictsExist:
                conflict = session.ConflictingSessions[0][0]
                start_time = conflict.StartTime
                end_time = conflict.EndTime
                content = {
                    'conflict_name': conflict.SessionName,
                    'conflict_start': start_time.isoformat(),
                    'conflict_end': end_time.isoformat()
                }
                return self.error_response(409, "Schedule Conflict Exists",
                                           content=content)

            session_id = session.SessionIDs[0][0]

            self._session_api.updateSessionExternalId(
                session_id, new_session.get('external_id'))

            if new_session.get('is_public'):
                self._access_api.updateSessionIsPublic(session_id, True)

            messages = []
            creators = new_session.get('folder_creators')
            if creators and type(creators) is list:
                messages = self._sync_creators(
                    new_session.get('folder_id'), creators)

            self._audit_log.info('%s scheduled %s for %s from %s to %s' % (
                request.user, new_session.get('external_id'),
                new_session.get('uwnetid'), new_session.get('start_time'),
                new_session.get('end_time')))

            return self.json_response({
                'recording_id': session_id,
                'messages': messages
            })
        except InvalidParamException as ex:
            return self.error_response(400, "%s" % ex)
        except Exception as ex:
            return self.error_response(500, "Unable to save session: %s" % ex)

    def PUT(self, request, **kwargs):
        try:
            session_update = self._validate_session(request.body)
            session = self._session_api.getSessionsById(
                session_update.get('recording_id'))[0][0]

            start_utc = session.StartTime.astimezone(pytz.utc)
            end_utc = start_utc + datetime.timedelta(
                seconds=int(session.Duration))

            session_update_start = self._valid_time(session_update.get('start_time'))
            session_update_end = self._valid_time(session_update.get('end_time'))

            if not (start_utc.isoformat() == session_update_start
                    and end_utc.isoformat() == session_update_end):
                self._recorder_api.updateRecordingTime(
                    session.Id, session_update_start, session_update_end)

            access = self._access_api.getSessionAccessDetails(session.Id)
            if access.IsPublic != session_update.get('is_public'):
                self._access_api.updateSessionIsPublic(
                    session.Id, session_update.get('is_public'))

            if session.IsBroadcast != session_update.get('is_broadcast'):
                self._session_api.updateSessionIsBroadcast(
                    session.Id, session_update.get('is_broadcast'))

            folder_name = session_update.get('folder_name')
            if session.FolderName != folder_name:
                self._session_api.moveSessions(
                    [session.Id], session_update.get('folder_id'))

            messages = []
            creators = session_update.get('folder_creators')
            if creators and type(creators) is list:
                messages = self._sync_creators(
                    session_update.get('folder_id'), creators)

            self._audit_log.info('%s modified %s for %s from %s to %s in %s' % (
                request.user, session_update.get('external_id'),
                session_update.get('uwnetid'), session_update.get('start_time'),
                session_update.get('end_time'), session_update.get('folder_name')))

            return self.json_response({
                'recording_id': session.Id,
                'messages': messages
            })
        except InvalidParamException as ex:
            return self.error_response(400, "%s" % ex)
        except Exception as ex:
            return self.error_response(500, "Unable to save session: %s" % ex)

    def DELETE(self, request, **kwargs):
        try:
            session_id = self._valid_recorder_id(kwargs.get('session_id'))
            # do not permit param tampering
            key = course_event_key(request.GET.get('uwnetid', ''),
                                   request.GET.get('name', ''),
                                   request.GET.get('eid', ''),
                                   request.GET.get('rid', ''))

            if key != request.GET.get("key", None):
                raise InvalidParamException('Invalid Client Key')

            self._session_api.deleteSessions([session_id])
            self._audit_log.info('%s deleted session %s' %
                                 (request.user, session_id))
            return self.json_response({
                'deleted_recording_id': session_id
            })
        except InvalidParamException as err:
            return self.error_response(400, "Invalid Parameter: %s" % err)

    def _valid_folder(self, name, external_id):
        try:
            folder_id = Validation().panopto_id(external_id)
            return folder_id
        except InvalidParamException:
            pass

        try:
            if external_id and len(external_id):
                folders = self._session_api.getAllFoldersByExternalId(
                    [external_id])
                if folders and len(folders) == 1 and len(folders[0]):
                    return folders[0][0].Id

            folders = self._session_api.getFoldersList(search_query=name)
            if folders and len(folders):
                for folder in folders:
                    if folder.Name == name:
                        folder_id = folder.Id
                        if external_id and len(external_id):
                            self._session_api.updateFolderExternalId(
                                folder_id, external_id)

                        return folder_id

            new_folder = self._session_api.addFolder(name)
            if not new_folder:
                raise InvalidParamException('Cannot add folder: %s' % name)

            new_folder_id = new_folder.Id

            if external_id and len(external_id):
                self._session_api.updateFolderExternalId(
                    new_folder_id, external_id)

            return new_folder_id
        except Exception as ex:
            raise InvalidParamException('Cannot add folder: %s' % ex)

    def _validate_session(self, request_body):
        session = {}
        data = json.loads(request_body)

        session['recording_id'] = data.get("recording_id", "")
        session['uwnetid'] = data.get("uwnetid", "")
        session['name'] = self._valid_recording_name(data.get("name", "").strip())
        session['external_id'] = self._valid_external_id(
            data.get("external_id", "").strip())
        session['recorder_id'] = self._valid_recorder_id(
            data.get("recorder_id", "").strip())
        session['folder_external_id'] = data.get(
            "folder_external_id", "").strip()

        session['session_id'] = data.get("session_id", "").strip()
        if len(session['session_id']):
            self._valid_external_id(session['session_id'])

        # do not permit param tamperings
        key = course_event_key(session['uwnetid'], session['name'],
                               session['external_id'], session['recorder_id'])
        if key != data.get("key", ''):
            raise InvalidParamException('Invalid Client Key')

        session['is_broadcast'] = self._valid_boolean(data.get("is_broadcast", False))
        session['is_public'] = self._valid_boolean(data.get("is_public", False))
        session['start_time'] = self._valid_time(data.get("start_time", "").strip())
        session['end_time'] = self._valid_time(data.get("end_time", "").strip())
        session['folder_name'] = data.get("folder_name", "").strip()
        session['folder_id'] = self._valid_folder(session['folder_name'],
                                                  session['folder_external_id'])
        session['folder_creators'] = data.get("creators", None)
        return session

    def _valid_external_id(self, external_id):
        if external_id and len(external_id):
            return external_id

        raise InvalidParamException('bad external_id')

    def _valid_recorder_id(self, recorder_id):
        if (recorder_id):
            return Validation().panopto_id(recorder_id)

        raise InvalidParamException('missing recorder id')

    def _valid_recording_name(self, name):
        if name and len(name):
            return name

        raise InvalidParamException('bad recording name')

    def _valid_boolean(self, is_broadcast):
        if not (is_broadcast is None or type(is_broadcast) == bool):
            raise InvalidParamException('bad broadcast flag')

        return is_broadcast

    def _valid_time(self, time):
        if time and len(time):
            return time

        raise InvalidParamException('bad time value')

    def _sync_creators(self, folder_id, folder_creators):
        messages = []
        new_creator_ids = []
        deleted_creator_ids = []
        current_creators = get_panopto_folder_creators(folder_id)
        for creator in folder_creators:
            if creator not in current_creators:
                try:
                    new_creator_ids.append(self._get_panopto_user_id(creator))
                except PanoptoUserException as ex:
                    messages.append('Invalid UWNetId %s' % creator)

        for creator in current_creators:
            if creator not in folder_creators:
                try:
                    deleted_creator_ids.append(self._get_panopto_user_id(creator))
                except PanoptoUserException as ex:
                    messages.append('Invalid UWNetId %s' % creator)

        if len(new_creator_ids):
            try:
                self._access_api.grantUsersAccessToFolder(
                    folder_id, new_creator_ids, 'Creator')
            except PanoptoAPIException as ex:
                match = re.match(r'.*Server raised fault: \'(.+)\'$', str(ex))
                messages.append('%s: %s' % (creator, match.group(1) if match else str(ex)))

        if len(deleted_creator_ids):
            try:
                self._access_api.revokeUsersAccessFromFolder(
                    folder_id, deleted_creator_ids, 'Creator')
            except PanoptoAPIException as ex:
                match = re.match(r'.*Server raised fault: \'(.+)\'$', str(ex))
                messages.append('%s: %s' % (creator, match.group(1) if match else str(ex)))

        return messages

    def _get_panopto_user_id(self, netid):
        key = "%s\%s" % (settings.PANOPTO_API_APP_ID, netid)
        user = self._user_api.getUserByKey(key)
        if not user or user['UserId'] == '00000000-0000-0000-0000-000000000000':
            raise PanoptoUserException('Unprovisioned UWNetId: %s' % (netid))

        return user['UserId']
Ejemplo n.º 7
0
 def __init__(self):
     self._session = SessionManagement()
     self._access = AccessManagement()
     self._user = UserManagement()
Ejemplo n.º 8
0
 def __init__(self):
     self._session = SessionManagement()
     self._access = AccessManagement()
     self._user = UserManagement()