public static IEnumerable <OperationResult <User> > DeleteAllUsers(RequestManager requestManager)
        {
            throw new NotImplementedException("You do not want to execute this by accident!");
            // Step 1: start downloading user objects using partitioning
            // This will return users as they become available from concurrent response handlers
            IEnumerable <User> users;

            using (var builder = GraphRequestBuilder <User> .GetBuilder <UserCollectionResponseHandler>(requestManager, out users))
            {
                foreach (var filter in GenericHelpers.GenerateFilterRangesForAlphaNumProperties("userPrincipalName"))
                {
                    builder.Users.Request().Select("id, userPrincipalName").Top(999).Filter(filter).GetAsync().Wait();
                }
            }
            IEnumerable <OperationResult <User> > results;

            using (var builder = GraphRequestBuilder <User> .GetBuilderForSingleOperation(requestManager, out results))
            {
                foreach (var user in users.Where(u => !u.Id.Equals("383d113a-4967-41a4-9d98-3dc9c255db2b", StringComparison.OrdinalIgnoreCase)))
                {
                    if (!user.UserPrincipalName.EndsWith("petersgraphtest.onmicrosoft.com", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new NotImplementedException("You do not want to execute this by accident!");
                    }
                    builder.Users[user.Id].Request().ReturnNoContent().DeleteAsync().Wait();
                }
            }
            return(results);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Get all users in the organization, as fast as possible.
        /// </summary>
        /// <param name="requestManager">You can modify batchSize and concurrencyLevel in requestManager to change how requests are sent.
        /// Currently, it turns out that setting batchSize to 1 (essentially disabling batching), combined with a high concurrencyLevel (say 16),
        /// results in best performance for GET operations
        /// </param>
        /// <remarks>
        /// Graph permissions required:
        /// https://developer.microsoft.com/en-us/graph/docs/api-reference/v1.0/api/user_list
        /// </remarks>
        /// <returns></returns>
        public static IEnumerable <User> GetAllUsers(RequestManager requestManager)
        {
            // This collection will be populated with results as they become available. RequestManager executes requests in the background and asynchronously
            // adds them to this collection. The users are added to the collection immediately after they are returned and can be consumed via enumeration.
            // The underlying collection will block enumeration until the RequestManager is done processing all queued results
            IEnumerable <User> users;

            // The builder allows us to construct requests using standard Graph SDK syntax. However, instead of sending the requests it queues them with the RequestManager
            // for later execution in the background. The manager may batch multiple requests together for better performance.
            using (var builder = GraphRequestBuilder <User> .GetBuilder <UserCollectionResponseHandler>(requestManager, out users))
            {
                // We use filters to partition the large user collection into individual "streams". Graph supports efficient, indexed, queries on userPrinicpal name, so we use that property.
                foreach (var filter in GenericHelpers.GenerateFilterRangesForAlphaNumProperties("userPrincipalName"))
                {
                    // This is standard syntax of the Graph SDK. We "pretend" to send the request and wait for it, but in reality the GraphRequestBuilder class does not execute the request here.
                    // Instead, it queues it up with the RequestManager for background execution. The reason we call GetAsync().Wait() is to force the code internal to the Graph SDK
                    // to fully execute and build the final request.
                    // The Top() expression is used to maximize the size of each result page. 999 is the maximum size for the User collection.
                    // Other query parameters could be added here, too, for example we could use Select() to control which properties will be returned.
                    builder.Users.Request().Top(999).Filter(filter).GetAsync().Wait();

                    // Note that with normal SDK usage the above call would only give us the first page of results.
                    // However, this particular builder is specialized to handling collections. The internal response handler will receive the first page and automatically
                    // queue up another request (internally) until all pages are retrieved.
                }
            }
            // Note that at this point we have not fully fetched all results. This collection can be enumerated and will block if more results are incoming.
            // E.g. you could say users.ToArray() to wait for all results, or use foreach and gradually process results as they become available.
            return(users);
        }
        /// <summary>
        /// Gets all groups in the tenant, with all their members.
        /// Today, Graph's $expand parameter cannot be used to download all members in a group, it just gets the top N members.
        /// The approach taken here is to download group objects first (which do not contain members), and then get all members of each group.
        /// We can optimize this futher by parallelizing requests to get groups with requests to get members - this way we don't have to wait
        /// for all groups to download before we start fetching members.
        /// </summary>
        /// <returns></returns>
        public static IEnumerable <Group> GetAllGroupsWithMembers(RequestManager requestManager)
        {
            // Step 1: start downloading group objects using partitioning

            // This collection will be gradually populated with group objects, as they are fetched in the background by RequestManager
            IEnumerable <Group> groups;

            using (var builder = GraphRequestBuilder <Group> .GetBuilder <GroupCollectionResponseHandler>(requestManager, out groups))
            {
                // We use filters to split the group collection into streams. Graph supports indexed queries on the mailNickname property so we can use that.
                // This is useful if the tenat contains many groups.
                foreach (var filter in GenericHelpers.GenerateFilterRangesForAlphaNumProperties("mailNickname"))
                {
                    // This is standard syntax of the Graph SDK. We "pretend" to send the request and wait for it, but in reality the GraphRequestBuilder class does not execute the request here.
                    // Instead, it queues it up with the RequestManager for background execution. The reason we call GetAsync().Wait() is to force the code internal to the Graph SDK
                    // to fully execute and build the final request.
                    // The Top() expression is used to maximize the size of each result page. 999 is the maximum size for the Group collection.
                    // Other query parameters could be added here, too, for example we could use Select() to control which properties will be returned.
                    builder.Groups.Request().Top(999).Filter(filter).GetAsync().Wait();
                }
            }

            // Step 2: start downloading group members
            // At this point, groups are already trickling in from the background thread managed by Requestmanager.
            // As groups objects come in, we immediately create a request to download members

            // This collection will contain groups with fully populated Members property
            IEnumerable <Group> groupsWithMembers;

            // This builder supports creation of requests for collections embedded in the Group object, such as Members
            using (var builder = GroupNestedCollectionsRequestBuilder.GetBuilder(requestManager, out groupsWithMembers))
            {
                // For each group object that has been downloaded we can now create a request. Note that the "groups" collection will block the thread
                // and wait if there are more results that have not been fetched yet.
                foreach (var group in groups)
                {
                    // Again, we queue up more requests to execute in the background.
                    // The request is only for the first page, but the specialized builder knows how to handle responses and will queue up more requests
                    // until the full group membership list is fetched and added to the group object.
                    builder.Members(group).Request().Top(999).GetAsync().Wait();
                }
            }
            // Note that at this point we have not fully fetched all results. This collection can be enumerated and will block if more results are incoming.
            // E.g. you could say groupsWithMembers.ToArray() to wait for all results, or use foreach and gradually process results as they become available.
            // Any group objects that show up in this collection will already have a full list of members populated.
            return(groupsWithMembers);
        }
Exemplo n.º 4
0
        public static string GetDeviceReport(RequestManager requestManager)
        {
            IEnumerable <Device> devices;

            using (var builder = GraphRequestBuilder <Device> .GetBuilder <DeviceCollectionResponseHandler>(requestManager, out devices))
            {
                builder.Devices.Request().Select("operatingSystem, isManaged, isCompliant").Top(999).GetAsync().Wait();
                foreach (var filter in GenericHelpers.GenerateFilterRangesForAlphaNumProperties("displayName"))
                {
                    builder.Devices.Request().Select("operatingSystem, isManaged, isCompliant").Top(999).Filter(filter).GetAsync().Wait();
                }
            }
            var report = devices.Distinct(new GenericHelpers.EntityComparer()).Cast <Device>()
                         .GroupBy(d => $"OS: {d.OperatingSystem ?? "null"}, isManaged: {d.IsManaged ?? false}, isCompliant: {d.IsCompliant ?? false}")
                         .Select(g => new { DeviceCategory = g.Key, DeviceCount = g.Count() });

            StringBuilder sb = new StringBuilder();

            foreach (var line in report.OrderByDescending(l => l.DeviceCount))
            {
                sb.AppendLine($"{line.DeviceCategory} - Count: {line.DeviceCount}");
            }
            return(sb.ToString());
        }