예제 #1
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureContainer(ServiceRegistry services)
        {
            services.AddMiniProfiler(opt =>
            {
                // opt.RouteBasePath = "/profiler";
                opt.ShouldProfile             = _ => true;
                opt.ShowControls              = true;
                opt.StackMaxLength            = short.MaxValue;
                opt.PopupStartHidden          = false;
                opt.PopupShowTrivial          = true;
                opt.PopupShowTimeWithChildren = true;
            });

            services.AddHttpsRedirection(options => options.HttpsPort = 443);

            // If environment is localhost, then enable CORS policy, otherwise no cross-origin access
            services.AddCors(options => options.AddPolicy("CorsPolicy", builder => builder
                                                          .WithOrigins(_configuration.GetSection("TrustedSpaUrls").Get <string[]>())
                                                          .AllowAnyHeader()
                                                          .AllowAnyMethod()
                                                          .AllowCredentials()));

            // Add framework services
            // Add functionality to inject IOptions<T>
            services.AddOptions();

            services.AddResponseCompression();

            services.Configure <JwtSettings>(_configuration.GetSection("JwtSettings"));

            services.AddLogging();

            services.AddRouting(options => options.LowercaseUrls = true);

            if (_env.IsDevelopment())
            {
                services.AddDistributedMemoryCache();
            }
            else
            {
                var redisConnectionString =
                    ConnectionStringUrlToRedisResource(_configuration.GetValue <string>("REDISTOGO_URL"));

                services.AddStackExchangeRedisCache(c => c.Configuration = redisConnectionString);
            }

            services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                options.IdleTimeout         = TimeSpan.FromMinutes(60);
                options.Cookie.HttpOnly     = true;
                options.Cookie.Name         = ApiConstants.AuthenticationSessionCookieName;
                options.Cookie.SecurePolicy = CookieSecurePolicy.None;
            });

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = "Stream-Ripper-API", Version = "v1"
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

                if (File.Exists(xmlPath))
                {
                    c.IncludeXmlComments(xmlPath);
                }

                c.AddSecurityDefinition("Bearer",
                                        new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme.",
                    Type        = SecuritySchemeType.Http,
                    Scheme      = "bearer"
                });
            });

            services.AddMvc(x =>
            {
                x.ModelValidatorProviders.Clear();

                // Not need to have https
                x.RequireHttpsPermanent = false;

                // Allow anonymous for localhost
                if (_env.IsDevelopment())
                {
                    x.Filters.Add <AllowAnonymousFilter>();
                }

                // Exception filter attribute
                x.Filters.Add <ExceptionFilterAttribute>();
            }).AddNewtonsoftJson(x =>
            {
                x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            })
            .AddRazorPagesOptions(x => x.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()));

            services.AddDbContext <EntityDbContext>(opt =>
            {
                if (_env.IsDevelopment())
                {
                    opt.UseSqlite(_configuration.GetValue <string>("ConnectionStrings:Sqlite"));
                }
                else
                {
                    var postgresConnectionString =
                        ConnectionStringUrlToPgResource(_configuration.GetValue <string>("DATABASE_URL")
                                                        ?? throw new Exception("DATABASE_URL is null"));
                    opt.UseNpgsql(postgresConnectionString);
                }
            });

            services.AddIdentity <User, IdentityRole <int> >(x => x.User.RequireUniqueEmail = true)
            .AddEntityFrameworkStores <EntityDbContext>()
            .AddRoles <IdentityRole <int> >()
            .AddDefaultTokenProviders();

            // L2 EF cache
            if (_env.IsDevelopment())
            {
                services.AddEFSecondLevelCache(options =>
                                               options.UseEasyCachingCoreProvider("memory").DisableLogging(true)
                                               );

                services.AddEasyCaching(options => options.UseInMemory("memory"));
            }
            else
            {
                services.AddEFSecondLevelCache(options =>
                                               options.UseEasyCachingCoreProvider("redis").DisableLogging(true));

                services.AddEasyCaching(options =>
                {
                    var(_, dictionary) = UrlUtility.UrlToResource(_configuration.GetValue <string>("REDISTOGO_URL"));

                    // use memory cache with your own configuration
                    options.UseRedis(x =>
                    {
                        x.DBConfig.Endpoints.Add(
                            new EasyCaching.Core.Configurations.ServerEndPoint(dictionary["Host"],
                                                                               int.Parse(dictionary["Port"])));
                        x.DBConfig.Username           = dictionary["Username"];
                        x.DBConfig.Password           = dictionary["Password"];
                        x.DBConfig.AbortOnConnectFail = false;
                    });
                });
            }

            services.AddEfRepository <EntityDbContext>(x =>
            {
                x.Profiles(Assembly.Load("Dal"), Assembly.Load("Models"));
            });

            var jwtSetting = _configuration
                             .GetSection("JwtSettings")
                             .Get <JwtSettings>();

            if (_env.IsDevelopment() && string.IsNullOrEmpty(jwtSetting.Key))
            {
                jwtSetting.Key =
                    "DCk2T4guOWvu8WRklEEmKazH5gqUJQnyCYXfzFJQU84tY0iJFeUJc2yIQqkqJ4od8AQvyXdlOFP0Q0QGWzB84W4hWFptL8APynvt";

                IdentityModelEventSource.ShowPII = true;
            }

            services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme    = JwtBearerDefaults.AuthenticationScheme;
            })
            .AddJwtBearer(config =>
            {
                config.RequireHttpsMetadata = false;
                config.SaveToken            = true;

                config.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidIssuer      = jwtSetting.Issuer,
                    ValidAudience    = jwtSetting.Audience,
                    IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSetting.Key))
                };
            });

            services.For <JwtSettings>().Use(jwtSetting).Singleton();

            // If environment is localhost then use mock email service
            if (_env.IsDevelopment())
            {
                services.For <IS3Service>().Use(new S3Service()).Singleton();
            }
            else
            {
                var(accessKeyId, secretAccessKey, url) = (
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_ACCESS_KEY_ID"),
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_SECRET_ACCESS_KEY"),
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_URL")
                    );

                var          prefix     = new Uri(url).Segments.GetValue(1)?.ToString();
                const string bucketName = "cloud-cube";

                // Generally bad practice
                var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);

                // Create S3 client
                services.For <IAmazonS3>().Use(new AmazonS3Client(credentials, RegionEndpoint.USEast1));
                services.For <S3ServiceConfig>().Use(new S3ServiceConfig(bucketName, prefix));

                services.For <IS3Service>().Use(ctx => new S3Service(
                                                    ctx.GetInstance <ILogger <S3Service> >(),
                                                    ctx.GetInstance <IAmazonS3>(),
                                                    ctx.GetInstance <S3ServiceConfig>()
                                                    ));
            }

            // Register stuff in container, using the StructureMap APIs...
            services.Scan(_ =>
            {
                _.AssemblyContainingType(typeof(Startup));
                _.Assembly("Api");
                _.Assembly("Logic");
                _.Assembly("Dal");
                _.WithDefaultConventions();
            });
        }
예제 #2
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureContainer(ServiceRegistry services)
        {
            services.AddMiniProfiler(opt =>
            {
                // opt.RouteBasePath = "/profiler";
                opt.ShouldProfile             = _ => true;
                opt.ShowControls              = true;
                opt.StackMaxLength            = short.MaxValue;
                opt.PopupStartHidden          = false;
                opt.PopupShowTrivial          = true;
                opt.PopupShowTimeWithChildren = true;
            });

            services.AddHttpsRedirection(options => options.HttpsPort = 443);

            // Add framework services
            // Add functionality to inject IOptions<T>
            services.AddOptions();

            services.AddResponseCompression();

            services.AddLogging();

            services.AddRouting(options => options.LowercaseUrls = true);

            services.AddDistributedMemoryCache();

            services.AddSession(options =>
            {
                // Set a short timeout for easy testing.
                options.IdleTimeout         = TimeSpan.FromMinutes(60);
                options.Cookie.HttpOnly     = true;
                options.Cookie.Name         = ApiConstants.AuthenticationSessionCookieName;
                options.Cookie.SecurePolicy = CookieSecurePolicy.None;
            });

            // Make sure a JS engine is registered, or you will get an error!
            services.AddJsEngineSwitcher(options => options.DefaultEngineName = ChakraCoreJsEngine.EngineName)
            .AddChakraCore();

            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo {
                    Title = ApplicationName, Version = "v1"
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);

                if (File.Exists(xmlPath))
                {
                    c.IncludeXmlComments(xmlPath);
                }

                c.AddSecurityDefinition("Bearer", // Name the security scheme
                                        new OpenApiSecurityScheme
                {
                    Description = "JWT Authorization header using the Bearer scheme.",
                    Type        = SecuritySchemeType.Http,
                    Scheme      = "bearer"
                });
            });

            services.AddMvc(x =>
            {
                // Not need to have https
                x.RequireHttpsPermanent = false;

                // Allow anonymous for localhost
                if (_env.IsDevelopment())
                {
                    x.Filters.Add <AllowAnonymousFilter>();
                }

                // Exception filter attribute
                x.Filters.Add <ExceptionFilterAttribute>();
            })
            .AddViewOptions(x =>
            {
                x.HtmlHelperOptions.ClientValidationEnabled = true;
            })
            .AddNewtonsoftJson(x =>
            {
                x.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
                x.SerializerSettings.Converters.Add(new StringEnumConverter {
                    NamingStrategy = new CamelCaseNamingStrategy()
                });
                x.SerializerSettings.ContractResolver =
                    new CamelCasePropertyNamesContractResolver();

                x.SerializerSettings.ContractResolver = new IgnoreUserContractResolver();
            })
            .AddRazorPagesOptions(x => x.Conventions.ConfigureFilter(new IgnoreAntiforgeryTokenAttribute()));

            services.AddWebMarkupMin(opt =>
            {
                opt.AllowMinificationInDevelopmentEnvironment = true;
                opt.AllowCompressionInDevelopmentEnvironment  = true;
            })
            .AddHtmlMinification()
            .AddHttpCompression();

            // If using Kestrel:
            services.Configure <KestrelServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            // If using IIS:
            services.Configure <IISServerOptions>(options =>
            {
                options.AllowSynchronousIO = true;
            });

            services.AddDbContext <EntityDbContext>(opt =>
            {
                if (_env.IsDevelopment())
                {
                    opt.UseSqlite(_configuration.GetValue <string>("ConnectionStrings:Sqlite"));
                }
                else
                {
                    var postgresConnectionString =
                        ConnectionStringUrlToPgResource(_configuration.GetValue <string>("DATABASE_URL")
                                                        ?? throw new Exception("DATABASE_URL is null"));
                    opt.UseNpgsql(postgresConnectionString);
                }
            }, ServiceLifetime.Transient);

            services.AddIdentity <User, IdentityRole <int> >(x => x.User.RequireUniqueEmail = true)
            .AddEntityFrameworkStores <EntityDbContext>()
            .AddRoles <IdentityRole <int> >()
            .AddDefaultTokenProviders();

            // L2 EF cache
            if (_env.IsDevelopment())
            {
                services.AddEFSecondLevelCache(options =>
                                               options.UseEasyCachingCoreProvider("memory").DisableLogging(true)
                                               );

                services.AddEasyCaching(options => options.UseInMemory("memory"));
            }
            else
            {
                services.AddEFSecondLevelCache(options =>
                                               options.UseEasyCachingCoreProvider("redis").DisableLogging(true));

                services.AddEasyCaching(options =>
                {
                    var(_, dictionary) = UrlUtility.UrlToResource(_configuration.GetValue <string>("REDISTOGO_URL"));

                    // use memory cache with your own configuration
                    options.UseRedis(x =>
                    {
                        x.DBConfig.Endpoints.Add(new ServerEndPoint(dictionary["Host"], int.Parse(dictionary["Port"])));
                        x.DBConfig.Username           = dictionary["Username"];
                        x.DBConfig.Password           = dictionary["Password"];
                        x.DBConfig.AbortOnConnectFail = false;
                    });
                });
            }

            services.AddEfRepository <EntityDbContext>(x =>
            {
                x.Profiles(Assembly.Load("Dal"), Assembly.Load("Models"));
            });

            services.AddAutoMapper(Assembly.Load("Models"));

            services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(x =>
            {
                x.Cookie.MaxAge = TimeSpan.FromMinutes(60);
                x.LoginPath     = new PathString("/Login/");
                x.LogoutPath    = new PathString("/Logout/");
            });

            services.For <GlobalConfigs>().Use(new GlobalConfigs()).Singleton();

            // Initialize the email jet client
            services.For <IMailjetClient>().Use(new MailjetClient(
                                                    _configuration.GetValue <string>("MAIL_JET_KEY"),
                                                    _configuration.GetValue <string>("MAIL_JET_SECRET"))
                                                ).Singleton();

            // If environment is localhost then use mock email service
            if (_env.IsDevelopment())
            {
                services.For <IS3Service>().Use(new S3Service()).Singleton();
                services.For <IEmailServiceApi>().Use(new EmailServiceApi()).Singleton();
            }
            else
            {
                var(accessKeyId, secretAccessKey, url) = (
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_ACCESS_KEY_ID"),
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_SECRET_ACCESS_KEY"),
                    _configuration.GetRequiredValue <string>("CLOUDCUBE_URL")
                    );

                var          prefix     = new Uri(url).Segments.GetValue(1)?.ToString();
                const string bucketName = "cloud-cube";

                // Generally bad practice
                var credentials = new BasicAWSCredentials(accessKeyId, secretAccessKey);

                // Create S3 client
                services.For <IAmazonS3>().Use(new AmazonS3Client(credentials, RegionEndpoint.USEast1));
                services.For <S3ServiceConfig>().Use(new S3ServiceConfig(bucketName, prefix));

                services.For <IS3Service>().Use(ctx => new S3Service(
                                                    ctx.GetInstance <ILogger <S3Service> >(),
                                                    ctx.GetInstance <IAmazonS3>(),
                                                    ctx.GetInstance <S3ServiceConfig>()
                                                    ));

                services.For <MailGunConfig>().Use(new MailGunConfig
                {
                    ApiKey = _configuration.GetRequiredValue <string>("MAILGUN_API_KEY"),
                    Domain = _configuration.GetRequiredValue <string>("MAILGUN_DOMAIN")
                });
            }

            // Register stuff in container, using the StructureMap APIs...
            services.Scan(_ =>
            {
                _.AssemblyContainingType(typeof(Startup));
                _.Assembly("Api");
                _.Assembly("Logic");
                _.Assembly("Dal");
                _.WithDefaultConventions();
            });
        }