public void ConfigureServices()

in src/dotnet/APIView/APIViewWeb/Startup.cs [67:285]


        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplicationInsightsTelemetry();
            services.AddApplicationInsightsTelemetryProcessor<TelemetryIpAddressFilter>();

            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.Lax;
            });

            services.Configure<OrganizationOptions>(options => Configuration
                .GetSection("Github")
                .Bind(options));

#pragma warning disable ASP5001 // Type or member is obsolete
#pragma warning disable CS0618 // Type or member is obsolete
            services.AddMvc()
                .SetCompatibilityVersion(CompatibilityVersion.Latest)
                .AddRazorRuntimeCompilation();
#pragma warning restore CS0618 // Type or member is obsolete
#pragma warning restore ASP5001 // Type or member is obsolete

            services.AddRazorPages(options =>
            {
                options.Conventions.AuthorizeFolder("/Assemblies", RequireOrganizationPolicy);
                options.Conventions.AddPageRoute("/Assemblies/Index", "");
            });

            services.AddSingleton<IBlobCodeFileRepository, BlobCodeFileRepository>();
            services.AddSingleton<IBlobOriginalsRepository, BlobOriginalsRepository>();
            services.AddSingleton<IBlobUsageSampleRepository, BlobUsageSampleRepository>();

            services.AddSingleton<ICosmosReviewRepository,CosmosReviewRepository>();
            services.AddSingleton<ICosmosAPIRevisionsRepository, CosmosAPIRevisionsRepository>();
            services.AddSingleton<ICosmosCommentsRepository, CosmosCommentsRepository>();
            services.AddSingleton<ICosmosPullRequestsRepository, CosmosPullRequestsRepository>();
            services.AddSingleton<ICosmosSamplesRevisionsRepository, CosmosSamplesRevisionsRepository>();
            services.AddSingleton<ICosmosUserProfileRepository, CosmosUserProfileRepository>();
            services.AddSingleton<IDevopsArtifactRepository, DevopsArtifactRepository>();

            services.AddSingleton<IReviewManager, ReviewManager>();
            services.AddSingleton<IAPIRevisionsManager, APIRevisionsManager>();
            services.AddSingleton<ICommentsManager, CommentsManager>();
            services.AddSingleton<INotificationManager, NotificationManager>();
            services.AddSingleton<IPullRequestManager, PullRequestManager>();
            services.AddSingleton<IPackageNameManager, PackageNameManager>();
            services.AddSingleton<ISamplesRevisionsManager, SamplesRevisionsManager>();
            services.AddSingleton<ICodeFileManager, CodeFileManager>();
            services.AddSingleton<IUserProfileManager, UserProfileManager>();
            services.AddSingleton<UserPreferenceCache>();

            services.AddSingleton<LanguageService, JsonLanguageService>();
            services.AddSingleton<LanguageService, CSharpLanguageService>();
            services.AddSingleton<LanguageService, CLanguageService>();
            services.AddSingleton<LanguageService, JavaLanguageService>();
            services.AddSingleton<LanguageService, PythonLanguageService>();
            services.AddSingleton<LanguageService, JavaScriptLanguageService>();
            services.AddSingleton<LanguageService, RustLanguageService>();
            services.AddSingleton<LanguageService, CppLanguageService>();
            services.AddSingleton<LanguageService, GoLanguageService>();
            services.AddSingleton<LanguageService, ProtocolLanguageService>();
            services.AddSingleton<LanguageService, SwaggerLanguageService>();
            services.AddSingleton<LanguageService, SwiftLanguageService>();
            services.AddSingleton<LanguageService, XmlLanguageService>();
            services.AddSingleton<LanguageService, TypeSpecLanguageService>();

            if (Environment.IsDevelopment() && Configuration["AuthenticationScheme"] == "Test")
            {
                services.AddAuthentication("Test")
                    .AddScheme<AuthenticationSchemeOptions, TestAuthHandler>("Test", options => { });
                services.AddSingleton<IStartupFilter, UITestsStartUpFilter>();
            }
            else
            {
                services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                    options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
                })
                .AddCookie(options =>
                {
                    options.LoginPath = "/Login";
                    options.AccessDeniedPath = "/Unauthorized";
                })
                .AddOAuth("GitHub", options =>
                {
                    options.ClientId = Configuration["Github:ClientId"];
                    options.ClientSecret = Configuration["Github:ClientSecret"];
                    options.CallbackPath = new PathString("/signin-github");
                    options.Scope.Add("user:email");

                    options.AuthorizationEndpoint = "https://github.com/login/oauth/authorize";
                    options.TokenEndpoint = "https://github.com/login/oauth/access_token";
                    options.UserInformationEndpoint = "https://api.github.com/user";

                    options.SaveTokens = true;

                    options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "id");
                    options.ClaimActions.MapJsonKey(ClaimTypes.Name, "name");
                    options.ClaimActions.MapJsonKey(ClaimConstants.Login, "login");
                    options.ClaimActions.MapJsonKey(ClaimConstants.Url, "html_url");
                    options.ClaimActions.MapJsonKey(ClaimConstants.Avatar, "avatar_url");
                    options.ClaimActions.MapJsonKey(ClaimConstants.Name, "name");

                    options.Events = new OAuthEvents
                    {
                        OnCreatingTicket = async context =>
                        {
                            var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                            request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);

                            var response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                            response.EnsureSuccessStatusCode();

                            var user = JsonDocument.Parse(await response.Content.ReadAsStringAsync());

                            context.RunClaimActions(user.RootElement);
                            if (user.RootElement.TryGetProperty("organizations_url", out var organizationsUrlProperty))
                            {
                                request = new HttpRequestMessage(HttpMethod.Get, organizationsUrlProperty.GetString());
                                request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);

                                response = await context.Backchannel.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, context.HttpContext.RequestAborted);
                                response.EnsureSuccessStatusCode();

                                var orgs = JArray.Parse(await response.Content.ReadAsStringAsync());
                                var orgNames = new StringBuilder();

                                bool isFirst = true;
                                foreach (var org in orgs)
                                {
                                    if (isFirst)
                                    {
                                        isFirst = false;
                                    }
                                    else
                                    {
                                        orgNames.Append(",");
                                    }
                                    orgNames.Append(org["login"]);
                                }

                                string msEmail = await GetMicrosoftEmailAsync(context);
                                if (msEmail != null)
                                {
                                    context.Identity.AddClaim(
                                        new Claim(ClaimConstants.Email, msEmail));
                                }
                                context.Identity.AddClaim(new Claim(ClaimConstants.Orgs, orgNames.ToString()));
                            }
                        }
                    };
                });
            }

            services.AddAuthorization();
            services.AddCors(options => {
                options.AddPolicy("AllowCredentials", builder =>
                {
                    string [] origins = (Environment.IsDevelopment()) ? URlHelpers.GetAllowedStagingOrigins() : URlHelpers.GetAllowedProdOrigins();
                    builder.WithOrigins(origins)
                        .AllowAnyMethod()
                        .AllowAnyHeader()
                        .AllowCredentials()
                        .SetPreflightMaxAge(TimeSpan.FromHours(20));
                });
            });
            services.AddSingleton<IConfigureOptions<AuthorizationOptions>, ConfigureOrganizationPolicy>();
            services.AddSingleton<IAuthorizationHandler, OrganizationRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, CommentOwnerRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, ReviewOwnerRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, APIRevisionOwnerRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, ApproverRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, ResolverRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, AutoAPIRevisionModifierRequirementHandler>();
            services.AddSingleton<IAuthorizationHandler, SamplesRevisionOwnerRequirementHandler>();
            services.AddSingleton(x =>
            {
                return new CosmosClient(Configuration["CosmosEndpoint"], new DefaultAzureCredential());
            });
            services.AddSingleton(x =>
            {
                return new BlobServiceClient(new Uri(Configuration["StorageAccountUrl"]), new DefaultAzureCredential());
            });

            services.AddHostedService<ReviewBackgroundHostedService>();
            services.AddHostedService<PullRequestBackgroundHostedService>();
            services.AddHostedService<LinesWithDiffBackgroundHostedService>();
            services.AddAutoMapper(Assembly.GetExecutingAssembly());

            services.AddControllersWithViews()
                .AddJsonOptions(options => options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve)
                .PartManager.ApplicationParts.Add(new AssemblyPart(typeof(BaseApiController).Assembly));
            services.AddSignalR(options => {
                options.EnableDetailedErrors = true;
                options.MaximumReceiveMessageSize =  1024 * 1024;
            });
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version = "v1",
                    Title = "APIView API",
                    Description = "API Endpoints for consuming APIView application",
                    Contact = new OpenApiContact
                    {
                        Name = "Azure SDK Engineering Systems",
                        Url = new Uri("https://teams.microsoft.com/l/channel/19%3a3adeba4aa1164f1c889e148b1b3e3ddd%40thread.skype/APIView?groupId=3e17dcb0-4257-4a30-b843-77f47f1d4121&tenantId=72f988bf-86f1-41af-91ab-2d7cd011db47")
                    }
                });
                var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename));
            });
        }