public static async Task Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            var storage               = CloudStorageAccount.Parse(StorageAccount);
            var cloudTableClient      = storage.CreateCloudTableClient();
            var groupsStatisticsTable = cloudTableClient.GetTableReference("groupsstatistics");
            var groupsOwnersTable     = cloudTableClient.GetTableReference("groupowners");
            var groupsGuestsTable     = cloudTableClient.GetTableReference("groupguests");
            await groupsStatisticsTable.CreateIfNotExistsAsync().ConfigureAwait(false);

            await groupsOwnersTable.CreateIfNotExistsAsync().ConfigureAwait(false);

            await groupsGuestsTable.CreateIfNotExistsAsync().ConfigureAwait(false);

            // Get a Bearer Token with the App
            var    httpClient = new HttpClient();
            string token;

            try
            {
                var app = ConfidentialClientApplicationBuilder.Create(AppId)
                          .WithAuthority($"https://login.windows.net/{TenantId}/oauth2/token")
                          .WithRedirectUri("https://governance365function")
                          .WithClientSecret(AppSecret)
                          .Build();

                var authenticationProvider = new MsalAuthenticationProvider(app, Scopes);
                token = authenticationProvider.GetTokenAsync().Result;
                httpClient.DefaultRequestHeaders.Authorization =
                    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
            }
            catch (Exception)
            {
                throw;
            }

            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

            JObject groupsPageJson = null;

            do
            {
                if (string.IsNullOrEmpty(groupsPageJson?["@odata.nextLink"]?.ToString()))
                {
                    // first group page
                    groupsPageJson = JObject.Parse(await(await httpClient.GetAsync(groupsUrl + groupsSelection).ConfigureAwait(false)).Content.ReadAsStringAsync().ConfigureAwait(false));
                }
                else
                {
                    // next group page
                    groupsPageJson = JObject.Parse(await(await httpClient.GetAsync(groupsPageJson?["@odata.nextLink"]?.ToString()).ConfigureAwait(false)).Content.ReadAsStringAsync().ConfigureAwait(false));
                }
                if (!(groupsPageJson["value"] is JArray groupsPage))
                {
                    continue;
                }

                // Batch operation to store pages of groups in Azure table storage
                var groupPageBatchOperation = new TableBatchOperation();
                foreach (var group in groupsPage)
                {
                    var memberCount = 0;
                    var ownerCount  = 0;
                    var guestCount  = 0;

                    #region PROCESS GROUP TYPE AND DYNAMIC MEMBERSHIP

                    var groupType         = string.Empty;
                    var dynamicMemberShip = false;
                    var yammerProvisionedOffice365Group = false;

                    foreach (var type in (JArray)group["groupTypes"])
                    {
                        if (type.ToString().Equals("Unified"))
                        {
                            if (group["resourceProvisioningOptions"].ToString().Contains("Team"))
                            {
                                groupType = "Team";
                            }
                            else
                            {
                                groupType = "Office365 Group";
                            }

                            if (group["creationOptions"].ToString().Contains("YammerProvisioning"))
                            {
                                yammerProvisionedOffice365Group = true;
                            }
                        }

                        if (type.ToString().Equals("DynamicMembership"))
                        {
                            dynamicMemberShip = true;
                        }
                    }

                    if (groupType.Equals(string.Empty))
                    {
                        if (!group["mailEnabled"].ToString().ToLower().Equals("true"))
                        {
                            groupType = "Security Group";
                        }
                        else
                        {
                            if (!group["securityEnabled"].ToString().ToLower().Equals("true"))
                            {
                                groupType = "Distribution Group";
                            }
                            else
                            {
                                groupType = "Mail-enabled Security Group";
                            }
                        }
                    }
                    #endregion

                    const string groupMemberSelection = "?$select=id,userPrincipalName,displayName,userType,accountEnabled";
                    var          groupMembersUrl      = $"https://graph.microsoft.com/v1.0/groups/{group["id"]?.ToString()}/members{groupMemberSelection}";
                    var          groupOwnersUrl       = $"https://graph.microsoft.com/v1.0/groups/{group["id"]?.ToString()}/owners{groupMemberSelection}";

                    #region PROCESS GROUP MEMBERS AND GUESTS

                    var processMemberPageResult = await ProcessGroupMemberPageAsync(groupMembersUrl, group, httpClient, groupsGuestsTable, groupsOwnersTable, false).ConfigureAwait(false);

                    memberCount += processMemberPageResult.MemberCount;
                    guestCount  += processMemberPageResult.GuestCount;

                    while (processMemberPageResult.NextLink != null)
                    {
                        processMemberPageResult = await ProcessGroupMemberPageAsync(processMemberPageResult.NextLink, group, httpClient, groupsGuestsTable, groupsOwnersTable, false).ConfigureAwait(false);

                        memberCount += processMemberPageResult.MemberCount;
                        guestCount  += processMemberPageResult.GuestCount;
                    }
                    #endregion

                    #region PROCESS GROUP OWNERS

                    var processOwnerPageResult = await ProcessGroupMemberPageAsync(groupOwnersUrl, group, httpClient, groupsGuestsTable, groupsOwnersTable, true).ConfigureAwait(false);

                    ownerCount += processOwnerPageResult.OwnerCount;
                    while (processOwnerPageResult.NextLink != null)
                    {
                        processOwnerPageResult = await ProcessGroupMemberPageAsync(processOwnerPageResult.NextLink, group, httpClient, groupsGuestsTable, groupsOwnersTable, true).ConfigureAwait(false);

                        ownerCount += processOwnerPageResult.OwnerCount;
                    }
                    #endregion

                    var groupStatisticsEntity = new GroupStatisticsItemTableEntity()
                    {
                        PartitionKey    = "group",
                        RowKey          = group["id"]?.ToString(),
                        Classification  = group["classification"]?.ToString(),
                        CreatedDateTime = group["createdDateTime"] != null &&
                                          !group["createdDateTime"].ToString().Equals(string.Empty)
                                ? DateTimeOffset.Parse(group["createdDateTime"].ToString())
                                : (DateTimeOffset?)null,
                        DeletedDateTime = group["deletedDateTime"] != null &&
                                          !group["deletedDateTime"].ToString().Equals(string.Empty)
                                ? DateTimeOffset.Parse(group["deletedDateTime"].ToString())
                                : (DateTimeOffset?)null,
                        Description       = group["description"]?.ToString(),
                        DisplayName       = group["displayName"]?.ToString(),
                        GroupType         = groupType,
                        DynamicMembership = dynamicMemberShip,
                        Id                    = group["id"]?.ToString(),
                        Mail                  = group["mail"]?.ToString(),
                        MailEnabled           = group["mailEnabled"]?.ToString(),
                        MailNickname          = group["mailNickname"]?.ToString(),
                        OnPremisesSyncEnabled = group["onPremisesSyncEnabled"]?.ToString(),
                        RenewedDateTime       = group["renewedDateTime"] != null &
                                                !group["renewedDateTime"].ToString().Equals(string.Empty)
                                ? DateTimeOffset.Parse(group["renewedDateTime"].ToString())
                                : (DateTimeOffset?)null,
                        SecurityEnabled = group["securityEnabled"]?.ToString(),
                        Visibility      = group["visibility"]?.ToString(),
                        Guests          = guestCount,
                        Owners          = ownerCount,
                        Members         = memberCount
                    };
                    groupPageBatchOperation.Add(TableOperation.InsertOrReplace(groupStatisticsEntity));
                }
                await groupsStatisticsTable.ExecuteBatchAsync(groupPageBatchOperation).ConfigureAwait(false);
            } while (!string.IsNullOrEmpty(groupsPageJson["@odata.nextLink"]?.ToString()));
            httpClient.Dispose();
        }
Example #2
0
        public static async Task Run(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
            ILogger log)
        {
            var storage             = CloudStorageAccount.Parse(StorageAccount);
            var cloudTableClient    = storage.CreateCloudTableClient();
            var usersTable          = cloudTableClient.GetTableReference("users");
            var userStatisticsTable = cloudTableClient.GetTableReference("userstatistics");
            await usersTable.CreateIfNotExistsAsync().ConfigureAwait(false);

            await userStatisticsTable.CreateIfNotExistsAsync().ConfigureAwait(false);

            // Get a Bearer Token with the App
            var    httpClient = new HttpClient();
            string token;

            try
            {
                var app = ConfidentialClientApplicationBuilder.Create(AppId)
                          .WithAuthority($"https://login.windows.net/{TenantId}/oauth2/token")
                          .WithRedirectUri("https://governance365function")
                          .WithClientSecret(AppSecret)
                          .Build();

                var authenticationProvider = new MsalAuthenticationProvider(app, Scopes);
                token = authenticationProvider.GetTokenAsync().Result;
                httpClient.DefaultRequestHeaders.Authorization =
                    new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
            }
            catch (Exception)
            {
                throw;
            }

            httpClient.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);

            //initialize object for storing all user statistics
            UserQueryObject usersPage      = null;
            var             userStatistics = new UserStatisticsTableEntity()
            {
                PartitionKey     = "userstatistics",
                RowKey           = TenantId,
                DeactivatedUsers = 0,
                DeletedUsers     = 0,
                GuestUsers       = 0,
                InternalUsers    = 0,
                Users            = 0
            };

            //get all users (until nextlinnk is empty) and members/guests + sum up statistics
            do
            {
                if (string.IsNullOrEmpty(usersPage?.OdataNextLink?.ToString()))
                {
                    //first request
                    usersPage = JsonConvert.DeserializeObject <Governance365.Models.UserQueryObject>(await(await httpClient.GetAsync(usersUrl + UserSelectedProperties).ConfigureAwait(false)).Content.ReadAsStringAsync().ConfigureAwait(false));
                }
                else
                {
                    //next page request
                    usersPage = JsonConvert.DeserializeObject <Governance365.Models.UserQueryObject>(await(await httpClient.GetAsync(usersPage?.OdataNextLink?.ToString()).ConfigureAwait(false)).Content.ReadAsStringAsync().ConfigureAwait(false));
                }

                //batch request to store pages of users in Azure storage
                var userPageBatchOperation = new TableBatchOperation();
                foreach (var user in usersPage.Value)
                {
                    if (user.UserType != null)
                    {
                        userStatistics.Users++;
                        if (user.UserType.Equals("Member"))
                        {
                            userStatistics.InternalUsers++;
                        }
                        else if (user.UserType.Equals("Guest"))
                        {
                            userStatistics.GuestUsers++;
                        }
                        if (string.IsNullOrEmpty(user.AccountEnabled) && !bool.Parse(user.AccountEnabled))
                        {
                            userStatistics.DeactivatedUsers++;
                        }
                    }
                    user.PartitionKey = "user";
                    user.RowKey       = user.Id.ToString();
                    //add user entity to batch operation
                    userPageBatchOperation.Add(TableOperation.InsertOrReplace(user));
                }
                //write user page to Azure tabel storage
                await usersTable.ExecuteBatchAsync(userPageBatchOperation).ConfigureAwait(false);
            } while (!string.IsNullOrEmpty(usersPage.OdataNextLink?.ToString()));

            //write user statistics to table "userstatistics" -> single value with overwrite
            var insertUserStatisticsOperation = TableOperation.InsertOrReplace(userStatistics);
            await userStatisticsTable.ExecuteAsync(insertUserStatisticsOperation).ConfigureAwait(false);

            httpClient.Dispose();
        }