Beispiel #1
0
        //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));
        }
Beispiel #2
0
        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.");
            }
        }
Beispiel #3
0
        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);
        }
Beispiel #4
0
        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);
        }
Beispiel #5
0
        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);
                }
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
        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;
            }
        }