public static async Task <string> GetUsersWithDelta(GraphServiceClient client, string deltaLink, ITargetBlock <User> target, CancellationToken token)
        {
            IUserDeltaCollectionPage page = new UserDeltaCollectionPage();

            page.InitializeNextPageRequest(client, deltaLink);
            return(await GraphHelperUsers.GetUsersWithDelta(page, target, token));
        }
        public static IEnumerable <User> UsersDeltaQueryEfficient(RequestManager requestManager)
        {
            // Step 1: make a request to get the latest delta token, without returning any results. The goal is to obtain the current token, and later download the current resource state - efficiently
            string latestDeltaTokenUrl = $"{requestManager.GraphClient.BaseUrl}/users/delta?$deltaToken=latest";
            var    page = new UserDeltaCollectionPage();

            page.InitializeNextPageRequest(requestManager.GraphClient, latestDeltaTokenUrl);
            var emptyPage         = page.NextPageRequest.GetAsync().Result;
            var firstDeltaRequest = GetNextDeltaRequest(emptyPage, requestManager.GraphClient);

            // Step 2: download the current state of the User collection, efficiently
            var currentStateDict = UserScenarios.GetAllUsers(requestManager).ToDictionary(u => u.Id);

            // Step 3: pick up delta changes since before we downloaded the current state
            var changesSinceCurrentState = ExecuteDeltaCycle(firstDeltaRequest);

            // Step 4: merge changes into current state
            foreach (var change in changesSinceCurrentState)
            {
                currentStateDict[change.Id] = change;
            }

            // Step 5: we now have current state, get the delta link for future changes
            var deltaRequest = GetNextDeltaRequest(changesSinceCurrentState, requestManager.GraphClient);

            return(WaitForDeltaChanges(deltaRequest));
        }
        private static IUserDeltaCollectionPage ExecuteDeltaCycle(IUserDeltaRequest request)
        {
            IUserDeltaCollectionPage currentUserState = new UserDeltaCollectionPage();
            IUserDeltaCollectionPage currentPage;

            do
            {
                currentPage = request.GetAsync().Result;
                foreach (var user in currentPage)
                {
                    currentUserState.Add(user);
                }
                request = currentPage.NextPageRequest;
            } while (request != null);
            currentUserState.AdditionalData = currentPage.AdditionalData;
            return(currentUserState);
        }
        /// <inheritdoc/>
        public async Task <(IEnumerable <User>, string)> GetAllUsersAsync(string deltaLink = null)
        {
            var users = new List <User>();
            IUserDeltaCollectionPage collectionPage;

            if (string.IsNullOrEmpty(deltaLink))
            {
                collectionPage = await this.graphServiceClient
                                 .Users
                                 .Delta()
                                 .Request()
                                 .Select("id, displayName, userPrincipalName, userType")
                                 .Top(GraphConstants.MaxPageSize)
                                 .WithMaxRetry(GraphConstants.MaxRetry)
                                 .GetAsync();
            }
            else
            {
                collectionPage = new UserDeltaCollectionPage();
                collectionPage.InitializeNextPageRequest(this.graphServiceClient, deltaLink);
                collectionPage = await collectionPage
                                 .NextPageRequest
                                 .WithMaxRetry(GraphConstants.MaxRetry)
                                 .GetAsync();
            }

            users.AddRange(collectionPage);

            while (collectionPage.NextPageRequest != null)
            {
                collectionPage = await collectionPage
                                 .NextPageRequest
                                 .WithMaxRetry(GraphConstants.MaxRetry)
                                 .GetAsync();

                users.AddRange(collectionPage);
            }

            collectionPage.AdditionalData.TryGetValue("@odata.deltaLink", out object delta);

            return(users, delta as string);
        }
        public static async Task <List <string> > GetUsersAsync(GraphServiceClient graphClient, HttpContext httpContext)
        {
            IUserDeltaCollectionPage userPage = new UserDeltaCollectionPage();

            userPage.InitializeNextPageRequest(
                graphClient,
                graphClient.
                Users.
                Delta().
                Request().
                Select("Id,displayName,userPrincipalName,mail").
                RequestUrl);

            var pageRequestCount = 0;
            var userIds          = new List <string>();

            do
            {
                userPage = await userPage.NextPageRequest.GetAsync(CancellationToken.None);

                userPage
                .Where(_ => _.DisplayName != null)
                .ForEach(_ =>
                {
                    if (Startup.IsCosmosDbGraphEnabled)
                    {
                        CosmosDbGraphHelper.Users(_);
                        userIds.Add(_.Id);
                    }
                });

                pageRequestCount++;
            }while (userPage.NextPageRequest != null && pageRequestCount < _maxPageRequestsPerTenant);

            return(userIds);
        }
Beispiel #6
0
        public static async Task Run([TimerTrigger("0 */10 * * * *")] TimerInfo timer, ILogger log)
        {
            // アプリケーション設定を取得します
            var appConfig         = new ConfigurationBuilder().AddEnvironmentVariables().Build();
            var graphTenantId     = appConfig.GetValue <string>("GraphTenantId");
            var graphAuthority    = appConfig.GetValue <string>("GraphAuthority");
            var graphClientId     = appConfig.GetValue <string>("GraphClientId");
            var graphClientSecret = appConfig.GetValue <string>("GraphClientSecret");
            var graphRedirectUrl  = appConfig.GetValue <string>("GraphRedirectUrl");
            var graphScope        = appConfig.GetValue <string>("GraphScope");
            var blobStorage       = appConfig.GetValue <string>("BlobStorage");
            var blobContainerName = appConfig.GetValue <string>("BlobContainerName");
            var blobFileName      = appConfig.GetValue <string>("BlobFileName");
            var teamsGroupId      = appConfig.GetValue <string>("TeamsGroupId");
            var eventSenderId     = appConfig.GetValue <string>("EventSenderId");

            try
            {
                // OAuth の Access Token を取得します
                var clientCredential  = new ClientCredential(graphClientSecret);
                var clientApplication = new ConfidentialClientApplication(
                    graphClientId,
                    graphAuthority + "/" + graphTenantId,
                    graphRedirectUrl,
                    clientCredential,
                    null,
                    null);
                var authenticationResult = await clientApplication.AcquireTokenForClientAsync(graphScope.Split(", "));

                // Microsoft Graph Service Client を初期化します
                var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async msg =>
                {
                    await Task.Run(() =>
                    {
                        msg.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authenticationResult.AccessToken);
                    });
                }));

                // BLOB ストレージにファイルが存在するかどうかを確認します
                var storageAccount = CloudStorageAccount.Parse(blobStorage);
                var blobClient     = storageAccount.CreateCloudBlobClient();
                var blobContainer  = blobClient.GetContainerReference(blobContainerName);
                var blobFile       = blobContainer.GetBlockBlobReference(blobFileName);

                var userDeltaCollectionPage = default(IUserDeltaCollectionPage);
                if (await blobFile.ExistsAsync())
                {
                    // ファイルがある場合、前回からの差分のユーザーを取得します
                    userDeltaCollectionPage = new UserDeltaCollectionPage();
                    userDeltaCollectionPage.InitializeNextPageRequest(graphClient, await blobFile.DownloadTextAsync());
                    userDeltaCollectionPage = await userDeltaCollectionPage.NextPageRequest.GetAsync();
                }
                else
                {
                    // ファイルがない場合、すべての差分を取得します
                    userDeltaCollectionPage = await graphClient.Users.Delta().Request().GetAsync();
                }

                // ページングして対象のユーザーのみをフィルターします
                var targetUsers = new List <User>();
                while (true)
                {
                    foreach (var user in userDeltaCollectionPage)
                    {
                        // 削除済みユーザーを除外します
                        if (user.AdditionalData?.ContainsKey("@removed") != true)
                        {
                            // ライセンスのないユーザーを除外します
                            var licenseDetails = await graphClient.Users[user.Id].LicenseDetails.Request().GetAsync();
                            var servicePlans   = licenseDetails.SelectMany(ld => ld.ServicePlans).ToList();
                            if (servicePlans.Any(sp => sp.ServicePlanId == TeamsServicePlanId) &&
                                servicePlans.Any(sp => sp.ServicePlanId == ExchangeStandardServicePlanId ||
                                                 sp.ServicePlanId == ExchangeEnterpriseServicePlanId))
                            {
                                targetUsers.Add(user);
                            }
                        }
                    }

                    // 次のページがない場合は処理を抜けます
                    if (userDeltaCollectionPage.NextPageRequest == null)
                    {
                        break;
                    }
                    // 次のページを取得します
                    userDeltaCollectionPage = await userDeltaCollectionPage.NextPageRequest.GetAsync();
                }

                // ユーザーを Teams のメンバーとして追加します
                foreach (var user in targetUsers)
                {
                    try
                    {
                        await graphClient.Groups[teamsGroupId].Members.References.Request().AddAsync(user);
                    }
                    catch (Exception)
                    {
                        // 追加済みの場合があるためエラーは無視します
                    }
                }

                // ユーザーに会議出席依頼を送付します
                if (targetUsers.Any())
                {
                    await graphClient.Users[eventSenderId].Events.Request().AddAsync(new Event()
                    {
                        Attendees = targetUsers.Select(user => new Attendee()
                        {
                            EmailAddress = new EmailAddress()
                            {
                                Address = user.Mail,
                                Name    = user.DisplayName
                            },
                            Type = AttendeeType.Required
                        }),
                        Subject = "新入社員向け説明会",
                        Body    = new ItemBody()
                        {
                            ContentType = BodyType.Html,
                            Content     = "<p>お疲れさまです。</p>"
                                          + "<p>新入社員向け説明会を開催しますのでご参集ください。</p>"
                                          + "<p>よろしくお願いします。</p>",
                        },
                        Start = new DateTimeTimeZone()
                        {
                            DateTime = DateTime.Today.AddDays(2).AddHours(9).ToString("s"),
                            TimeZone = "Tokyo Standard Time"
                        },
                        End = new DateTimeTimeZone()
                        {
                            DateTime = DateTime.Today.AddDays(2).AddHours(18).ToString("s"),
                            TimeZone = "Tokyo Standard Time"
                        },
                    });
                }

                // deltaLink を BLOB ストレージに保存します
                if (userDeltaCollectionPage.AdditionalData.TryGetValue("@odata.deltaLink", out var deltaLink))
                {
                    await blobContainer.CreateIfNotExistsAsync();

                    await blobFile.UploadTextAsync(deltaLink.ToString());
                }
            }
            catch (Exception ex)
            {
                log.LogError(ex.ToString());
            }
        }