Exemplo n.º 1
0
        public static async Task Main(string[] args)
        {
            // Get the IP address to bind to as a command line arguement or default
            // to 127.0.0.1.
            var userSuppliedIp = args.Length < 1 ? "127.0.0.1" : args[0];

            // Require the IP address be supplied as a command line argument.
            var localIp       = IPAddress.Parse(userSuppliedIp);
            var localEndPoint = new IPEndPoint(localIp, BspConstants.DefaultPort);

            // Begin listening for clients attempting to discover the server IP
            _ = StartUdpListing(localEndPoint);

            // Create objects used for every connection.
            var generalLogger = new Logger(Console.Out);
            var unparser      = new MessageUnparser();
            var listener      = new BspListener(generalLogger);
            var gameTypeRepo  = CreateGameTypeRepository();
            var userRepo      = CreateUserRepository();
            var matchMaker    = new MatchMaker();

            // The body of this foreach loop is a callback. This body will run for
            // connection our listener accepts. Here we create objects specific for
            // each connection.
            await foreach (var socket in listener.StartListeningAsync(localEndPoint))
            {
                // Create a logger that will log with the client's EndPoint.
                var logger = new EndPointLogger(Console.Out, socket.RemoteEndPoint);

                // Create a disconnecter that can clean up a connection.
                var disconnecter = new ServerDisconnecter(logger, socket, userRepo, matchMaker);

                // Create a sender for sending messages to the client.
                var senderHandler = new MultiMessageHandler();
                var sender        = new BspSender(socket, logger, unparser, senderHandler);

                // Create a container for this connections state.
                var container = new ServerNetworkStateContainer(sender, disconnecter, gameTypeRepo,
                                                                userRepo, matchMaker);

                // Create a context for our state machine.
                var context = new NetworkStateContext(container, disconnecter);

                // Register incoming messages with this context.
                senderHandler.AddHandler(LoggingMessageHandler.ForSending(logger));
                senderHandler.AddHandler(new SentMessageHandler(context));

                // Register outgoing messages with this context.
                var receiverHandler = new MultiMessageHandler();
                receiverHandler.AddHandler(LoggingMessageHandler.ForReceiving(logger));
                receiverHandler.AddHandler(new ReceiveMessageHandler(context));

                // Create a parser for this connection
                var parser = new MessageParser(receiverHandler, gameTypeRepo);

                // Begin asynchronously receiving messages
                var receiver = new BspReceiver(socket, disconnecter, parser, logger);
                _ = receiver.StartReceivingAsync();
            }
        }
Exemplo n.º 2
0
        public async Task WritesToLogger()
        {
            // ARRANGE
            var logger = new StringBuilderHttpMessageLogger();

            var nullHandler = new Mock <HttpClientHandler>();

            nullHandler.Protected()
            .Setup <Task <HttpResponseMessage> >(
                "SendAsync",
                ItExpr.IsAny <HttpRequestMessage>(),
                ItExpr.IsAny <CancellationToken>()
                )
            // prepare the expected response of the mocked http call
            .ReturnsAsync(new HttpResponseMessage()
            {
                StatusCode = HttpStatusCode.OK
            })
            .Verifiable();


            var handler = new LoggingMessageHandler(logger, nullHandler.Object);

            using (var client = new HttpClient(handler, true))
            {
                // ACT
                _ = await client.GetAsync("http://localhost");

                var log = logger.GetLog(true);

                // ASSERT
                Assert.False(string.IsNullOrEmpty(log));
            }
        }
        public HttpClientBuilder WithLogging(ILoggerFactory loggerFactory)
        {
            var loggingMessageHandler = new LoggingMessageHandler(loggerFactory.CreateLogger <LoggingMessageHandler>());

            AddHandlerToChain(loggingMessageHandler);

            return(this);
        }
Exemplo n.º 4
0
        private HttpClient CreateClient()
        {
            HttpMessageHandler handler = new HttpClientHandler();

            handler = new LoggingMessageHandler(handler, this.log, this.timeProvider, this.repository);
            handler = new ThrottlingHandler(handler, this.settings);

            return(new HttpClient(handler));
        }
Exemplo n.º 5
0
 public LoggingMessageHandlerTestsFixture()
 {
     Logger = new Mock <ILogger <LoggingMessageHandler> >();
     HttpResponseMessage = new HttpResponseMessage();
     InnerMessageHandler = new FakeHttpMessageHandler {
         HttpResponseMessage = HttpResponseMessage
     };
     LoggingMessageHandler = new LoggingMessageHandler(Logger.Object)
     {
         InnerHandler = InnerMessageHandler
     };
     HttpClient = new HttpClient(LoggingMessageHandler);
 }
Exemplo n.º 6
0
        public async Task given_unknown_type_then_sut_ignores_message(
            IEventConverter converter,
            LoggingMessageHandler spy,
            Message message,
            string unknownType)
        {
            EventProcessor sut       = new EventProcessorBuilder(converter, spy).Build();
            EventData      eventData = converter.ConvertToEvent(message);

            eventData.Properties["Type"] = unknownType;

            await sut.Process(new[] { eventData });

            spy.Log.Should().BeEmpty();
        }
Exemplo n.º 7
0
        public async Task sut_processes_event_correctly(
            IEventConverter converter,
            LoggingMessageHandler spy,
            string id,
            MessageData1 data,
            TracingProperties tracingProperties)
        {
            EventProcessor sut       = new EventProcessorBuilder(converter, spy).Build();
            var            message   = new Message(id, data, tracingProperties);
            EventData      eventData = converter.ConvertToEvent(message);

            await sut.Process(new[] { eventData });

            spy.Log.Should().ContainSingle();
            spy.Log.Single().Should().BeEquivalentTo(message);
        }
Exemplo n.º 8
0
        public static async Task Run()
        {
            /////////////////////////////
            //
            // Programmer configuration
            //
            /////////////////////////////

            var sharepointDomain   = "demo.sharepoint.com";
            var siteCollectionPath = "/sites/GraphCommunityDemo";

            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */


            // Use the system browser to login
            //  https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core#how-to-use-the-system-browser-ie-the-default-browser-of-the-os

            var options = new PublicClientApplicationOptions()
            {
                AadAuthorityAudience = AadAuthorityAudience.AzureAdMyOrg,
                AzureCloudInstance   = AzureCloudInstance.AzurePublic,
                ClientId             = azureAdOptions.ClientId,
                TenantId             = azureAdOptions.TenantId,
                RedirectUri          = "http://localhost"
            };

            // Create the public client application (desktop app), with a default redirect URI
            var pca = PublicClientApplicationBuilder
                      .CreateWithApplicationOptions(options)
                      .Build();

            // Enable a simple token cache serialiation so that the user does not need to
            // re-sign-in each time the application is run
            TokenCacheHelper.EnableSerialization(pca.UserTokenCache);

            var scopes = new string[] { $"https://graph.microsoft.com/Sites.Read.All" };
            IAuthenticationProvider ap = new InteractiveAuthenticationProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);

                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var WebUrl = $"https://{sharepointDomain}{siteCollectionPath}";

                    try
                    {
                        var results = await graphServiceClient
                                      .Sites["root"]
                                      .Request()
                                      .Select(s => s.DisplayName)
                                      .GetAsync();

                        Console.WriteLine($"title: {results.DisplayName}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }



                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    var log = logger.GetLog();
                    Console.WriteLine(log);
                }
        }
Exemplo n.º 9
0
        public static async Task Run()
        {
            /////////////////////////////
            //
            // Programmer configuration
            //
            /////////////////////////////

            var sharepointDomain   = "demo.sharepoint.com";
            var siteCollectionPath = "/sites/GraphCommunityDemo";

            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */


            // Use the system browser to login
            //  https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/System-Browser-on-.Net-Core#how-to-use-the-system-browser-ie-the-default-browser-of-the-os

            var options = new PublicClientApplicationOptions()
            {
                AadAuthorityAudience = AadAuthorityAudience.AzureAdMyOrg,
                AzureCloudInstance   = AzureCloudInstance.AzurePublic,
                ClientId             = azureAdOptions.ClientId,
                TenantId             = azureAdOptions.TenantId,
                RedirectUri          = "http://localhost"
            };

            // Create the public client application (desktop app), with a default redirect URI
            var pca = PublicClientApplicationBuilder
                      .CreateWithApplicationOptions(options)
                      .Build();

            // Enable a simple token cache serialiation so that the user does not need to
            // re-sign-in each time the application is run
            TokenCacheHelper.EnableSerialization(pca.UserTokenCache);

            var scopes = new string[] { $"https://{sharepointDomain}/AllSites.FullControl" };
            IAuthenticationProvider ap = new InteractiveAuthenticationProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);

                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var WebUrl = $"https://{sharepointDomain}{siteCollectionPath}";

                    var queryText     = $"adaptive";
                    var propsToSelect = new List <string>()
                    {
                        "Title", "Path", "DocId]"
                    };
                    var sortList = new List <SearchQuery.Sort>()
                    {
                        new SearchQuery.Sort("DocId", SearchQuery.SortDirection.Ascending)
                    };

                    var query = new SearchQuery(
                        queryText: queryText,
                        selectProperties: propsToSelect,
                        sortList: sortList);

                    try
                    {
                        var results = await graphServiceClient
                                      .SharePointAPI(WebUrl)
                                      .Search
                                      .Request()
                                      .PostQueryAsync(query);

                        var rowCount  = results.PrimaryQueryResult.RelevantResults.RowCount;
                        var totalRows = results.PrimaryQueryResult.RelevantResults.TotalRows;

                        Console.WriteLine($"rowCount: {rowCount}");

                        string lastDocId = null;
                        foreach (var item in results.PrimaryQueryResult.RelevantResults.Table.Rows)
                        {
                            Console.WriteLine(item.Cells.FirstOrDefault(c => c.Key == "Path").Value);

                            var docId = item.Cells.FirstOrDefault(c => c.Key == "DocId")?.Value;
                            if (docId != null)
                            {
                                lastDocId = docId;
                            }
                        }

                        if (totalRows > rowCount && !string.IsNullOrEmpty(lastDocId))
                        {
                            var nextPageQuery = new SearchQuery(
                                queryText: $"{queryText} indexdocid>{lastDocId}",
                                selectProperties: propsToSelect,
                                sortList: sortList);

                            var page2results = await graphServiceClient
                                               .SharePointAPI(WebUrl)
                                               .Search
                                               .Request()
                                               .PostQueryAsync(nextPageQuery);

                            foreach (var item in page2results.PrimaryQueryResult.RelevantResults.Table.Rows)
                            {
                                Console.WriteLine(item.Cells.FirstOrDefault(c => c.Key == "Path").Value);
                            }
                        }
                        Console.WriteLine($"totalRows: {totalRows}");
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }



                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    var log = logger.GetLog();
                    Console.WriteLine(log);
                }
        }
Exemplo n.º 10
0
        public static async Task Main(string[] args)
        {
            // Create a logger
            var logger = new Logger(Console.Out);

            // If the user did not supply an IP or hostname, attempt to
            // discover a server on the same subnet.
            IPEndPoint endPoint;

            if (args.Length > 0)
            {
                if (IPAddress.TryParse(args[0], out var ip))
                {
                    endPoint = new IPEndPoint(ip, BspConstants.DefaultPort);
                }
                else
                {
                    // Maybe the user supplied a hostname not an IP
                    var addresses = Dns.GetHostAddresses(args[0]);

                    if (addresses.Length < 1)
                    {
                        Console.WriteLine("Could not find hostname.");
                        return;
                    }

                    endPoint = new IPEndPoint(addresses.Last(), BspConstants.DefaultPort);
                }
            }
            else
            {
                logger.LogInfo("Attempting to discover server end point...");
                endPoint = await DiscoverServerEndPoint(BspConstants.DefaultPort);
            }

            // Attempt to connect to the server.
            var unparser = new MessageUnparser();
            var socket   = new Socket(SocketType.Stream, ProtocolType.Tcp);

            try
            {
                logger.LogInfo($"Attempting to connect to {endPoint}");
                socket.Connect(endPoint);
            }
            catch (SocketException)
            {
                logger.LogError($"Failed to connect to {endPoint}");
            }

            // Create a disconnecter that can clean up a connection.
            var disconnecter = new ClientDisconnecter(logger, socket);

            // Create a sender for sending to the server.
            var senderHandler = new MultiMessageHandler();
            var sender        = new BspSender(socket, logger, unparser, senderHandler);

            // Create a prompter to handle user interaction.
            var prompter = new Prompter(sender);

            // Create a state machine
            var container = new ClientNetworkStateContainer(prompter);
            var context   = new NetworkStateContext(container, disconnecter);

            // Register sending messages with our state machine.
            senderHandler.AddHandler(LoggingMessageHandler.ForSending(logger));
            senderHandler.AddHandler(new SentMessageHandler(context));

            // Register receiving messages with our state machine.
            var receiverHandler = new MultiMessageHandler();

            receiverHandler.AddHandler(LoggingMessageHandler.ForReceiving(logger));
            receiverHandler.AddHandler(new ReceiveMessageHandler(context));

            // Create a parser for our connection with the server
            var parser   = new MessageParser(receiverHandler, new GameTypeRepository());
            var receiver = new BspReceiver(socket, disconnecter, parser, logger);

            // Begin receive messages and start the prompt.
            var receivingTask = receiver.StartReceivingAsync();

            prompter.PromptLogOn();
            await receivingTask;
        }
        public static async Task Run()
        {
            /////////////////////////////
            //
            // Programmer configuration
            //
            /////////////////////////////

            var sharepointDomain   = "demo.sharepoint.com";
            var siteCollectionPath = "/sites/SiteDesignTest";

            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */

            var pca = PublicClientApplicationBuilder
                      .Create(azureAdOptions.ClientId)
                      .WithTenantId(azureAdOptions.TenantId)
                      .Build();

            var scopes = new string[] { $"https://{sharepointDomain}/AllSites.FullControl" };
            IAuthenticationProvider ap = new DeviceCodeProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);

                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var WebUrl = $"https://{sharepointDomain}{siteCollectionPath}";

                    var siteScript = new SiteScriptMetadata()
                    {
                        Title       = "Green Theme",
                        Description = "Apply the Green Theme",
                        Content     = "{\"$schema\": \"schema.json\",\"actions\": [{\"verb\": \"applyTheme\",\"themeName\": \"Green\"}],\"bindata\": { },\"version\": 1}",
                    };

                    var createdScript = await graphServiceClient
                                        .SharePointAPI(WebUrl)
                                        .SiteScripts
                                        .Request()
                                        .CreateAsync(siteScript);

                    var siteDesign = new SiteDesignMetadata()
                    {
                        Title         = "Green Theme",
                        Description   = "Apply the Green theme",
                        SiteScriptIds = new System.Collections.Generic.List <Guid>()
                        {
                            new Guid(createdScript.Id)
                        },
                        WebTemplate = "64"                 // 64 = Team Site, 68 = Communication Site, 1 = Groupless Team Site
                    };

                    var createdDesign = await graphServiceClient
                                        .SharePointAPI(WebUrl)
                                        .SiteDesigns
                                        .Request()
                                        .CreateAsync(siteDesign);

                    var applySiteDesignRequest = new ApplySiteDesignRequest
                    {
                        SiteDesignId = createdDesign.Id,
                        WebUrl       = WebUrl
                    };

                    var applySiteDesignResponse = await graphServiceClient
                                                  .SharePointAPI(WebUrl)
                                                  .SiteDesigns.Request()
                                                  .ApplyAsync(applySiteDesignRequest);

                    foreach (var outcome in applySiteDesignResponse.ActionOutcomes)
                    {
                        Console.WriteLine(outcome.OutcomeText);
                    }


                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    var log = logger.GetLog();
                    Console.WriteLine(log);
                }
        }
Exemplo n.º 12
0
        public static async Task Run()
        {
            /////////////////////////////
            //
            // Programmer configuration
            //
            /////////////////////////////

            var sharepointDomain   = "demo.sharepoint.com";
            var siteCollectionPath = "/sites/SiteGroupsTest";

            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */

            var pca = PublicClientApplicationBuilder
                      .Create(azureAdOptions.ClientId)
                      .WithTenantId(azureAdOptions.TenantId)
                      .Build();

            var scopes = new string[] { $"https://{sharepointDomain}/AllSites.FullControl" };
            IAuthenticationProvider ap = new DeviceCodeProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);

                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var WebUrl = $"https://{sharepointDomain}{siteCollectionPath}";

                    var groups = await graphServiceClient
                                 .SharePointAPI(WebUrl)
                                 .Web
                                 .SiteGroups
                                 .Request()
                                 .Expand(g => g.Users)
                                 .Expand("Owner")
                                 .GetAsync();


                    foreach (var group in groups)
                    {
                        Console.WriteLine(group.Title);
                        foreach (var user in group.Users)
                        {
                            Console.WriteLine($"  {user.LoginName}");
                        }
                    }

                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    var log = logger.GetLog();
                    Console.WriteLine(log);
                }
        }
        public static async Task Run()
        {
            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */

            var pca = PublicClientApplicationBuilder
                      .Create(azureAdOptions.ClientId)
                      .WithTenantId(azureAdOptions.TenantId)
                      .Build();

            var scopes = new string[] { "https://graph.microsoft.com/Mail.Read" };
            IAuthenticationProvider ap = new DeviceCodeProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);


                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var messages =
                        await graphServiceClient
                        .Me
                        .Messages
                        .Request()
                        .Top(1)
                        .GetAsync();

                    Console.WriteLine($"ID: {messages.CurrentPage[0].Id}");

                    Console.WriteLine();

                    var messagesI =
                        await graphServiceClient
                        .Me
                        .Messages
                        .Request()
                        .WithImmutableId()
                        .Top(1)
                        .GetAsync();

                    Console.WriteLine($"ImmutableId: {messagesI.CurrentPage[0].Id}");
                    Console.WriteLine();

                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    Console.WriteLine(logger.GetLog());
                }
        }
Exemplo n.º 14
0
        public static async Task Run()
        {
            /////////////////////////////
            //
            // Programmer configuration
            //
            /////////////////////////////

            var sharepointDomain   = "demo.sharepoint.com";
            var siteCollectionPath = "/sites/GraphCommunityDemo";

            /////////////////
            //
            // Configuration
            //
            /////////////////

            AzureAdOptions azureAdOptions = new AzureAdOptions();

            var settingsFilename = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "appsettings.json");
            var builder          = new ConfigurationBuilder()
                                   .AddJsonFile(settingsFilename, optional: false)
                                   .AddUserSecrets <Program>();
            var config = builder.Build();

            config.Bind("AzureAd", azureAdOptions);

            ////////////////////////////
            //
            // Graph Client with Logger
            //
            ////////////////////////////

            var logger = new StringBuilderHttpMessageLogger();

            /*
             *  Could also use the Console if preferred...
             *
             *  var logger = new ConsoleHttpMessageLogger();
             */

            var pca = PublicClientApplicationBuilder
                      .Create(azureAdOptions.ClientId)
                      .WithTenantId(azureAdOptions.TenantId)
                      .Build();

            var scopes = new string[] { $"https://{sharepointDomain}/AllSites.FullControl" };
            IAuthenticationProvider ap = new DeviceCodeProvider(pca, scopes);

            using (LoggingMessageHandler loggingHandler = new LoggingMessageHandler(logger))
                using (HttpProvider hp = new HttpProvider(loggingHandler, false, new Serializer()))
                {
                    GraphServiceClient graphServiceClient = new GraphServiceClient(ap, hp);


                    ////////////////////////////
                    //
                    // Setup is complete, run the sample
                    //
                    ////////////////////////////

                    var WebUrl = $"https://{sharepointDomain}{siteCollectionPath}";

                    var web = await graphServiceClient
                              .SharePointAPI(WebUrl)
                              .Web
                              .Request()
                              .GetAsync();

                    var changeToken = web.CurrentChangeToken;
                    Console.WriteLine($"current change token: {changeToken.StringValue}");

                    Console.WriteLine($"Make an update to the site {WebUrl}");
                    Console.WriteLine("Press enter to continue");
                    Console.ReadLine();

                    var qry = new ChangeQuery(true, true);
                    qry.ChangeTokenStart = changeToken;

                    var changes = await graphServiceClient
                                  .SharePointAPI(WebUrl)
                                  .Web
                                  .Request()
                                  .GetChangesAsync(qry);

                    Console.WriteLine(changes.Count);

                    foreach (var item in changes)
                    {
                        Console.WriteLine($"{item.ChangeType}");
                    }

                    Console.WriteLine("Press enter to show log");
                    Console.ReadLine();
                    Console.WriteLine();
                    var log = logger.GetLog();
                    Console.WriteLine(log);
                }
        }