コード例 #1
0
        public static IMvcBuilder AddNaos(
            this IMvcBuilder mvcBuilder,
            Action <NaosMvcOptions> optionsAction = null)
        {
            var options = new NaosMvcOptions();

            optionsAction?.Invoke(options);

            if (!options.ControllerRegistrations.IsNullOrEmpty())
            {
                mvcBuilder
                .AddMvcOptions(o =>
                {
                    o.Filters.Add <OperationCancelledExceptionFilter>();
                    o.Conventions.Add(new GeneratedControllerRouteConvention());
                })
                .ConfigureApplicationPartManager(o => o
                                                 .FeatureProviders.Add(
                                                     new GeneratedRepositoryControllerFeatureProvider(options.ControllerRegistrations)));
            }

            mvcBuilder.AddControllersAsServices(); // needed to resolve controllers through di https://andrewlock.net/controller-activation-and-dependency-injection-in-asp-net-core-mvc/
            mvcBuilder.AddJsonOptions(o => o.AddDefaultJsonSerializerSettings(options.JsonSerializerSettings));

            return(mvcBuilder);
        }
コード例 #2
0
        /// <summary>
        ///     Finds all the types that are <see cref="Controller" /> or <see cref="FeatureController" />and add them to the Api
        ///     as services.
        /// </summary>
        /// <param name="builder">The builder</param>
        /// <param name="services">The services to look into</param>
        /// <returns>The Mvc builder</returns>
        public static IMvcBuilder AddControllers(this IMvcBuilder builder, IServiceCollection services)
        {
            // Adds Controllers with API endpoints
            IEnumerable <ServiceDescriptor> controllerTypes = services.Where(s => s.ServiceType.GetTypeInfo().BaseType == typeof(Controller));

            foreach (ServiceDescriptor controllerType in controllerTypes)
            {
                builder.AddApplicationPart(controllerType.ServiceType.GetTypeInfo().Assembly);
            }

            // Adds FeatureControllers with API endpoints.
            IEnumerable <ServiceDescriptor> featureControllerTypes = services.Where(s => s.ServiceType.GetTypeInfo().BaseType == typeof(FeatureController));

            foreach (ServiceDescriptor featureControllerType in featureControllerTypes)
            {
                builder.AddApplicationPart(featureControllerType.ServiceType.GetTypeInfo().Assembly);
            }

            // Adds ServerNodeContoller with API endpoints.
            builder.AddApplicationPart(typeof(ServerNodeContoller).Assembly);

            // Adds PublicController with API endpoints.
            builder.AddApplicationPart(typeof(PublicController).Assembly);

            builder.AddControllersAsServices();
            return(builder);
        }
コード例 #3
0
        /// <summary>
        /// Extension method for adding the jellyfin API to the service collection.
        /// </summary>
        /// <param name="serviceCollection">The service collection.</param>
        /// <param name="pluginAssemblies">An IEnumerable containing all plugin assemblies with API controllers.</param>
        /// <param name="knownProxies">A list of all known proxies to trust for X-Forwarded-For.</param>
        /// <returns>The MVC builder.</returns>
        public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable <Assembly> pluginAssemblies, IReadOnlyList <string> knownProxies)
        {
            IMvcBuilder mvcBuilder = serviceCollection
                                     .AddCors()
                                     .AddTransient <ICorsPolicyProvider, CorsPolicyProvider>()
                                     .Configure <ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
                for (var i = 0; i < knownProxies.Count; i++)
                {
                    if (IPAddress.TryParse(knownProxies[i], out var address))
                    {
                        options.KnownProxies.Add(address);
                    }
                }
            })
                                     .AddMvc(opts =>
            {
                // Allow requester to change between camelCase and PascalCase
                opts.RespectBrowserAcceptHeader = true;

                opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter());
                opts.OutputFormatters.Insert(0, new PascalCaseJsonProfileFormatter());

                opts.OutputFormatters.Add(new CssOutputFormatter());
                opts.OutputFormatters.Add(new XmlOutputFormatter());
            })

                                     // Clear app parts to avoid other assemblies being picked up
                                     .ConfigureApplicationPartManager(a => a.ApplicationParts.Clear())
                                     .AddApplicationPart(typeof(StartupController).Assembly)
                                     .AddJsonOptions(options =>
            {
                // Update all properties that are set in JsonDefaults
                var jsonOptions = JsonDefaults.GetPascalCaseOptions();

                // From JsonDefaults
                options.JsonSerializerOptions.ReadCommentHandling    = jsonOptions.ReadCommentHandling;
                options.JsonSerializerOptions.WriteIndented          = jsonOptions.WriteIndented;
                options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
                options.JsonSerializerOptions.NumberHandling         = jsonOptions.NumberHandling;

                options.JsonSerializerOptions.Converters.Clear();
                foreach (var converter in jsonOptions.Converters)
                {
                    options.JsonSerializerOptions.Converters.Add(converter);
                }

                // From JsonDefaults.PascalCase
                options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy;
            });

            foreach (Assembly pluginAssembly in pluginAssemblies)
            {
                mvcBuilder.AddApplicationPart(pluginAssembly);
            }

            return(mvcBuilder.AddControllersAsServices());
        }
コード例 #4
0
        /// <summary>
        /// Finds all the types that are <see cref="Controller"/> and add them to the Api as services.
        /// </summary>
        /// <param name="builder">The builder</param>
        /// <param name="services">The services to look into</param>
        /// <returns>The Mvc builder</returns>
        public static IMvcBuilder AddControllers(this IMvcBuilder builder, IServiceCollection services)
        {
            var controllerTypes = services.Where(s => s.ServiceType.GetTypeInfo().BaseType == typeof(Controller));

            foreach (var controllerType in controllerTypes)
            {
                builder.AddApplicationPart(controllerType.ServiceType.GetTypeInfo().Assembly);
            }

            builder.AddControllersAsServices();
            return(builder);
        }
コード例 #5
0
        /// <summary>
        /// Extension method for adding the jellyfin API to the service collection.
        /// </summary>
        /// <param name="serviceCollection">The service collection.</param>
        /// <param name="baseUrl">The base url for the API.</param>
        /// <param name="pluginAssemblies">An IEnumberable containing all plugin assemblies with API controllers.</param>
        /// <returns>The MVC builder.</returns>
        public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, string baseUrl, IEnumerable <Assembly> pluginAssemblies)
        {
            IMvcBuilder mvcBuilder = serviceCollection
                                     .AddCors(options =>
            {
                options.AddPolicy(ServerCorsPolicy.DefaultPolicyName, ServerCorsPolicy.DefaultPolicy);
            })
                                     .Configure <ForwardedHeadersOptions>(options =>
            {
                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
            })
                                     .AddMvc(opts =>
            {
                opts.UseGeneralRoutePrefix(baseUrl);
                opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter());
                opts.OutputFormatters.Insert(0, new PascalCaseJsonProfileFormatter());

                opts.OutputFormatters.Add(new CssOutputFormatter());
                opts.OutputFormatters.Add(new XmlOutputFormatter());
            })

                                     // Clear app parts to avoid other assemblies being picked up
                                     .ConfigureApplicationPartManager(a => a.ApplicationParts.Clear())
                                     .AddApplicationPart(typeof(StartupController).Assembly)
                                     .AddJsonOptions(options =>
            {
                // Update all properties that are set in JsonDefaults
                var jsonOptions = JsonDefaults.GetPascalCaseOptions();

                // From JsonDefaults
                options.JsonSerializerOptions.ReadCommentHandling    = jsonOptions.ReadCommentHandling;
                options.JsonSerializerOptions.WriteIndented          = jsonOptions.WriteIndented;
                options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
                options.JsonSerializerOptions.NumberHandling         = jsonOptions.NumberHandling;

                options.JsonSerializerOptions.Converters.Clear();
                foreach (var converter in jsonOptions.Converters)
                {
                    options.JsonSerializerOptions.Converters.Add(converter);
                }

                // From JsonDefaults.PascalCase
                options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy;
            });

            foreach (Assembly pluginAssembly in pluginAssemblies)
            {
                mvcBuilder.AddApplicationPart(pluginAssembly);
            }

            return(mvcBuilder.AddControllersAsServices());
        }
コード例 #6
0
        public static IServiceCollection AddDeploymentMvc(this IServiceCollection services,
                                                          EnvironmentConfiguration environmentConfiguration,
                                                          IKeyValueConfiguration configuration,
                                                          ILogger logger,
                                                          IApplicationAssemblyResolver applicationAssemblyResolver)
        {
            ViewAssemblyLoader.LoadViewAssemblies(logger);
            var         filteredAssemblies = applicationAssemblyResolver.GetAssemblies();
            IMvcBuilder mvcBuilder         = services.AddMvc(
                options =>
            {
                options.InputFormatters.Insert(0, new XWwwFormUrlEncodedFormatter());
                options.Filters.Add <ModelValidatorFilterAttribute>();
            })
                                             .AddNewtonsoftJson(
                options =>
            {
                options.SerializerSettings.Converters.Add(new DateConverter());
                options.SerializerSettings.Formatting = Formatting.Indented;
            });

            foreach (Assembly filteredAssembly in filteredAssemblies)
            {
                logger.Debug("Adding assembly {Assembly} to MVC application parts", filteredAssembly.FullName);
                mvcBuilder.AddApplicationPart(filteredAssembly);
            }

            var viewAssemblies = AssemblyLoadContext.Default.Assemblies
                                 .Where(assembly => !assembly.IsDynamic && (assembly.GetName().Name?.Contains("View") ?? false))
                                 .ToArray();

            foreach (var item in viewAssemblies)
            {
                mvcBuilder.AddApplicationPart(item);
            }

            if (environmentConfiguration.ToHostEnvironment().IsDevelopment() ||
                configuration.ValueOrDefault(StartupConstants.RuntimeCompilationEnabled))
            {
                mvcBuilder.AddRazorRuntimeCompilation();
            }

            mvcBuilder
            .AddControllersAsServices();

            services.AddAntiforgery();

            return(services);
        }
コード例 #7
0
        internal static IMvcBuilder AddExternalControllers(this IMvcBuilder builder)
        {
            List <Assembly> assemblies = new List <Assembly>();
            string          path       = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

            foreach (string dll in Directory.GetFiles(path, "*.dll"))
            {
                assemblies.Add(Assembly.LoadFile(dll));
            }

            foreach (var asm in assemblies)
            {
                builder.AddApplicationPart(asm);
            }

            builder.AddControllersAsServices();

            return(builder);
        }
コード例 #8
0
        public static void InstallModules(
            this IServiceCollection services,
            string contentRootPath)
        {
            LineBotService.ContentRootPath = contentRootPath;

            #region Internal Module
            List <Type> result = new List <Type>();

            IMvcBuilder mvc = services.AddMvc();

            foreach (var assembly in Assembly
                     .GetEntryAssembly()
                     .GetReferencedAssemblies()
                     .Select(Assembly.Load)
                     .Concat(new Assembly[] { Assembly.GetEntryAssembly() }))
            {
                mvc = mvc.AddApplicationPart(assembly);

                Type[] types = null;
                try {
                    types = assembly.GetTypes();
                } catch (ReflectionTypeLoadException e) {
                    Console.WriteLine("[FAIL LOAD]: " + assembly.FullName + ";" + e.InnerException);
                    types = e.Types;
                }
                result.AddRange(types);
            }

            LineBotService.ReplyModules = new List <(Type, bool)>();
            foreach (var type in result)
            {
                if (!type.GetInterfaces().Contains(typeof(ILineReplyModule)))
                {
                    continue;
                }
                LineBotService.ReplyModules.Add((type, true));
                services.AddScoped(type);
            }
            #endregion

            var pluginsPath = Path.Combine(contentRootPath, "plugins");

            Console.WriteLine($"PluginsPath: {pluginsPath}");
            if (!Directory.Exists(pluginsPath))
            {
                Console.WriteLine("建立plugins目錄");
                Directory.CreateDirectory(pluginsPath);
            }

            // plugin
            Directory.GetDirectories(pluginsPath).ParallelForEachAsync(async module => {
                Console.WriteLine("Install:" + module);
                foreach (var dll in Directory.GetFiles(module, "*.dll", SearchOption.AllDirectories))
                {
                    System.Runtime.Loader.AssemblyLoadContext.Default
                    .LoadFromAssemblyPath(dll);
                }
                foreach (var dll in Directory.GetFiles(module, "*.dll", SearchOption.AllDirectories))
                {
                    InstallReplayProcessFromDll(services, mvc, dll);
                }
            }).GetAwaiter().GetResult();

            mvc = mvc.AddControllersAsServices();

            // 停用模組
            using (var file = File.Open("disableModules.txt", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read)) {
                var moduleNames = new StreamReader(file).ReadToEnd()?.Split(',') ?? new string[0];
                moduleNames = moduleNames.Select(x => x.Trim()).Where(x => x.Length > 0).ToArray();
                foreach (var moduleName in moduleNames)
                {
                    var moduleIndex = LineBotService.ReplyModules.FindIndex(x => x.type.Name.ToLower() == moduleName.ToLower());
                    LineBotService.ReplyModules[moduleIndex] = (LineBotService.ReplyModules[moduleIndex].type, false);
                }
            }
        }
コード例 #9
0
        /// <summary>
        /// Extension method for adding the jellyfin API to the service collection.
        /// </summary>
        /// <param name="serviceCollection">The service collection.</param>
        /// <param name="pluginAssemblies">An IEnumerable containing all plugin assemblies with API controllers.</param>
        /// <param name="config">The <see cref="NetworkConfiguration"/>.</param>
        /// <returns>The MVC builder.</returns>
        public static IMvcBuilder AddJellyfinApi(this IServiceCollection serviceCollection, IEnumerable <Assembly> pluginAssemblies, NetworkConfiguration config)
        {
            IMvcBuilder mvcBuilder = serviceCollection
                                     .AddCors()
                                     .AddTransient <ICorsPolicyProvider, CorsPolicyProvider>()
                                     .Configure <ForwardedHeadersOptions>(options =>
            {
                // https://github.com/dotnet/aspnetcore/blob/master/src/Middleware/HttpOverrides/src/ForwardedHeadersMiddleware.cs
                // Enable debug logging on Microsoft.AspNetCore.HttpOverrides.ForwardedHeadersMiddleware to help investigate issues.

                options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost;

                if (config.KnownProxies.Length == 0)
                {
                    options.KnownNetworks.Clear();
                    options.KnownProxies.Clear();
                }
                else
                {
                    AddProxyAddresses(config, config.KnownProxies, options);
                }

                // Only set forward limit if we have some known proxies or some known networks.
                if (options.KnownProxies.Count != 0 || options.KnownNetworks.Count != 0)
                {
                    options.ForwardLimit = null;
                }
            })
                                     .AddMvc(opts =>
            {
                // Allow requester to change between camelCase and PascalCase
                opts.RespectBrowserAcceptHeader = true;

                opts.OutputFormatters.Insert(0, new CamelCaseJsonProfileFormatter());
                opts.OutputFormatters.Insert(0, new PascalCaseJsonProfileFormatter());

                opts.OutputFormatters.Add(new CssOutputFormatter());
                opts.OutputFormatters.Add(new XmlOutputFormatter());

                opts.ModelBinderProviders.Insert(0, new NullableEnumModelBinderProvider());
            })

                                     // Clear app parts to avoid other assemblies being picked up
                                     .ConfigureApplicationPartManager(a => a.ApplicationParts.Clear())
                                     .AddApplicationPart(typeof(StartupController).Assembly)
                                     .AddJsonOptions(options =>
            {
                // Update all properties that are set in JsonDefaults
                var jsonOptions = JsonDefaults.PascalCaseOptions;

                // From JsonDefaults
                options.JsonSerializerOptions.ReadCommentHandling    = jsonOptions.ReadCommentHandling;
                options.JsonSerializerOptions.WriteIndented          = jsonOptions.WriteIndented;
                options.JsonSerializerOptions.DefaultIgnoreCondition = jsonOptions.DefaultIgnoreCondition;
                options.JsonSerializerOptions.NumberHandling         = jsonOptions.NumberHandling;

                options.JsonSerializerOptions.Converters.Clear();
                foreach (var converter in jsonOptions.Converters)
                {
                    options.JsonSerializerOptions.Converters.Add(converter);
                }

                // From JsonDefaults.PascalCase
                options.JsonSerializerOptions.PropertyNamingPolicy = jsonOptions.PropertyNamingPolicy;
            });

            foreach (Assembly pluginAssembly in pluginAssemblies)
            {
                mvcBuilder.AddApplicationPart(pluginAssembly);
            }

            return(mvcBuilder.AddControllersAsServices());
        }
コード例 #10
0
        // This method gets called by a runtime.
        // Use this method to add services to the container
        public void ConfigureServices(IServiceCollection services)
        {
            var    hostEnv        = services.BuildServiceProvider().GetRequiredService <IHostingEnvironment>();
            string configRootPath = services.BuildServiceProvider().GetRequiredService <IHostingEnvironment>().ConfigRootPath();

            //
            // Configuration
            services.AddSingleton((s) => Configuration);
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            //
            // Logging
            services.AddApiLogging();

            //
            // Auditing
            services.AddApiAuditing();

            //
            // Load plugins
            ModuleConfig modConfig = new ModuleConfig(Path.Combine(configRootPath, "modules.json"));
            ModuleLoader loader    = new ModuleLoader(hostEnv);

            LoadPlugins(loader, modConfig.Modules);

            services.AddOptions();


            //
            // CORS
            services.AddCors();

            //
            // Api Keys
            services.AddApiKeyProvider();

            //
            // Authentication
            services.AddAuthentication();
            services.AddAuthorization(o =>
            {
                o.AddPolicy("AccessToken", p => p.RequireAuthenticatedUser().RequireClaim(Core.Security.ClaimTypes.AccessToken));

                o.AddPolicy("Administrators", p => p.RequireAuthenticatedUser().RequireRole("Administrators"));

                o.AddPolicy("AdministrativeGroup", p => p.RequireAuthenticatedUser().RequireAssertion(authContext =>
                                                                                                      IsUserInAdministrators(authContext, Configuration)
                                                                                                      ));
            });

            //
            // Antiforgery
            services.TryAddSingleton <IAntiforgeryTokenStore, AntiForgeryTokenStore>();
            services.AddAntiforgery();
            services.AddAntiforgery(o =>
            {
                o.RequireSsl = true;
                o.CookieName = o.FormFieldName = Core.Http.HeaderNames.XSRF_TOKEN;
            });

            //
            // MVC
            IMvcBuilder builder = services.AddMvc(o => {
                // Replace default json output formatter
                o.OutputFormatters.RemoveType <AspNetCore.Mvc.Formatters.JsonOutputFormatter>();

                var settings = JsonSerializerSettingsProvider.CreateSerializerSettings();
                o.OutputFormatters.Add(new JsonOutputFormatter(settings, System.Buffers.ArrayPool <char> .Shared));

                // TODO
                // Workaround filter to fix Object Results returned from controllers
                // Remove when https://github.com/aspnet/Mvc/issues/4960 is resolved
                o.Filters.Add(typeof(Fix4960ActionFilter));

                o.Filters.Add(typeof(ResourceInfoFilter));

                RemoveFilter <UnsupportedContentTypeFilter>(o);
            });

            foreach (var asm in loader.GetAllLoadedAssemblies())
            {
                builder.AddApplicationPart(asm);
            }

            builder.AddControllersAsServices();
            builder.AddWebApiConventions();
        }
コード例 #11
0
 public static IMvcBuilder AddSecureApi(this IMvcBuilder builder, IServiceCollection services)
 {
     builder.AddApplicationPart(typeof(SecureApiControllerBase).Assembly);
     builder.AddControllersAsServices();
     return(builder);
 }
コード例 #12
0
        // This method gets called by a runtime.
        // Use this method to add services to the container
        public void ConfigureServices(IServiceCollection services)
        {
            //
            // IHttpContextAccessor
            services.AddSingleton <IHttpContextAccessor, HttpContextAccessor>();

            //
            // Logging
            services.AddApiLogging();

            //
            // Auditing
            services.AddApiAuditing();

            //
            // Files
            services.AddFileProvider();

            //
            // Load plugins
            ModuleConfig modConfig = new ModuleConfig(_hostingEnv.GetConfigPath("modules.json"));
            ModuleLoader loader    = new ModuleLoader(_hostingEnv);

            LoadPlugins(loader, modConfig.Modules);
            AdminHost.Instance.ConfigureModules(services);

            //
            // CORS
            services.AddCors();

            //
            // Authentication
            services.AddBearerAuthentication();

            //
            // Authorization
            services.AddAuthorizationPolicy();

            services.AddConfigurationWriter(_hostingEnv);

            //
            // Antiforgery
            services.TryAddSingleton <IAntiforgeryTokenStore, AntiForgeryTokenStore>();
            services.AddAntiforgery(o => {
                o.RequireSsl = true;
                o.CookieName = o.FormFieldName = HeaderNames.XSRF_TOKEN;
            });

            //
            // Caching
            services.AddMemoryCache();

            //
            // MVC
            IMvcBuilder builder = services.AddMvc(o => {
                // Replace default json output formatter
                o.OutputFormatters.RemoveType <AspNetCore.Mvc.Formatters.JsonOutputFormatter>();

                var settings = JsonSerializerSettingsProvider.CreateSerializerSettings();
                o.OutputFormatters.Add(new JsonOutputFormatter(settings, System.Buffers.ArrayPool <char> .Shared));

                // TODO
                // Workaround filter to fix Object Results returned from controllers
                // Remove when https://github.com/aspnet/Mvc/issues/4960 is resolved
                o.Filters.Add(typeof(Fix4960ActionFilter));

                o.Filters.Add(typeof(ActionFoundFilter));

                o.Filters.Add(typeof(ResourceInfoFilter));

                RemoveFilter <UnsupportedContentTypeFilter>(o);
            });

            foreach (var asm in loader.GetAllLoadedAssemblies())
            {
                builder.AddApplicationPart(asm);
            }

            builder.AddControllersAsServices();
            builder.AddWebApiConventions();
        }
コード例 #13
0
 /// <summary>
 /// Register the specified <paramref name="controllerTypes"/> as services and as a source for controller
 /// discovery.
 /// </summary>
 /// <param name="builder">The <see cref="IMvcBuilder"/>.</param>
 /// <param name="controllerTypes">A sequence of controller <see cref="Type"/>s to register.</param>
 /// <returns>The <see cref="IMvcBuilder"/>.</returns>
 public static IMvcBuilder AddControllersAsServices(
     this IMvcBuilder builder,
     params Type[] controllerTypes)
 {
     return(builder.AddControllersAsServices(controllerTypes.AsEnumerable()));
 }