Panopto API 202: Working with user details and session details

Return to the Panopto API index page

This page was based on the query from the Panopto Forum. Sometimes it is best to try and something from the real world.

We’ve been trying to promote the use of Panopto for student presentations, but keep getting the same feedback from academic staff. If they use the dropbox facility then each student has to log in to the recorder separately, and this adds time to an already busy session. However, if the academic records all the presentations logged in as him/herself then the recordings will be available to all students, and access then has to be managed individually. It would therefore help matters if the academic could move the recording into the dropbox folder and then change the owner of the recording to the individual student, thereby having the same end result as the student having logged in to record.

This request seems to have a few requirements

  1. We need to deal with sessions in a particular folder
  2. We need to change the owner of the video in a programmatic way

Just these two requirements tell us that were’re going to be using more than one of our service references. Sessions in a folder are managed by the PanoptoSessionManagment, and actually changing the owner is also PanoptoSessionManagement, but getting the user details used to change the owner is PanoptoUserManagement.

We can’t use the same authentication information for both, so we’ll need to make two.

PanoptoSessionManagement.AuthenticationInfo sessionAuthInfoPSM = new PanoptoSessionManagement.AuthenticationInfo()
{
    UserKey = "api",
    Password = "s2ezupajePhasaP5"
};

PanoptoUserManagement.AuthenticationInfo sessionAuthInfoPUM = new PanoptoUserManagement.AuthenticationInfo()
{
    UserKey = "api",
    Password = "s2ezupajePhasaP5"
};

Object names need to be unique, so you’ll notice that I now need to refer to sessionAuthInfoPSM or sessionAuthInfoPUM when referring to session and user management.

For this request I’ve decided that the easiest way to choose a user is for the academic in question to put the username of the student as the first word of the presentation title. This seems the quickest way of using the API to change all the owner details.

To start with we need to do exactly the same as we did on 201, but we do need to change the code to reflect the PSM we added above.

PanoptoSessionManagement.Pagination pagination = new PanoptoSessionManagement.Pagination { MaxNumberResults = 5, PageNumber = 0 };
PanoptoSessionManagement.ListSessionsRequest requestPSM = new PanoptoSessionManagement.ListSessionsRequest { Pagination = pagination, FolderId = Guid.Parse("76083047-7ccd-494f-8f8a-0f01a1101876")};
ISessionManagement sessionMgr = new SessionManagementClient();
// User management goes here
ListSessionsResponse response = sessionMgr.GetSessionsList(sessionAuthInfoPSM, requestPSM, null);

if (response.Results.Length > 0)
{
    foreach (Session session in response.Results)
    {
        Console.WriteLine(session.Id + ": " + session.Name);
    }
}

We know that we’ll need to deal with user details as well as session details, so replace // User management goes here with

IUserManagement userMgr = new UserManagementClient();

userMgr can now be used for all these commands.

The end goal for this application will be to call UpdateSessionOwner. Notice how this command states that it must be run by an administrator, so is unlikely to work using the lecturers integration account. It will work for us as long as our API user is an administrator.

UpdateSessionOwner needs to have authentication details, a GUID of a session (or sessions) to update, and the username to change the owner to. We’ve checked the authentication and already found the ID, so we just need to find the username.

The following code, to be added under the “Console.WriteLine(session.Id + “: ” + session.Name);” line takes the first word of the session title, which will hopefully be a username.

string[] splitUsername = session.Name.Split(' ');

As explained in 004, users using Blackboard (or other integrations) have the integration name prefixed to the username. To account for this add this line above the “if (response.Results…” line

// If using intergration add the Instance name here in the format @"InstanceName\" 
// If not using intergration, leave as empty string
string intergrationName = @"BBPreProd\";

We can now refer to the real username

Console.WriteLine("Checking if " + intergrationName + splitUsername[0] + " is a real user");

We’re next going to check that the string returned is a real username. We’ll do this by searching for it

PanoptoUserManagement.ListUsersRequest requestPUM = new PanoptoUserManagement.ListUsersRequest {};
ListUsersResponse userResponse = userMgr.ListUsers(sessionAuthInfoPUM, requestPUM, intergrationName + splitUsername[0])

You’ll notice that this code is practically the same as further up the page except …

PanoptoSessionManagement is PanoptoUserManagement
ListSessionsRequest is  ListUsersRequest
ListSessionsResponse is ListUsersResponse
sessionMgr is userMgr
GetSessionsList is ListUsers

… so very similar.

Because it is so similar we can use almost the same code to loop through the result.

if (userResponse.TotalResultCount > 0)
{
    foreach (User user in userResponse.PagedResults)
    {
        if (user.UserKey.Equals(intergrationName + splitUsername[0]))
        { 
            Console.WriteLine("Changing owner of {0} to {1}", session.Name, intergrationName + splitUsername[0]);
            // Do the work here
            break;
        }
    }
}
else
{
    Console.WriteLine(intergrationName + splitUsername[0] + " isn't a real user");
}

The main difference here is that we have userReponse.PagedResults instead of [session]response.Results. I’ve also added a check to see if the username matches what we are expecting, in case the first word is “a” and the first result is “andy” (i.e. the user doesn’t exist).

We can now update the owner, but UpdateSessionOwner needs an array of sessions, so we need to make our session an array before running the main command

Guid[] sessionIdArray = new Guid[] { session.Id };
sessionMgr.UpdateSessionOwner(sessionAuthInfoPSM, sessionIdArray, intergrationName + splitUsername[0]);

Full code below

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using ConsolePanoptoAPI.PanoptoAccessManagement;
using ConsolePanoptoAPI.PanoptoAuth;
using ConsolePanoptoAPI.PanoptoRemoteRecorderManagement;
using ConsolePanoptoAPI.PanoptoSessionManagement;
using ConsolePanoptoAPI.PanoptoUsageReporting;
using ConsolePanoptoAPI.PanoptoUserManagement;

// ANY NEW NAMESPACES SHOULD BE ADDED HERE

// END OF NAMESPACES

namespace ConsolePanoptoAPI
{
    class Program
    {
        static bool hasBeenInitialized = false;

        static void Main(string[] args)
        {
            // PUT YOUR AUTHENTICATION DETAILS HERE

            PanoptoSessionManagement.AuthenticationInfo sessionAuthInfoPSM = new PanoptoSessionManagement.AuthenticationInfo()
            {
                UserKey = "api",
                Password = "s2ezupajePhasaP5"
            };

            PanoptoUserManagement.AuthenticationInfo sessionAuthInfoPUM = new PanoptoUserManagement.AuthenticationInfo()
            {
                UserKey = "api",
                Password = "s2ezupajePhasaP5"
            };

            // END OF AUTHENTICATION DETAILS

            // START WRITING CODE HERE

            PanoptoSessionManagement.Pagination pagination = new PanoptoSessionManagement.Pagination { MaxNumberResults = 5, PageNumber = 0 };
            PanoptoSessionManagement.ListSessionsRequest requestPSM = new PanoptoSessionManagement.ListSessionsRequest {Pagination = pagination, FolderId = Guid.Parse("76083047-7ccd-494f-8f8a-0f01a1101876")};
            ISessionManagement sessionMgr = new SessionManagementClient();
            IUserManagement userMgr = new UserManagementClient();
            ListSessionsResponse response = sessionMgr.GetSessionsList(sessionAuthInfoPSM, requestPSM, null);

            // If using intergration add the Instance name here in the format @"InstanceName\" 
            // If not using intergration, leave as empty string
            string intergrationName = @"BBPreProd\";

            if (response.Results.Length > 0)
            {
                foreach (Session session in response.Results)
                {
                    Console.WriteLine(session.Id + ": " + session.Name);
                    string[] splitUsername = session.Name.Split(' ');
                    Console.WriteLine("Checking if " + intergrationName + splitUsername[0] + " is a real user");
                    PanoptoUserManagement.ListUsersRequest requestPUM = new PanoptoUserManagement.ListUsersRequest {};
                    ListUsersResponse userResponse = userMgr.ListUsers(sessionAuthInfoPUM, requestPUM, intergrationName + splitUsername[0]);
                    if (userResponse.TotalResultCount > 0)
                    {
                        foreach (User user in userResponse.PagedResults)
                        {
                            if (user.UserKey.Equals(intergrationName + splitUsername[0]))
                            { 
                                Console.WriteLine("Changing owner of {0} to {1}", session.Name, intergrationName + splitUsername[0]);
                                Guid[] sessionIdArray = new Guid[] { session.Id };
                                sessionMgr.UpdateSessionOwner(sessionAuthInfoPSM, sessionIdArray, intergrationName + splitUsername[0]);
                                break;
                            }
                        }

                    }
                    else
                    {
                        Console.WriteLine(intergrationName + splitUsername[0] + " isn't a real user");
                    }
                }
            }
            else
            {
                Console.WriteLine("No sessions found");
            }

            // STOP WRITING CODE HERE

            Console.WriteLine("Press Enter to exit");
            Console.ReadLine();
        }

        /// 
        /// Ensures that our custom certificate validation has been applied
        /// 
        public static void EnsureCertificateValidation()
        {
            if (!hasBeenInitialized)
            {
                ServicePointManager.ServerCertificateValidationCallback +=
                    new System.Net.Security.RemoteCertificateValidationCallback(CustomCertificateValidation);
                hasBeenInitialized = true;
            }
        }

        /// 
        /// Ensures that server certificate is authenticated
        /// 
        private static bool CustomCertificateValidation(object sender,
            X509Certificate cert, X509Chain chain, System.Net.Security.SslPolicyErrors error)
        {
            return true;
        }

        /// 
        /// Creates an auth code. Used when we want to authenticate a user, but don't know their password.
        /// 
        ///The instance name as set in Panopto > System > Identity Providors
        ///Username as defined by Panopto
        ///The full server name as defined by Panopto > System > Settings > General site settings > Web server FQDN
        ///The key produced through Panopto > System > Identity Providors
        /// 
        private static string CreateAuthCode(string identityProviderInstanceName, string username, string serverFqdn, string applicationKey)
        {
            string payload = identityProviderInstanceName + "\\" + username + "@" + serverFqdn.ToLower() + "|" + applicationKey.ToLower();

            var data = Encoding.ASCII.GetBytes(payload);
            var hashData = new System.Security.Cryptography.SHA1Managed().ComputeHash(data);

            var hash = string.Empty;

            foreach (var b in hashData)
                hash += b.ToString("X2");

            return hash;
        }
    }
}

Return to the Panopto API index page

2 Comments

  1. Sihan

    Hi,
    Appreciate if you can get back to us on following with api and operations details.

    1. How can we get a list of userID’s by using session ID?

    2. How to differentiate between live and recorded sessions using userID?

    Thanks,
    Sihan.

    4 years ago
  2. Ajit Narkhede

    Hi,
    Appreciate if you can get back to us on following with api and operations details.

    1. How can we get a list of userID’s by using session ID?

    2. How to differentiate between live and recorded sessions using userID?

    Thanks,
    Ajit

    4 years ago

Leave a Reply

Your email address will not be published. Required fields are marked *