SEBWIN-623, SEBWIN-628, SEBWIN-641, #521: Updated Zoom WebSDK to version 2.10.1 and changed authentication to use SDK key and JWT token.
This commit is contained in:
parent
296f87727d
commit
0bb9f42a3a
8 changed files with 138 additions and 188 deletions
|
@ -92,12 +92,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
|
||||||
case Keys.Proctoring.Zoom.AllowRaiseHand:
|
case Keys.Proctoring.Zoom.AllowRaiseHand:
|
||||||
MapZoomAllowRaiseHands(settings, value);
|
MapZoomAllowRaiseHands(settings, value);
|
||||||
break;
|
break;
|
||||||
case Keys.Proctoring.Zoom.ApiKey:
|
|
||||||
MapZoomApiKey(settings, value);
|
|
||||||
break;
|
|
||||||
case Keys.Proctoring.Zoom.ApiSecret:
|
|
||||||
MapZoomApiSecret(settings, value);
|
|
||||||
break;
|
|
||||||
case Keys.Proctoring.Zoom.AudioMuted:
|
case Keys.Proctoring.Zoom.AudioMuted:
|
||||||
MapZoomAudioMuted(settings, value);
|
MapZoomAudioMuted(settings, value);
|
||||||
break;
|
break;
|
||||||
|
@ -353,22 +347,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData.DataMapping
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void MapZoomApiKey(AppSettings settings, object value)
|
|
||||||
{
|
|
||||||
if (value is string key)
|
|
||||||
{
|
|
||||||
settings.Proctoring.Zoom.ApiKey = key;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MapZoomApiSecret(AppSettings settings, object value)
|
|
||||||
{
|
|
||||||
if (value is string secret)
|
|
||||||
{
|
|
||||||
settings.Proctoring.Zoom.ApiSecret = secret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void MapZoomAudioMuted(AppSettings settings, object value)
|
private void MapZoomAudioMuted(AppSettings settings, object value)
|
||||||
{
|
{
|
||||||
if (value is bool muted)
|
if (value is bool muted)
|
||||||
|
|
|
@ -258,8 +258,6 @@ namespace SafeExamBrowser.Configuration.ConfigurationData
|
||||||
internal const string AllowChat = "zoomFeatureFlagChat";
|
internal const string AllowChat = "zoomFeatureFlagChat";
|
||||||
internal const string AllowClosedCaptions = "zoomFeatureFlagCloseCaptions";
|
internal const string AllowClosedCaptions = "zoomFeatureFlagCloseCaptions";
|
||||||
internal const string AllowRaiseHand = "zoomFeatureFlagRaiseHand";
|
internal const string AllowRaiseHand = "zoomFeatureFlagRaiseHand";
|
||||||
internal const string ApiKey = "zoomApiKey";
|
|
||||||
internal const string ApiSecret = "zoomApiSecret";
|
|
||||||
internal const string AudioMuted = "zoomAudioMuted";
|
internal const string AudioMuted = "zoomAudioMuted";
|
||||||
internal const string Enabled = "zoomEnable";
|
internal const string Enabled = "zoomEnable";
|
||||||
internal const string MeetingNumber = "zoomRoom";
|
internal const string MeetingNumber = "zoomRoom";
|
||||||
|
|
|
@ -96,10 +96,9 @@ namespace SafeExamBrowser.Proctoring
|
||||||
}
|
}
|
||||||
else if (settings.Zoom.Enabled)
|
else if (settings.Zoom.Enabled)
|
||||||
{
|
{
|
||||||
credentials.Add(new JProperty("apiKey", settings.Zoom.ApiKey));
|
|
||||||
credentials.Add(new JProperty("apiSecret", settings.Zoom.ApiSecret));
|
|
||||||
credentials.Add(new JProperty("meetingNumber", settings.Zoom.MeetingNumber));
|
credentials.Add(new JProperty("meetingNumber", settings.Zoom.MeetingNumber));
|
||||||
credentials.Add(new JProperty("password", settings.Zoom.Password));
|
credentials.Add(new JProperty("password", settings.Zoom.Password));
|
||||||
|
credentials.Add(new JProperty("sdkKey", settings.Zoom.SdkKey));
|
||||||
credentials.Add(new JProperty("signature", settings.Zoom.Signature));
|
credentials.Add(new JProperty("signature", settings.Zoom.Signature));
|
||||||
credentials.Add(new JProperty("userName", settings.Zoom.UserName));
|
credentials.Add(new JProperty("userName", settings.Zoom.UserName));
|
||||||
}
|
}
|
||||||
|
|
|
@ -103,8 +103,7 @@ namespace SafeExamBrowser.Proctoring
|
||||||
}
|
}
|
||||||
else if (settings.Zoom.Enabled)
|
else if (settings.Zoom.Enabled)
|
||||||
{
|
{
|
||||||
start = !string.IsNullOrWhiteSpace(settings.Zoom.ApiKey);
|
start = !string.IsNullOrWhiteSpace(settings.Zoom.SdkKey) && !string.IsNullOrWhiteSpace(settings.Zoom.Signature);
|
||||||
start &= !string.IsNullOrWhiteSpace(settings.Zoom.ApiSecret) || !string.IsNullOrWhiteSpace(settings.Zoom.Signature);
|
|
||||||
start &= !string.IsNullOrWhiteSpace(settings.Zoom.MeetingNumber);
|
start &= !string.IsNullOrWhiteSpace(settings.Zoom.MeetingNumber);
|
||||||
start &= !string.IsNullOrWhiteSpace(settings.Zoom.UserName);
|
start &= !string.IsNullOrWhiteSpace(settings.Zoom.UserName);
|
||||||
}
|
}
|
||||||
|
@ -168,9 +167,9 @@ namespace SafeExamBrowser.Proctoring
|
||||||
settings.JitsiMeet.ServerUrl = args.JitsiMeetServerUrl;
|
settings.JitsiMeet.ServerUrl = args.JitsiMeetServerUrl;
|
||||||
settings.JitsiMeet.Token = args.JitsiMeetToken;
|
settings.JitsiMeet.Token = args.JitsiMeetToken;
|
||||||
|
|
||||||
settings.Zoom.ApiKey = args.ZoomApiKey;
|
|
||||||
settings.Zoom.MeetingNumber = args.ZoomMeetingNumber;
|
settings.Zoom.MeetingNumber = args.ZoomMeetingNumber;
|
||||||
settings.Zoom.Password = args.ZoomPassword;
|
settings.Zoom.Password = args.ZoomPassword;
|
||||||
|
settings.Zoom.SdkKey = args.ZoomSdkKey;
|
||||||
settings.Zoom.Signature = args.ZoomSignature;
|
settings.Zoom.Signature = args.ZoomSignature;
|
||||||
settings.Zoom.Subject = args.ZoomSubject;
|
settings.Zoom.Subject = args.ZoomSubject;
|
||||||
settings.Zoom.UserName = args.ZoomUserName;
|
settings.Zoom.UserName = args.ZoomUserName;
|
||||||
|
@ -272,8 +271,8 @@ namespace SafeExamBrowser.Proctoring
|
||||||
Thread.Sleep(2000);
|
Thread.Sleep(2000);
|
||||||
|
|
||||||
window.Close();
|
window.Close();
|
||||||
control = default(ProctoringControl);
|
control = default;
|
||||||
window = default(IProctoringWindow);
|
window = default;
|
||||||
fileSystem.Delete(filePath);
|
fileSystem.Delete(filePath);
|
||||||
|
|
||||||
logger.Info("Stopped proctoring.");
|
logger.Info("Stopped proctoring.");
|
||||||
|
|
|
@ -1,167 +1,148 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.10.1/css/bootstrap.css" />
|
||||||
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.5.0/css/bootstrap.css" />
|
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.10.1/css/react-select.css" />
|
||||||
<link type="text/css" rel="stylesheet" href="https://source.zoom.us/2.5.0/css/react-select.css" />
|
<meta charset="utf-8" />
|
||||||
</head>
|
<meta http-equiv="origin-trial" content="" />
|
||||||
<body>
|
</head>
|
||||||
<script src="https://source.zoom.us/2.5.0/lib/vendor/react.min.js"></script>
|
<body>
|
||||||
<script src="https://source.zoom.us/2.5.0/lib/vendor/react-dom.min.js"></script>
|
<script src="https://source.zoom.us/2.10.1/lib/vendor/react.min.js"></script>
|
||||||
<script src="https://source.zoom.us/2.5.0/lib/vendor/redux.min.js"></script>
|
<script src="https://source.zoom.us/2.10.1/lib/vendor/react-dom.min.js"></script>
|
||||||
<script src="https://source.zoom.us/2.5.0/lib/vendor/redux-thunk.min.js"></script>
|
<script src="https://source.zoom.us/2.10.1/lib/vendor/redux.min.js"></script>
|
||||||
<script src="https://source.zoom.us/2.5.0/lib/vendor/lodash.min.js"></script>
|
<script src="https://source.zoom.us/2.10.1/lib/vendor/redux-thunk.min.js"></script>
|
||||||
<script src="https://source.zoom.us/zoom-meeting-2.5.0.min.js"></script>
|
<script src="https://source.zoom.us/2.10.1/lib/vendor/lodash.min.js"></script>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9/crypto-js.min.js"></script>
|
<script src="https://source.zoom.us/zoom-meeting-2.10.1.min.js"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var audioJoin = 0;
|
var audioJoin = 0;
|
||||||
var videoJoin = 0;
|
var videoJoin = 0;
|
||||||
var join = 0;
|
var join = 0;
|
||||||
|
|
||||||
function controlUserInterface(_) {
|
function controlUserInterface(_) {
|
||||||
var appSignal = document.getElementById('app-signal');
|
var appSignal = document.getElementById('app-signal');
|
||||||
var audioButton = document.getElementsByClassName('join-audio-by-voip__join-btn')[0];
|
var audioButton = document.getElementsByClassName('join-audio-by-voip__join-btn')[0];
|
||||||
var audioContainer = document.getElementsByClassName('join-audio-container')[0];
|
var audioContainer = document.getElementsByClassName('join-audio-container')[0];
|
||||||
var joinButton = document.getElementsByClassName('joinWindowBtn')[0];
|
var joinButton = document.getElementsByClassName('joinWindowBtn')[0];
|
||||||
var leave = document.getElementsByClassName('footer__leave-btn-container')[0];
|
var leave = document.getElementsByClassName('footer__leave-btn-container')[0];
|
||||||
var more = document.getElementsByClassName('more-button')[0];
|
var more = document.getElementsByClassName('more-button')[0];
|
||||||
var participantControls = document.getElementsByClassName('participants-item__buttons')[0];
|
var participantControls = document.getElementsByClassName('participants-item__buttons')[0];
|
||||||
var raiseHandContainer = document.getElementsByClassName('participants-section-container__participants-footer')[0];
|
var raiseHandContainer = document.getElementsByClassName('participants-section-container__participants-footer')[0];
|
||||||
var videoButton = document.getElementsByClassName('send-video-container__btn')[0];
|
var videoButton = document.getElementsByClassName('send-video-container__btn')[0];
|
||||||
var videoContainer = document.getElementsByClassName('send-video-container')[0];
|
var videoContainer = document.getElementsByClassName('send-video-container')[0];
|
||||||
|
|
||||||
if (appSignal) {
|
if (appSignal) {
|
||||||
appSignal.style.visibility = 'hidden';
|
appSignal.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioButton && !'%_AUDIO_MUTED_%' && audioJoin < 500) {
|
if (audioButton && !'%_AUDIO_MUTED_%' && audioJoin < 500) {
|
||||||
audioButton.click();
|
audioButton.click();
|
||||||
audioJoin++;
|
audioJoin++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (audioContainer && !'%_AUDIO_MUTED_%') {
|
if (audioContainer && !'%_AUDIO_MUTED_%') {
|
||||||
audioContainer.style.visibility = 'hidden';
|
audioContainer.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (joinButton && join < 500) {
|
if (joinButton && join < 500) {
|
||||||
joinButton.click();
|
joinButton.click();
|
||||||
join++;
|
join++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (leave) {
|
if (leave) {
|
||||||
leave.style.visibility = 'hidden';
|
leave.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (more) {
|
if (more) {
|
||||||
more.style.visibility = 'hidden';
|
more.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (participantControls) {
|
if (participantControls) {
|
||||||
participantControls.style.visibility = 'hidden';
|
participantControls.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (raiseHandContainer && !'%_ALLOW_RAISE_HAND_%') {
|
if (raiseHandContainer && !'%_ALLOW_RAISE_HAND_%') {
|
||||||
raiseHandContainer.style.visibility = 'hidden';
|
raiseHandContainer.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoButton && !'%_VIDEO_MUTED_%' && videoJoin < 500) {
|
if (videoButton && !'%_VIDEO_MUTED_%' && videoJoin < 500) {
|
||||||
videoButton.click();
|
videoButton.click();
|
||||||
videoJoin++;
|
videoJoin++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (videoContainer && !'%_VIDEO_MUTED_%') {
|
if (videoContainer && !'%_VIDEO_MUTED_%') {
|
||||||
videoContainer.style.visibility = 'hidden';
|
videoContainer.style.visibility = 'hidden';
|
||||||
}
|
}
|
||||||
|
|
||||||
requestAnimationFrame(controlUserInterface);
|
requestAnimationFrame(controlUserInterface);
|
||||||
}
|
}
|
||||||
|
|
||||||
function startMeeting(credentials) {
|
function startMeeting(credentials) {
|
||||||
const ATTENDEE = 0;
|
var error = function (res) {
|
||||||
var signature = credentials.signature;
|
alert(`Failed to initialize meeting: ${JSON.stringify(res)}`);
|
||||||
|
};
|
||||||
|
|
||||||
if (!ZoomMtg.checkSystemRequirements()) {
|
var success = function () {
|
||||||
alert('This system does not meet the necessary requirements for Zoom!');
|
requestAnimationFrame(controlUserInterface);
|
||||||
}
|
|
||||||
|
|
||||||
ZoomMtg.setZoomJSLib('https://source.zoom.us/2.5.0/lib', '/av');
|
ZoomMtg.join({
|
||||||
ZoomMtg.preLoadWasm();
|
meetingNumber: new Number(credentials.meetingNumber),
|
||||||
ZoomMtg.prepareJssdk();
|
passWord: credentials.password,
|
||||||
|
sdkKey: credentials.sdkKey,
|
||||||
|
signature: credentials.signature,
|
||||||
|
userName: credentials.userName,
|
||||||
|
error: function (res) {
|
||||||
|
alert(`Failed to join meeting: ${JSON.stringify(res)}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (!signature) {
|
var params = {
|
||||||
signature = ZoomMtg.generateSignature({
|
audioPanelAlwaysOpen: false,
|
||||||
meetingNumber: credentials.meetingNumber,
|
disableCallOut: true,
|
||||||
apiKey: credentials.apiKey,
|
disableInvite: true,
|
||||||
apiSecret: credentials.apiSecret,
|
disableJoinAudio: false,
|
||||||
role: ATTENDEE,
|
disableRecord: true,
|
||||||
error: function (res) {
|
disableReport: true,
|
||||||
alert(`Failed to generate signature: ${JSON.stringify(res)}`);
|
disableVoIP: false,
|
||||||
}
|
leaveUrl: 'doesnotexist',
|
||||||
});
|
isLockBottom: true,
|
||||||
}
|
isShowJoiningErrorDialog: true,
|
||||||
|
isSupportAV: true,
|
||||||
|
isSupportBreakout: false,
|
||||||
|
isSupportChat: '%_ALLOW_CHAT_%',
|
||||||
|
isSupportCC: '%_ALLOW_CLOSED_CAPTIONS_%',
|
||||||
|
isSupportPolling: false,
|
||||||
|
isSupportQA: false,
|
||||||
|
isSupportNonverbal: false,
|
||||||
|
screenShare: false,
|
||||||
|
sharingMode: 'both',
|
||||||
|
showMeetingHeader: true,
|
||||||
|
showPureSharingContent: false,
|
||||||
|
videoDrag: true,
|
||||||
|
videoHeader: true,
|
||||||
|
meetingInfo: ['topic', 'host', 'participant'],
|
||||||
|
error: error,
|
||||||
|
success: success
|
||||||
|
};
|
||||||
|
|
||||||
ZoomMtg.init({
|
if (!ZoomMtg.checkSystemRequirements()) {
|
||||||
audioPanelAlwaysOpen: false,
|
alert('This system does not meet the necessary requirements for Zoom!');
|
||||||
disableCallOut: true,
|
}
|
||||||
disableInvite: true,
|
|
||||||
disableJoinAudio: false,
|
|
||||||
disableRecord: true,
|
|
||||||
disableReport: true,
|
|
||||||
disableVoIP: false,
|
|
||||||
leaveUrl: 'doesnotexist',
|
|
||||||
isLockBottom: true,
|
|
||||||
isShowJoiningErrorDialog: true,
|
|
||||||
isSupportAV: true,
|
|
||||||
isSupportBreakout: false,
|
|
||||||
isSupportChat: '%_ALLOW_CHAT_%',
|
|
||||||
isSupportCC: '%_ALLOW_CLOSED_CAPTIONS_%',
|
|
||||||
isSupportPolling: false,
|
|
||||||
isSupportQA: false,
|
|
||||||
isSupportNonverbal: false,
|
|
||||||
screenShare: false,
|
|
||||||
sharingMode: 'both',
|
|
||||||
showMeetingHeader: true,
|
|
||||||
showPureSharingContent: false,
|
|
||||||
videoDrag: true,
|
|
||||||
videoHeader: true,
|
|
||||||
meetingInfo: [
|
|
||||||
'topic',
|
|
||||||
'host',
|
|
||||||
'participant',
|
|
||||||
//'mn',
|
|
||||||
//'pwd',
|
|
||||||
//'telPwd',
|
|
||||||
//'invite',
|
|
||||||
//'dc'
|
|
||||||
],
|
|
||||||
error: function (res) {
|
|
||||||
alert(`Failed to initialize meeting: ${JSON.stringify(res)}`);
|
|
||||||
},
|
|
||||||
success: function () {
|
|
||||||
requestAnimationFrame(controlUserInterface);
|
|
||||||
|
|
||||||
ZoomMtg.join({
|
ZoomMtg.setZoomJSLib('https://source.zoom.us/2.10.1/lib', '/av');
|
||||||
apiKey: credentials.apiKey,
|
ZoomMtg.preLoadWasm();
|
||||||
meetingNumber: credentials.meetingNumber,
|
ZoomMtg.prepareWebSDK();
|
||||||
passWord: credentials.password,
|
ZoomMtg.init(params);
|
||||||
signature: signature,
|
}
|
||||||
userName: credentials.userName,
|
|
||||||
error: function (res) {
|
|
||||||
alert(`Failed to join meeting: ${JSON.stringify(res)}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function webMessageReceived(args) {
|
function webMessageReceived(args) {
|
||||||
if ('credentials' in args.data) {
|
if ('credentials' in args.data) {
|
||||||
startMeeting(args.data.credentials);
|
startMeeting(args.data.credentials);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('unload', () => ZoomMtg.leaveMeeting({}));
|
window.addEventListener('unload', () => ZoomMtg.leaveMeeting({}));
|
||||||
window.chrome.webview.addEventListener('message', webMessageReceived);
|
window.chrome.webview.addEventListener('message', webMessageReceived);
|
||||||
window.chrome.webview.postMessage('credentials');
|
window.chrome.webview.postMessage('credentials');
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
|
@ -16,9 +16,9 @@ namespace SafeExamBrowser.Server.Contracts.Events
|
||||||
public string JitsiMeetRoomName { get; set; }
|
public string JitsiMeetRoomName { get; set; }
|
||||||
public string JitsiMeetServerUrl { get; set; }
|
public string JitsiMeetServerUrl { get; set; }
|
||||||
public string JitsiMeetToken { get; set; }
|
public string JitsiMeetToken { get; set; }
|
||||||
public string ZoomApiKey { get; set; }
|
|
||||||
public string ZoomMeetingNumber { get; set; }
|
public string ZoomMeetingNumber { get; set; }
|
||||||
public string ZoomPassword { get; set; }
|
public string ZoomPassword { get; set; }
|
||||||
|
public string ZoomSdkKey { get; set; }
|
||||||
public string ZoomSignature { get; set; }
|
public string ZoomSignature { get; set; }
|
||||||
public string ZoomSubject { get; set; }
|
public string ZoomSubject { get; set; }
|
||||||
public string ZoomUserName { get; set; }
|
public string ZoomUserName { get; set; }
|
||||||
|
|
|
@ -298,9 +298,9 @@ namespace SafeExamBrowser.Server
|
||||||
attributes.Instruction.JitsiMeetToken = attributesJson["jitsiMeetToken"].Value<string>();
|
attributes.Instruction.JitsiMeetToken = attributesJson["jitsiMeetToken"].Value<string>();
|
||||||
break;
|
break;
|
||||||
case "ZOOM":
|
case "ZOOM":
|
||||||
attributes.Instruction.ZoomApiKey = attributesJson["zoomAPIKey"].Value<string>();
|
|
||||||
attributes.Instruction.ZoomMeetingNumber = attributesJson["zoomRoom"].Value<string>();
|
attributes.Instruction.ZoomMeetingNumber = attributesJson["zoomRoom"].Value<string>();
|
||||||
attributes.Instruction.ZoomPassword = attributesJson["zoomMeetingKey"].Value<string>();
|
attributes.Instruction.ZoomPassword = attributesJson["zoomMeetingKey"].Value<string>();
|
||||||
|
attributes.Instruction.ZoomSdkKey = attributesJson["zoomAPIKey"].Value<string>();
|
||||||
attributes.Instruction.ZoomSignature = attributesJson["zoomToken"].Value<string>();
|
attributes.Instruction.ZoomSignature = attributesJson["zoomToken"].Value<string>();
|
||||||
attributes.Instruction.ZoomSubject = attributesJson["zoomSubject"].Value<string>();
|
attributes.Instruction.ZoomSubject = attributesJson["zoomSubject"].Value<string>();
|
||||||
attributes.Instruction.ZoomUserName = attributesJson["zoomUserName"].Value<string>();
|
attributes.Instruction.ZoomUserName = attributesJson["zoomUserName"].Value<string>();
|
||||||
|
|
|
@ -31,16 +31,6 @@ namespace SafeExamBrowser.Settings.Proctoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AllowRaiseHand { get; set; }
|
public bool AllowRaiseHand { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The API key to be used for authentication.
|
|
||||||
/// </summary>
|
|
||||||
public string ApiKey { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The API secret to be used for authentication.
|
|
||||||
/// </summary>
|
|
||||||
public string ApiSecret { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the audio starts muted.
|
/// Determines whether the audio starts muted.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -71,6 +61,11 @@ namespace SafeExamBrowser.Settings.Proctoring
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool ReceiveVideo { get; set; }
|
public bool ReceiveVideo { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The SDK key to be used for authentication.
|
||||||
|
/// </summary>
|
||||||
|
public string SdkKey { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Determines whether the audio stream of the user will be sent to the server.
|
/// Determines whether the audio stream of the user will be sent to the server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Add table
Reference in a new issue