예제 #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 ConfigureServices(IServiceCollection services)
        {
            var config =
                new ApiConfig()
            {
                AuthTokenLength                = 32,
                PasswordResetTokenLength       = 32,
                EmailVerificationTokenLength   = 32,
                EmailVerificationTokenLifetime = new TimeSpan(30, 0, 0, 0),
                PasswordResetTokenLifetime     = new TimeSpan(2, 0, 0),
                ApiBaseAddress = Environment.GetEnvironmentVariable("API_BASE_ADDRESS")
            };

            services.AddSingleton(typeof(ApiConfig), config);

            services.AddSwaggerDocument(
                (config) =>
            {
                config.DocumentProcessors.Add(
                    new SecurityDefinitionAppender("AuthToken",
                                                   new NSwag.OpenApiSecurityScheme
                {
                    Type = NSwag.OpenApiSecuritySchemeType.ApiKey,
                    Name = "Auth-Token",
                    In   = NSwag.OpenApiSecurityApiKeyLocation.Header,
                }));
                config.OperationProcessors.Add(new OperationSecurityScopeProcessor("AuthToken"));

                config.PostProcess =
                    (document) =>
                {
                    document.Info.Version     = "v1";
                    document.Info.Title       = "gimana.id API";
                    document.Info.Description = "The backend API for gimana.id, a group project for DTETI FT UGM's enterpreunership course.";
                    document.Info.Contact     = new NSwag.OpenApiContact()
                    {
                        Name  = "Firdaus Bisma Suryakusuma",
                        Email = "*****@*****.**"
                    };
                };
            });

            #region init db
            AppDbContext dbContext = null;
            if (_env.IsDevelopment())
            {
                var devDatabaseType = Environment.GetEnvironmentVariable("DEV_DATABASE_TYPE");

                switch (devDatabaseType)
                {
                case "Concrete":
                    dbContext = new AppDbContext();
                    break;

                case "InMemory":
                    dbContext = new InMemoryAppDbContext();
                    break;

                default:
                    throw new Exception($"environment variable DEV_DATABASE_TYPE has invalid value({devDatabaseType}).");
                }
            }
            else if (_env.IsProduction())
            {
                dbContext = new AppDbContext();
            }

            if (dbContext.Users.Count() == 0)
            {
                var salt   = new SecurePasswordSaltGenerator().GenerateSecureRandomString();
                var hasher = new PasswordHasher();

                dbContext.Users.Add(
                    new User()
                {
                    Id       = Guid.NewGuid(),
                    Username = Environment.GetEnvironmentVariable("INIT_ADMIN_USERNAME"),
                    Email    = new UserEmail()
                    {
                        EmailAddress = Environment.GetEnvironmentVariable("INIT_ADMIN_EMAIL"),
                        IsVerified   = true
                    },
                    BanLiftedDate = DateTime.MinValue,
                    Privileges    = new List <UserPrivilege>()
                    {
                        new UserPrivilege()
                        {
                            PrivilegeName = "Admin"
                        }
                    },
                    PasswordCredential = new PasswordCredential()
                    {
                        HashedPassword = hasher.HashPassword(Environment.GetEnvironmentVariable("INIT_ADMIN_PASSWORD"), salt),
                        PasswordSalt   = salt
                    }
                });

                dbContext.SaveChanges();
            }
            #endregion
            services.AddTransient(
                typeof(AppDbContext),
                (serviceProvider) =>
            {
                if (_env.IsDevelopment())
                {
                    var devDatabaseType = Environment.GetEnvironmentVariable("DEV_DATABASE_TYPE");

                    switch (devDatabaseType)
                    {
                    case "Concrete":
                        return(new AppDbContext());

                    case "InMemory":
                        return(new InMemoryAppDbContext());

                    default:
                        throw new Exception($"environment variable DEV_DATABASE_TYPE has invalid value({devDatabaseType}).");
                    }
                }
                else if (_env.IsProduction())
                {
                    return(new AppDbContext());
                }
                else
                {
                    throw new Exception("unknown environment type.");
                }
            });

            services.AddSingleton(
                typeof(IMapper),
                new Mapper(new MapperConfig().GetConfiguration()));

            services.AddAuthentication(
                (config) =>
            {
                config.DefaultScheme = "RandomTokenScheme";
            })
            .AddScheme <RandomTokenAuthenticationSchemeOptions, ValidateRandomTokenAuthenticationHandler>("RandomTokenScheme", (options) => { });
            // Do we need to add `.AddCookie()` here?

            if (_env.IsDevelopment())
            {
                services.AddSingleton(
                    typeof(IEmailSender),
                    new MockEmailSender());
            }
            else if (_env.IsProduction())
            {
                services.AddSingleton(
                    typeof(IEmailSender),
                    new SmtpEmailSender(
                        Environment.GetEnvironmentVariable("EMAIL_CREDENTIAL_ADDRESS"),
                        Environment.GetEnvironmentVariable("EMAIL_CREDENTIAL_PASSWORD")));
            }

            services.AddSingleton(
                typeof(IPasswordHasher),
                new PasswordHasher());

            services.AddSingleton(
                typeof(ISecurePasswordSaltGenerator),
                new SecurePasswordSaltGenerator());

            services.AddSingleton(
                typeof(IAlphanumericTokenGenerator),
                new AlphanumericTokenGenerator());

            services.AddAuthorization(config =>
            {
                config.AddPolicy(AuthorizationPolicyConstants.EmailVerifiedPolicy, policy => policy.RequireClaim("EmailVerified", "True"));
                config.AddPolicy(AuthorizationPolicyConstants.IsNotBannedPolicy, policy => policy.RequireClaim("IsBanned", "False"));
                config.AddPolicy(AuthorizationPolicyConstants.ModeratorOnlyPolicy, policy => policy.RequireClaim("IsModerator", "True"));
                config.AddPolicy(AuthorizationPolicyConstants.AdminOnlyPolicy, policy => policy.RequireClaim("IsAdmin", "True"));
                config.AddPolicy(AuthorizationPolicyConstants.AuthenticatedUsersOnlyPolicy, policy => policy.RequireClaim("UserId"));
            });

            services.AddSpaStaticFiles(config => config.RootPath = "ClientApp/build");

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

            services.AddMvc().AddControllersAsServices();
        }