Esempio n. 1
0
        public void ConfigureServices(IServiceCollection services)
        {
            ShokoServer.ConfigureServices(services);
            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = CustomAuthOptions.DefaultScheme;
                options.DefaultChallengeScheme    = CustomAuthOptions.DefaultScheme;
            }).AddScheme <CustomAuthOptions, CustomAuthHandler>(CustomAuthOptions.DefaultScheme, _ => { });

            services.AddAuthorization(auth =>
            {
                auth.AddPolicy("admin",
                               policy => policy.Requirements.Add(new UserHandler(user => user.IsAdmin == 1)));
                auth.AddPolicy("init",
                               policy => policy.Requirements.Add(new UserHandler(user =>
                                                                                 user.JMMUserID == 0 && user.UserName == "init")));
            });

            services.AddSwaggerGen(
                options =>
            {
                // resolve the IApiVersionDescriptionProvider service
                // note: that we have to build a temporary service provider here because one has not been created yet
                var provider = services.BuildServiceProvider().GetRequiredService <IApiVersionDescriptionProvider>();

                // add a swagger document for each discovered API version
                // note: you might choose to skip or document deprecated API versions differently
                foreach (var description in provider.ApiVersionDescriptions)
                {
                    options.SwaggerDoc(description.GroupName, CreateInfoForApiVersion(description));
                }

                options.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme()
                {
                    Description = "Shoko API Key Header",
                    Name        = "apikey",
                    In          = ParameterLocation.Header,
                    Type        = SecuritySchemeType.ApiKey,
                    Scheme      = "apikey",
                });

                options.AddSecurityRequirement(new OpenApiSecurityRequirement()
                {
                    {
                        new OpenApiSecurityScheme {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id   = "ApiKey",
                            },
                        },
                        new string[] {}
                    },
                });

                // add a custom operation filter which sets default values
                //options.OperationFilter<SwaggerDefaultValues>();

                // integrate xml comments
                //Locate the XML file being generated by ASP.NET...
                var xmlFile = "Shoko.Server.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                if (File.Exists(xmlPath))
                {
                    options.IncludeXmlComments(xmlPath);
                }

                foreach (Type type in Loader.Instance.Plugins.Keys)
                {
                    var assembly = type.Assembly;
                    var location = assembly.Location;
                    var xml      = Path.Combine(Path.GetDirectoryName(location), $"{Path.GetFileNameWithoutExtension(location)}.xml");
                    if (File.Exists(xml))
                    {
                        options.IncludeXmlComments(xml);                       //Include the XML comments if it exists.
                    }
                }
                options.MapType <v3.Models.Shoko.SeriesType>(() => new OpenApiSchema {
                    Type = "string"
                });
                options.MapType <v3.Models.Shoko.EpisodeType>(() => new OpenApiSchema {
                    Type = "string"
                });

                options.CustomSchemaIds(x => x.FullName);
            });
            services.AddSwaggerGenNewtonsoftSupport();

            services.AddSignalR(o =>
            {
                o.EnableDetailedErrors = true;
            });

            services.AddSingleton <QueueEmitter>();
            services.AddSingleton <LegacyAniDBEmitter>();
            services.AddSingleton <LoggingEmitter>();

            // allow CORS calls from other both local and non-local hosts
            services.AddCors(options =>
            {
                options.AddDefaultPolicy(
                    builder =>
                {
                    builder
                    .AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader();
                });
            });

            // this caused issues with auth. https://stackoverflow.com/questions/43574552
            var mvc = services.AddMvc(options =>
            {
                options.EnableEndpointRouting             = false;
                options.AllowEmptyInputInBodyModelBinding = true;
                foreach (var formatter in options.InputFormatters)
                {
                    if (formatter.GetType() == typeof(NewtonsoftJsonInputFormatter))
                    {
                        ((NewtonsoftJsonInputFormatter)formatter).SupportedMediaTypes.Add(
                            MediaTypeHeaderValue.Parse("text/plain"));
                    }
                }

                options.Filters.Add(typeof(DatabaseBlockedFilter));
                options.Filters.Add(typeof(ServerNotRunningFilter));

                EmitEmptyEnumerableInsteadOfNullAttribute.MvcOptions = options;
            })
                      .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
                      .AddNewtonsoftJson(json =>
            {
                json.SerializerSettings.MaxDepth         = 10;
                json.SerializerSettings.ContractResolver = new OmitEmptyEnumerableResolver
                {
                    NamingStrategy = new DefaultNamingStrategy()
                };
                json.SerializerSettings.NullValueHandling    = NullValueHandling.Include;
                json.SerializerSettings.DefaultValueHandling = DefaultValueHandling.Populate;
                json.SerializerSettings.DateFormatString     = "yyyy-MM-dd";
            });

            foreach (Type type in Loader.Instance.Plugins.Keys)
            {
                var assembly = type.Assembly;
                if (assembly == Assembly.GetCallingAssembly())
                {
                    continue;                                            //Skip the current assembly, this is implicitly added by ASP.
                }
                mvc.AddApplicationPart(assembly).AddControllersAsServices();
            }


            services.AddApiVersioning(o =>
            {
                o.ReportApiVersions = true;
                o.AssumeDefaultVersionWhenUnspecified = true;
                o.DefaultApiVersion = ApiVersion.Default;
                o.ApiVersionReader  = ApiVersionReader.Combine(
                    new QueryStringApiVersionReader(),
                    new HeaderApiVersionReader("api-version"),
                    new ShokoApiReader()
                    );
            });
            services.AddVersionedApiExplorer();
            services.AddResponseCaching();

            services.Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });
        }