//todo: move to companyLms/settings service? public static KeyValuePair <string, string> GetApiKeys(ILmsLicense lmsCompany, string globalAppId, string globalAppKey) { string appId = null; string appKey = null; var isSandbox = lmsCompany.GetSetting <bool>(LmsLicenseSettingNames.IsOAuthSandbox); if (isSandbox) { appId = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.OAuthAppId); appKey = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.OAuthAppKey); } else { appId = globalAppId; appKey = globalAppKey; } return(new KeyValuePair <string, string>(appId, appKey)); }
public void DeleteProfile(ILmsLicense lmsCompany, TelephonyProfileInfoResult profile) { if (lmsCompany == null) { throw new ArgumentNullException(nameof(lmsCompany)); } if (profile == null) { throw new ArgumentNullException(nameof(profile)); } string roomNumber = profile.TelephonyProfileFields.First(x => x.Key == "x-tel-meetingone-conference-id").Value; if (string.IsNullOrWhiteSpace(roomNumber)) { throw new InvalidOperationException("Can't find meeting-one room number"); } var access = new AccessDetails { UserName = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.UserName), SecretHashKey = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.SecretHashKey), OwningAccountNumber = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.OwningAccountNumber), }; bool deleted = false; try { var client = new MeetingOneClient(_baseAddress, _logger); deleted = client.DeleteRoom(access, roomNumber); } catch (Exception ex) { _logger.Error($"MeetingOneClient.DeleteRoom failed. RoomNumber:'{roomNumber}'. LmsCompanyId:{lmsCompany.Id}", ex); } if (!deleted) { throw new InvalidOperationException("MeetingONE API hasn't deleted room."); } }
public LmsCalendarEventServiceBase GetCalendarEventService(LmsProviderEnum lmsId, ILmsLicense lmsLicense) { switch (lmsId) { case LmsProviderEnum.Canvas: bool enableExportToCalendar = lmsLicense.GetSetting <bool>(LmsLicenseSettingNames.EnableCanvasExportToCalendar); if (!enableExportToCalendar) { return(null); } return(IoC.Resolve <LmsCalendarEventServiceBase>(lmsId + "CalendarService")); } return(null); }
public IEnumerable <TelephonyProfile> GetAudioProfiles(IAdobeConnectProxy provider, ILmsLicense lmsCompany, string principalId) { if (provider == null) { throw new ArgumentNullException(nameof(provider)); } if (lmsCompany == null) { throw new ArgumentNullException(nameof(lmsCompany)); } var usedAudioProfiles = lmsCompany.GetSetting <bool>(LmsLicenseSettingNames.AudioProfileUnique) ? _meetingModel.GetByCompanyWithAudioProfiles(lmsCompany).Select(x => x.AudioProfileId).ToList() : new List <string>(); var profiles = _innerService.GetAudioProfiles(provider, principalId) .Where(x => !usedAudioProfiles.Contains(x.ProfileId)).ToList(); return(profiles); }
public async Task SynchronizeUsers(ILmsLicense lmsCompany, bool syncACUsers, IEnumerable <int> meetingIds = null) { LmsUserServiceBase service = null; if ((LmsProviderEnum)lmsCompany.LmsProviderId == LmsProviderEnum.Brightspace) { service = IoC.Resolve <LmsUserServiceBase>(LmsProviderEnum.Brightspace.ToString() + "_Sync"); } else { service = lmsFactory.GetUserService((LmsProviderEnum)lmsCompany.LmsProviderId); } var acProvider = acAccountService.GetProvider(lmsCompany); var meetings = lmsCompany.LmsCourseMeetings.Where(x => meetingIds == null || meetingIds.Any(m => m == x.Id)).ToList(); var scoIds = new HashSet <string>(meetings.Select(x => x.GetMeetingScoId())).ToList(); var scos = acProvider.ReportBulkObjects(scoIds).Values; var settings = lmsCompany.Settings.ToList(); //to avoid nhibernate errors var groupedMeetings = meetings .Where(x => scos.Any(s => s.ScoId == x.ScoId)) .GroupBy(y => y.CourseId); List <LmsUser> users = lmsCompany.LmsUsers.ToList();//meetingIds == null ? lmsCompany.LmsUsers.ToList() : null; object localLockObject = new object(); Dictionary <string, IEnumerable <LmsUserDTO> > licenseUsers = new Dictionary <string, IEnumerable <LmsUserDTO> >(); // var input = meetings.Select(x => new Tuple<LmsCourseMeeting, string>(x, x.GetMeetingScoId())).ToList(); var timer = Stopwatch.StartNew(); //synchronous version //var parallelMode = ConfigurationManager.AppSettings["ParallelMode"]; //if (parallelMode == null || parallelMode != "1") //{ foreach (var groupedMeeting in groupedMeetings) { var courseId = groupedMeeting.Key; var opResult = await service.GetUsers(lmsCompany.GetLMSSettings(_settings), courseId); if (opResult.IsSuccess) { licenseUsers.Add(courseId, opResult.Data); } else { licenseUsers.Add(courseId, new List <LmsUserDTO>()); } } //} //parallel version //else //{ // Parallel.ForEach<int, Dictionary<int, IEnumerable<LmsUserDTO>>>( // groupedMeetings.Select(x => x.Key), // () => new Dictionary<int, IEnumerable<LmsUserDTO>>(), // (courseId, state, localDictionary) => // { // var opResult = service.GetUsers(lmsCompany, courseId); // if (opResult.IsSuccess) // { // localDictionary.Add(courseId, opResult.Data); // } // else // { // localDictionary.Add(courseId, new List<LmsUserDTO>()); // } // return localDictionary; // }, // (finalResult) => // { // lock (localLockObject) // foreach (var item in finalResult) // { // licenseUsers.Add(item.Key, item.Value); // } // } // ); //} timer.Stop(); logger.Warn($"Users from API elapsed seconds:{timer.Elapsed.ToString()}"); acProvider = acAccountService.GetProvider(lmsCompany); //users retrieve can take more than session timeout foreach (var courseGroup in groupedMeetings) { logger.InfoFormat("Retrieving users for LmsCompanyId={0}, LmsProvider={1}, CourseId={2}; MeetingIds:{3}", lmsCompany.Id, (LmsProviderEnum)lmsCompany.LmsProviderId, courseGroup.Key, String.Join(",", courseGroup.Select(x => x.Id))); try { //todo: set extra data param // var opResult = service.GetUsers(lmsCompany, lmsCompany.AdminUser, courseGroup.Key); // if (opResult.IsSuccess) // { var usersCount = licenseUsers[courseGroup.Key].Count(); if (usersCount == 0) { //todo: take all users (meeting.Users) and make foreach trying to retrieve logger.WarnFormat("Couldn't retrieve users from API for LmsCompanyId={0}, LmsProvider={1}, CourseId={2}", lmsCompany.Id, (LmsProviderEnum)lmsCompany.LmsProviderId, courseGroup.Key); } else if (usersCount > Core.Utils.Constants.SyncUsersCountLimit) { logger.WarnFormat("Course contains {0} users that is more than limit for users sync ({1}). LmsCompanyId={2}, LmsProvider={3}, CourseId={4}", usersCount, Core.Utils.Constants.SyncUsersCountLimit, lmsCompany.Id, (LmsProviderEnum)lmsCompany.LmsProviderId, courseGroup.Key); foreach (var meeting in courseGroup) { if (!meeting.EnableDynamicProvisioning) { meeting.EnableDynamicProvisioning = true; lmsCourseMeetingModel.RegisterSave(meeting, true); } } } else { var licenseUsersVar = licenseUsers[courseGroup.Key].ToList(); // var userIds = licenseUsersVar.Select(x => x.LtiId ?? x.Id); // logger.InfoFormat("API user ids: {0}", String.Join(",", userIds)); var existedDbUsers = users.Where(x => licenseUsersVar.Any(u => (u.LtiId ?? u.Id) == x.UserId)); //?? lmsUserModel.GetByUserIdAndCompanyLms(userIds.ToArray(), lmsCompany.Id); var existedUserIds = existedDbUsers.Select(x => x.Id).ToList(); var newUsers = UpdateDbUsers(licenseUsers[courseGroup.Key].ToList(), lmsCompany, users, acProvider); users.AddRange(newUsers); // merge results; foreach (var meeting in courseGroup) { if (lmsCompany.GetSetting <bool>(LmsLicenseSettingNames.UseCourseSections)) { licenseUsersVar = licenseUsers[courseGroup.Key].Where( x => x.SectionIds == null || x.SectionIds.Any(s => meeting.CourseSections.Any(cs => cs.LmsId == s))).ToList(); existedDbUsers = users.Where(x => licenseUsersVar.Any(u => (u.LtiId ?? u.Id) == x.UserId)); existedUserIds = existedDbUsers.Select(x => x.Id).ToList(); newUsers = new List <LmsUser>(); } //sync DB roles foreach (var dbRole in meeting.MeetingRoles) { var lmsUser = licenseUsersVar.FirstOrDefault(x => (x.LtiId ?? x.Id) == dbRole.User.UserId); if (lmsUser != null) { dbRole.LmsRole = lmsUser.LmsRole; } } var userRolesToDelete = meeting.MeetingRoles.Where(x => existedUserIds.All(u => u != x.User.Id)).ToList(); var usersToAddToMeeting = new List <LmsUser>(newUsers); usersToAddToMeeting.AddRange( existedDbUsers.Where( x => meeting.MeetingRoles.Select(mr => mr.User).All(u => u.Id != x.Id)).ToList()); if (userRolesToDelete.Any()) { logger.InfoFormat( "LmsUser ids to delete from meetingId={0}, courseId={1}: {2}", meeting.Id, meeting.CourseId, String.Join(", ", userRolesToDelete.Select(x => x.User.Id))); } if (usersToAddToMeeting.Any()) { logger.InfoFormat( "LmsUser ids to add to meetingId={0}, courseId={1}: {2}", meeting.Id, meeting.CourseId, String.Join(", ", usersToAddToMeeting.Select(x => x.UserId))); } userRolesToDelete.ForEach(x => meeting.MeetingRoles.Remove(x)); usersToAddToMeeting.ForEach(x => meeting.MeetingRoles.Add(new LmsUserMeetingRole { Meeting = meeting, User = x, LmsRole = licenseUsers[courseGroup.Key].First(dto => x.UserId == (dto.LtiId ?? dto.Id)) .LmsRole })); meeting.EnableDynamicProvisioning = false; lmsCourseMeetingModel.RegisterSave(meeting, true); // todo: optimize condition, probably refresh roles not for all users var dbPrincipalIds = new HashSet <string>( meeting.MeetingRoles.Where(x => x.User.PrincipalId != null).Select(x => x.User.PrincipalId)); List <MeetingPermissionInfo> enrollments = usersSetup.GetMeetingAttendees(acProvider, meeting.GetMeetingScoId()); var acPrincipalIds = new HashSet <string>(enrollments.Select(e => e.PrincipalId)); if (syncACUsers && (meeting.LmsMeetingType == (int)LmsMeetingType.Meeting || meeting.LmsMeetingType == (int)LmsMeetingType.VirtualClassroom || meeting.LmsMeetingType == (int)LmsMeetingType.Seminar) && (dbPrincipalIds.Count != meeting.MeetingRoles.Count || dbPrincipalIds.Count != acPrincipalIds.Count || dbPrincipalIds.Any(x => acPrincipalIds.All(p => p != x)))) { logger.InfoFormat("Synchronizing AC for meetingId={0}, courseId={1}", meeting.Id, meeting.CourseId); UpdateACRoles(lmsCompany, meeting, acProvider, enrollments); } } } // } } catch (Exception e) { var message = String.Format( $"Error happened when tried to update users for LmsCompany with id={lmsCompany.Id}, lmsCourseId={courseGroup.Key}"); logger.Error(message, e); } } }
public override async Task <(List <LmsUserDTO> users, string error)> GetUsersOldStyle(ILmsLicense lmsCompany, int courseId, LtiParamDTO param = null) { if (lmsCompany == null) { throw new ArgumentNullException(nameof(lmsCompany)); } //var course = _restApiClient.GetRestCall<RootObject>(lmsCompany.AdminUser.Username, // lmsCompany.AdminUser.Password, // $"courses/{courseId}/sections").Result; string clientId = lmsCompany.GetSetting <string>(LmsCompanySettingNames.SchoologyConsumerKey); string clientSecret = lmsCompany.GetSetting <string>(LmsCompanySettingNames.SchoologyConsumerSecret); var section = await _restApiClient.GetRestCall <Section>(clientId, clientSecret, $"sections/{courseId}"); List <Enrollment> enrollments = new List <Enrollment>(); RootObject2 enrollmentCallResult; int startPage = 0; int pageSize = 20; do { enrollmentCallResult = await _restApiClient.GetRestCall <RootObject2>(clientId, clientSecret, $"sections/{section.id}/enrollments?start={startPage}&limit={pageSize}"); enrollments.AddRange(enrollmentCallResult.enrollment); startPage += pageSize; } while (enrollments.Count < Int32.Parse(enrollmentCallResult.total)); //https://developers.schoology.com/api-documentation/rest-api-v1/enrollment //status 5: Archived (Course specific status members can be placed in before being fully unenrolled) enrollments = enrollments.Distinct().Where(e => e.status != "5").ToList(); var enrolledUserTasks = enrollments.GroupBy(u => u.uid).Select(g => g.First()).Select(enrollment => { var usr = new SchoologyRestApiClient().GetRestCall <User>(clientId, clientSecret, $"users/{enrollment.uid}"); return(usr.ContinueWith(x => { var u = x.Result; u.admin = enrollment.admin; return u; })); }); var enrolledUsers = await Task.WhenAll(enrolledUserTasks); var users = enrolledUsers .GroupBy(u => u.uid) .Select(g => g.First()) .Select(x => new LmsUserDTO { Id = x.uid, Login = string.IsNullOrWhiteSpace(x.username) ? x.primary_email : x.username, // TODO: middle name Name = x.name_first + " " + x.name_last, Email = x.primary_email, LmsRole = x.admin == 1 ? "Teacher" : "Student", PrimaryEmail = x.primary_email, }) .ToList(); return(users, null); }
public TelephonyProfile CreateProfile(ILmsLicense lmsCompany, ILtiParam param, string profileName, IAdobeConnectProxy acProxy) { if (lmsCompany == null) { throw new ArgumentNullException(nameof(lmsCompany)); } if (param == null) { throw new ArgumentNullException(nameof(param)); } if (string.IsNullOrWhiteSpace(profileName)) { throw new ArgumentException("Non-empty value expected", nameof(profileName)); } if (acProxy == null) { throw new ArgumentNullException(nameof(acProxy)); } try { var profiles = acProxy.TelephonyProviderList(null); var meetingOne = profiles.Values.FirstOrDefault(x => x.ClassName == ClassName); string providerId = meetingOne.ProviderId; if (meetingOne.ProviderStatus != "enabled") { throw new InvalidOperationException("MeetingOne provider is not enabled"); } var access = new AccessDetails { UserName = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.UserName), SecretHashKey = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.SecretHashKey), OwningAccountNumber = lmsCompany.GetSetting <string>(LmsLicenseSettingNames.Telephony.MeetingOne.OwningAccountNumber), }; var room = new RoomDto { Host = new Host { Email = param.lis_person_contact_email_primary, FirstName = param.PersonNameGiven, LastName = param.PersonNameFamily, MailingAddress = param.lis_person_contact_email_primary, }, RoomSettings = new RoomSettings { DialoutEnabled = true, AllowDomesticDialouts = true, AllowInternationalDialouts = true, }, }; // TODO: DI RoomDto result = null; try { var client = new MeetingOneClient(_baseAddress, _logger); result = client.CreateRoom(access, room); } catch (Exception ex) { _logger.Error("MeetingOneClient.CreateRoomAsync failed.", ex); return(null); } var acProfile = new TelephonyProfileUpdateItem { ProfileName = profileName, // ProfileStatus = "enabled", ProviderId = providerId, ProviderFields = new MeetingOneProviderFields { ConferenceId = result.Number, HostPin = result.HostPIN, }, }; TelephonyProfileInfoResult createdProfile = acProxy.TelephonyProfileUpdate(acProfile, false); return(createdProfile.TelephonyProfile); } catch (Exception ex) { _logger.Error($"CreateProfileAsync error. CompanyLicenseId: {lmsCompany.Id}.", ex); throw; } }