Initial Commit
commit
15ffe475c7
|
|
@ -0,0 +1,275 @@
|
|||
|
||||
# Created by https://www.gitignore.io/api/aspnetcore
|
||||
# Edit at https://www.gitignore.io/?templates=aspnetcore
|
||||
|
||||
### ASPNETCore ###
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
|
||||
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||
*.userprefs
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
[Ll]og/
|
||||
|
||||
# Visual Studio 2015 cache/options directory
|
||||
.vs/
|
||||
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||
#wwwroot/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
# NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
# DNX
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opendb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
*.VC.db
|
||||
*.VC.VC.opendb
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
*.sap
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding add-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# Visual Studio code coverage results
|
||||
*.coverage
|
||||
*.coveragexml
|
||||
|
||||
# NCrunch
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
nCrunchTemp_*
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||
# but database connection strings (with potential passwords) will be unencrypted
|
||||
*.pubxml
|
||||
*.publishproj
|
||||
|
||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||
# in these scripts will be unencrypted
|
||||
PublishScripts/
|
||||
|
||||
# NuGet Packages
|
||||
*.nupkg
|
||||
# The packages folder can be ignored because of Package Restore
|
||||
**/packages/*
|
||||
# except build/, which is used as an MSBuild target.
|
||||
!**/packages/build/
|
||||
# Uncomment if necessary however generally it will be regenerated when needed
|
||||
#!**/packages/repositories.config
|
||||
# NuGet v3's project.json files produces more ignoreable files
|
||||
*.nuget.props
|
||||
*.nuget.targets
|
||||
|
||||
# Microsoft Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Microsoft Azure Emulator
|
||||
ecf/
|
||||
rcf/
|
||||
|
||||
# Windows Store app package directories and files
|
||||
AppPackages/
|
||||
BundleArtifacts/
|
||||
Package.StoreAssociation.xml
|
||||
_pkginfo.txt
|
||||
|
||||
# Visual Studio cache files
|
||||
# files ending in .cache can be ignored
|
||||
*.[Cc]ache
|
||||
# but keep track of directories ending in .cache
|
||||
!*.[Cc]ache/
|
||||
|
||||
# Others
|
||||
ClientBin/
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.jfm
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
orleans.codegen.cs
|
||||
|
||||
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||
#bower_components/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file
|
||||
# to a newer Visual Studio version. Backup files are not needed,
|
||||
# because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
# GhostDoc plugin setting file
|
||||
*.GhostDoc.xml
|
||||
|
||||
# Node.js Tools for Visual Studio
|
||||
.ntvs_analysis.dat
|
||||
|
||||
# Visual Studio 6 build log
|
||||
*.plg
|
||||
|
||||
# Visual Studio 6 workspace options file
|
||||
*.opt
|
||||
|
||||
# Visual Studio LightSwitch build output
|
||||
**/*.HTMLClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/GeneratedArtifacts
|
||||
**/*.DesktopClient/ModelManifest.xml
|
||||
**/*.Server/GeneratedArtifacts
|
||||
**/*.Server/ModelManifest.xml
|
||||
_Pvt_Extensions
|
||||
|
||||
# Paket dependency manager
|
||||
.paket/paket.exe
|
||||
paket-files/
|
||||
|
||||
# FAKE - F# Make
|
||||
.fake/
|
||||
|
||||
# JetBrains Rider
|
||||
.idea/
|
||||
*.sln.iml
|
||||
|
||||
# CodeRush
|
||||
.cr/
|
||||
|
||||
# Python Tools for Visual Studio (PTVS)
|
||||
__pycache__/
|
||||
*.pyc
|
||||
|
||||
# Cake - Uncomment if you are using it
|
||||
# tools/
|
||||
|
||||
# End of https://www.gitignore.io/api/aspnetcore
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace OFBButte.Api.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
[ApiController]
|
||||
public class ValuesController : ControllerBase
|
||||
{
|
||||
// GET api/values
|
||||
[HttpGet]
|
||||
public ActionResult<IEnumerable<string>> Get()
|
||||
{
|
||||
return new string[] { "value1", "value2" };
|
||||
}
|
||||
|
||||
// GET api/values/5
|
||||
[HttpGet("{id}")]
|
||||
public ActionResult<string> Get(int id)
|
||||
{
|
||||
return "value";
|
||||
}
|
||||
|
||||
// POST api/values
|
||||
[HttpPost]
|
||||
public void Post([FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// PUT api/values/5
|
||||
[HttpPut("{id}")]
|
||||
public void Put(int id, [FromBody] string value)
|
||||
{
|
||||
}
|
||||
|
||||
// DELETE api/values/5
|
||||
[HttpDelete("{id}")]
|
||||
public void Delete(int id)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OFBButte.Application\OFBButte.Application.csproj" />
|
||||
<ProjectReference Include="..\OFBButte.Database\OFBButte.Database.csproj" />
|
||||
<ProjectReference Include="..\OFBButte.Entities\OFBButte.Entities.csproj" />
|
||||
<ProjectReference Include="..\OFBButte.Infrastructure\OFBButte.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace OFBButte.Api
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateWebHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
|
||||
WebHost.CreateDefaultBuilder(args)
|
||||
.UseStartup<Startup>();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:50405",
|
||||
"sslPort": 44314
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"OFBButte.Api": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "api/values",
|
||||
"applicationUrl": "https://localhost:5001;http://localhost:5000",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using OFBButte.Application.Configuration;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Database;
|
||||
|
||||
namespace OFBButte.Api
|
||||
{
|
||||
public class Startup
|
||||
{
|
||||
public Startup(IConfiguration configuration)
|
||||
{
|
||||
Configuration = configuration;
|
||||
}
|
||||
|
||||
public IConfiguration Configuration { get; }
|
||||
|
||||
// This method gets called by the runtime. Use this method to add services to the container.
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
|
||||
|
||||
// App Settings
|
||||
services.Configure<AppSettings>(Configuration.GetSection("App"));
|
||||
|
||||
// DB Context
|
||||
services.AddDbContext<OFBContext>(o =>
|
||||
{
|
||||
OFBContext.UseMySql(o, Configuration.GetConnectionString("OFBContext"));
|
||||
});
|
||||
services.AddScoped<IOFBContext, OFBContext>(s => s.GetService<OFBContext>());
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
|
||||
{
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
app.UseDeveloperExceptionPage();
|
||||
}
|
||||
else
|
||||
{
|
||||
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
|
||||
app.UseHsts();
|
||||
}
|
||||
|
||||
app.UseHttpsRedirection();
|
||||
app.UseMvc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"System": "Information",
|
||||
"Microsoft": "Information"
|
||||
}
|
||||
},
|
||||
"App": {
|
||||
"Environment": "Dev"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"OFBContext": "server=localhost;database=ofbtest;user=ofbapi;password=87hjdusiodksyeunsjkdis7"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*",
|
||||
"App": {
|
||||
"Environment": "Local"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"OFBContext": "server=localhost;database=ofbtest;user=ofbapi;password=87hjdusiodksyeunsjkdis7"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using OFBButte.Application.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Base
|
||||
{
|
||||
public class AuthorizeCommand
|
||||
{
|
||||
private readonly IAccess access;
|
||||
protected readonly IEnumerable<Permission> allowedPermissions;
|
||||
private AuthorizeCommand(IAccess access)
|
||||
{
|
||||
this.access = access;
|
||||
}
|
||||
public AuthorizeCommand(IAccess access, Permission permission): this(access)
|
||||
{
|
||||
this.allowedPermissions = new Permission[] { permission };
|
||||
}
|
||||
public AuthorizeCommand(IAccess access, IEnumerable<Permission> permissions): this(access)
|
||||
{
|
||||
this.allowedPermissions = permissions;
|
||||
}
|
||||
|
||||
public void Authorize()
|
||||
{
|
||||
if (allowedPermissions == null)
|
||||
{
|
||||
throw new UnauthorizedAccessException("Permission Denied");
|
||||
}
|
||||
foreach(var permission in allowedPermissions)
|
||||
{
|
||||
if (access.CanDo(permission))
|
||||
return;
|
||||
}
|
||||
throw new UnauthorizedAccessException($"Permission Denied: {string.Join(", ", allowedPermissions)}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using OFBButte.Application.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Base
|
||||
{
|
||||
public interface IAccess
|
||||
{
|
||||
bool CanDo(Permission permission);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Codes
|
||||
{
|
||||
public interface ICodeGenerator
|
||||
{
|
||||
string Generate(int byteSize = 16);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Configuration
|
||||
{
|
||||
public class AppSettings
|
||||
{
|
||||
public string Environment { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Configuration
|
||||
{
|
||||
public class ConnectionStrings
|
||||
{
|
||||
public string OFBContext { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Configuration
|
||||
{
|
||||
public class Permission
|
||||
{
|
||||
public string Value { get; private set; }
|
||||
private Permission(string permission)
|
||||
{
|
||||
Value = permission;
|
||||
}
|
||||
|
||||
public static Permission AddProfile { get; } = new Permission("Add Profile");
|
||||
|
||||
private static Dictionary<string, Permission> values = typeof(Permission).GetProperties(System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static).Where(p => p.PropertyType == typeof(Permission)).ToDictionary(p => p.Name, p => (Permission)p.GetValue(null));
|
||||
public static bool TryCast(string input, out Permission permission)
|
||||
{
|
||||
permission = null;
|
||||
if (values.TryGetValue(input, out Permission perm))
|
||||
{
|
||||
permission = perm;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static implicit operator string(Permission input)
|
||||
{
|
||||
return input.Value;
|
||||
}
|
||||
|
||||
public static explicit operator Permission(string input)
|
||||
{
|
||||
if (TryCast(input, out Permission permission))
|
||||
{
|
||||
return permission;
|
||||
} else
|
||||
{
|
||||
throw new InvalidCastException($"Could not cast {input} to {typeof(Permission).ToString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Database
|
||||
{
|
||||
public interface IOFBContext
|
||||
{
|
||||
DbSet<User> Users { get; set; }
|
||||
DbSet<Profile> Profiles { get; set; }
|
||||
DbSet<EmailVerificationCode> EmailVerificationCodes { get; set; }
|
||||
DbSet<PasswordResetCode> PasswordResetCodes { get; set; }
|
||||
DbSet<MissionarySupport> MissionarySupportForms { get; set; }
|
||||
int SaveChanges();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Email
|
||||
{
|
||||
public abstract class EmailMessage
|
||||
{
|
||||
public virtual string To { get; set; }
|
||||
public virtual string From { get; set; } = "donotreply@ofbbutte.com";
|
||||
public virtual string Subject { get; set; }
|
||||
public virtual string Body { get; set; }
|
||||
public abstract string TemplateName { get; set; }
|
||||
|
||||
public void SetBodyFromTemplate(bool isTest = true)
|
||||
{
|
||||
string baseHtml = System.IO.File.ReadAllText($@"Email\Templates\base.html");
|
||||
string template = System.IO.File.ReadAllText($@"Email\Templates\{TemplateName}.html");
|
||||
baseHtml = baseHtml.Replace("{{TEST}}", isTest ? "THIS IS A TEST" : "");
|
||||
template = baseHtml.Replace("{{CONTENT}}", template);
|
||||
var props = GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public).ToDictionary(p => p.Name, p => p.GetValue(this)?.ToString() ?? "");
|
||||
foreach (var property in props)
|
||||
{
|
||||
template = template.Replace($"{{{{{property.Key}}}}}", property.Value);
|
||||
}
|
||||
Body = template;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Application.Email
|
||||
{
|
||||
public interface IEmailSender
|
||||
{
|
||||
Task Send(EmailMessage message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Email
|
||||
{
|
||||
public class PasswordResetEmailMessage : EmailMessage
|
||||
{
|
||||
public override string TemplateName { get; set; } = "PasswordResetEmailMessage";
|
||||
public override string Subject { get; set; } = "OFB Butte: Password Reset";
|
||||
|
||||
public string Url { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<p>
|
||||
Please click the link below to reset your password.
|
||||
</p>
|
||||
<a href="{{Url}}">{{Url}}</a>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<p>
|
||||
Please verify your email by clicking the link below.
|
||||
</p>
|
||||
<a href="{{VerificationUrl}}">{{VerificationUrl}}</a>
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
<!DOCTYPE html>
|
||||
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title></title>
|
||||
</head>
|
||||
<body>
|
||||
{{TEST}}
|
||||
{{CONTENT}}
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Email
|
||||
{
|
||||
public class VerifyEmailMessage : EmailMessage
|
||||
{
|
||||
public override string TemplateName { get; set; } = "VerifyEmailMessage";
|
||||
public override string Subject { get; set; } = "OFB Butte: Email Verification";
|
||||
|
||||
// Email Properties
|
||||
public string VerificationUrl { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Exceptions
|
||||
{
|
||||
public class ValidationException: Exception
|
||||
{
|
||||
public ValidationException(string message): base(message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Missionary
|
||||
{
|
||||
public class AddMissionarySupportForm
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public AddMissionarySupportForm(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public MissionarySupport Handle(MissionarySupport support)
|
||||
{
|
||||
support.Id = 0;
|
||||
context.MissionarySupportForms.Add(support);
|
||||
context.SaveChanges();
|
||||
return support;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Missionary
|
||||
{
|
||||
public class GetMissionarySupportForm
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public GetMissionarySupportForm(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public MissionarySupport Handle(int id)
|
||||
{
|
||||
return context.MissionarySupportForms.FirstOrDefault(m => m.Id == id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OFBButte.Entities\OFBButte.Entities.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using OFBButte.Application.Base;
|
||||
using OFBButte.Application.Codes;
|
||||
using OFBButte.Application.Configuration;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class AddProfile: AuthorizeCommand
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly ICodeGenerator codes;
|
||||
public AddProfile(IAccess access, IOFBContext context, ICodeGenerator codes)
|
||||
:base(access, Permission.AddProfile)
|
||||
{
|
||||
this.context = context;
|
||||
this.codes = codes;
|
||||
}
|
||||
|
||||
public Profile Handle(Profile profile)
|
||||
{
|
||||
base.Authorize();
|
||||
|
||||
return Handle(profile.FirstName, profile.LastName, profile.Street, profile.City, profile.State, profile.Zip, profile.Country);
|
||||
}
|
||||
|
||||
public Profile Handle(string first, string last, string street, string city, string state, string zip, string country)
|
||||
{
|
||||
base.Authorize();
|
||||
|
||||
var profile = new Profile()
|
||||
{
|
||||
FirstName = first,
|
||||
LastName = last,
|
||||
Street = street,
|
||||
City = city,
|
||||
State = state,
|
||||
Zip = zip,
|
||||
Country = country,
|
||||
ModifiedDate = DateTime.Now,
|
||||
ProfileFederationCode = new ProfileFederationCode()
|
||||
{
|
||||
CreatedDate = DateTime.Now,
|
||||
Code = codes.Generate()
|
||||
}
|
||||
};
|
||||
context.Profiles.Add(profile);
|
||||
context.SaveChanges();
|
||||
return profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
using OFBButte.Application.Database;
|
||||
using OFBButte.Application.Exceptions;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class AddUser
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly IPasswordHasher hasher;
|
||||
public AddUser(IOFBContext context, IPasswordHasher hasher)
|
||||
{
|
||||
this.context = context;
|
||||
this.hasher = hasher;
|
||||
}
|
||||
|
||||
public User Handle(string email, string password)
|
||||
{
|
||||
// Check to see if email already exists
|
||||
var existingUser = context.Users.FirstOrDefault(u => u.Email == email);
|
||||
if (existingUser != null)
|
||||
throw new ValidationException("User with email already exists");
|
||||
|
||||
// Create the new user
|
||||
var user = new Entities.User()
|
||||
{
|
||||
Email = email,
|
||||
CreatedDate = DateTime.Now,
|
||||
Password = hasher.HashPassword(password)
|
||||
};
|
||||
|
||||
// Save to db
|
||||
context.Users.Add(user);
|
||||
context.SaveChanges();
|
||||
return user;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
using OFBButte.Application.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class DeleteUser
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public DeleteUser(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
public void Handle(string email)
|
||||
{
|
||||
// Get the user
|
||||
var user = context.Users.FirstOrDefault(u => u.Email == email && u.DeletedDate == null);
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
user.DeletedDate = DateTime.Now;
|
||||
context.SaveChanges();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using OFBButte.Application.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class FederateProfile
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public FederateProfile(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public bool Handle(string email, string lastName, string federationCode)
|
||||
{
|
||||
// Get the user
|
||||
var user = context.Users.FirstOrDefault(u => u.Email == email && u.Profile == null);
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
// Get the profile
|
||||
var profile = context.Profiles.FirstOrDefault(p => p.ProfileFederationCode.Code == federationCode && p.LastName == lastName);
|
||||
if (profile == null)
|
||||
return false;
|
||||
|
||||
user.Profile = profile;
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public interface IPasswordHasher
|
||||
{
|
||||
string HashPassword(string password);
|
||||
bool VerifyPassword(string hashedPassword, string password);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class LoginUser
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly IPasswordHasher hasher;
|
||||
public LoginUser(IOFBContext context, IPasswordHasher hasher)
|
||||
{
|
||||
this.context = context;
|
||||
this.hasher = hasher;
|
||||
}
|
||||
public User Handle(string email, string password)
|
||||
{
|
||||
var user = context.Users.FirstOrDefault(u => u.Email == email);
|
||||
if (user == null)
|
||||
throw new Exception("Could not find email: " + email);
|
||||
|
||||
var validPassword = hasher.VerifyPassword(user.Password, password);
|
||||
|
||||
if (validPassword)
|
||||
{
|
||||
return user;
|
||||
} else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
using OFBButte.Application.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class ResetPassword
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly IPasswordHasher hasher;
|
||||
public ResetPassword(IOFBContext context, IPasswordHasher hasher)
|
||||
{
|
||||
this.context = context;
|
||||
this.hasher = hasher;
|
||||
}
|
||||
|
||||
public bool Handle(int codeId, string code, string newPassword)
|
||||
{
|
||||
// Get user
|
||||
var dte = DateTime.Now.AddHours(-1);
|
||||
var user = context.Users.FirstOrDefault(u => u.PassswordResetCode.Id == codeId && u.PassswordResetCode.Code == code && u.PassswordResetCode.CreatedDate >= dte);
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
user.Password = hasher.HashPassword(newPassword);
|
||||
context.PasswordResetCodes.Remove(user.PassswordResetCode);
|
||||
user.PassswordResetCode = null;
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using OFBButte.Application.Codes;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Application.Email;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class SendEmailValidation
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly IEmailSender emailSender;
|
||||
private readonly ICodeGenerator codes;
|
||||
public SendEmailValidation(IOFBContext context, IEmailSender emailSender, ICodeGenerator codes)
|
||||
{
|
||||
this.context = context;
|
||||
this.emailSender = emailSender;
|
||||
this.codes = codes;
|
||||
}
|
||||
|
||||
public async Task Handle(string email)
|
||||
{
|
||||
var user = context.Users.Include(u => u.EmailVerificationCode).FirstOrDefault(u => u.Email == email);
|
||||
if (user == null)
|
||||
throw new Exception($"Could not find user with email: {email}");
|
||||
|
||||
if (user.EmailVerificationCode != null)
|
||||
{
|
||||
context.EmailVerificationCodes.Remove(user.EmailVerificationCode);
|
||||
}
|
||||
|
||||
// Generate verification code
|
||||
user.EmailVerificationCode = new Entities.EmailVerificationCode()
|
||||
{
|
||||
Code = codes.Generate(),
|
||||
CreatedDate = DateTime.Now
|
||||
};
|
||||
|
||||
context.SaveChanges();
|
||||
|
||||
// Create the email
|
||||
var emailMessage = new VerifyEmailMessage()
|
||||
{
|
||||
To = email,
|
||||
From = "donotreply@ofbbutte.com",
|
||||
VerificationUrl = $"https://ofbbutte.com/user/emailverification?c={user.EmailVerificationCode.Id}&code={user.EmailVerificationCode.Code}"
|
||||
};
|
||||
|
||||
await emailSender.Send(emailMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using OFBButte.Application.Codes;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Application.Email;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class SendResetPasswordEmail
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
private readonly IEmailSender emailSender;
|
||||
private readonly ICodeGenerator codes;
|
||||
|
||||
public SendResetPasswordEmail(IOFBContext context, IEmailSender emailSender, ICodeGenerator codes)
|
||||
{
|
||||
this.context = context;
|
||||
this.emailSender = emailSender;
|
||||
this.codes = codes;
|
||||
}
|
||||
|
||||
public async Task Handle(string email, string lastName)
|
||||
{
|
||||
// Get the user
|
||||
var user = context.Users.Include(u => u.PassswordResetCode).FirstOrDefault(u => u.Email == email && u.Profile.LastName == lastName);
|
||||
if (user == null)
|
||||
return;
|
||||
|
||||
if (user.PassswordResetCode != null)
|
||||
{
|
||||
context.PasswordResetCodes.Remove(user.PassswordResetCode);
|
||||
}
|
||||
|
||||
user.PassswordResetCode = new Entities.PasswordResetCode()
|
||||
{
|
||||
CreatedDate = DateTime.Now,
|
||||
Code = codes.Generate()
|
||||
};
|
||||
|
||||
context.SaveChanges();
|
||||
|
||||
var message = new PasswordResetEmailMessage()
|
||||
{
|
||||
To = user.Email,
|
||||
Url = $"http://ofbbutte.com/user/resetpassword?c={user.PassswordResetCode.Id}&code={user.PassswordResetCode.Code}"
|
||||
};
|
||||
|
||||
await emailSender.Send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class UpdateProfile
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public UpdateProfile(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public Profile Handle(string email, Profile profile)
|
||||
{
|
||||
// Get the user
|
||||
var user = context.Users.Include(u => u.Profile).FirstOrDefault(u => u.Email == email);
|
||||
if (user == null || user.Profile == null)
|
||||
return null;
|
||||
|
||||
user.Profile.City = profile.City;
|
||||
user.Profile.Country = profile.Country;
|
||||
user.Profile.FirstName = profile.FirstName;
|
||||
user.Profile.LastName = profile.LastName;
|
||||
user.Profile.ModifiedDate = DateTime.Now;
|
||||
user.Profile.State = profile.State;
|
||||
user.Profile.Street = profile.Street;
|
||||
user.Profile.Zip = profile.Zip;
|
||||
|
||||
context.SaveChanges();
|
||||
return user.Profile;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
using OFBButte.Application.Database;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Application.Users
|
||||
{
|
||||
public class VerifyEmail
|
||||
{
|
||||
private readonly IOFBContext context;
|
||||
public VerifyEmail(IOFBContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public bool Handle(int codeId, string code)
|
||||
{
|
||||
var dte = DateTime.Now.AddHours(-1);
|
||||
var user = context.Users.FirstOrDefault(u => u.EmailVerificationCode.Id == codeId && u.EmailVerificationCode.Code == code && u.EmailVerifiedDate > dte);
|
||||
if (user == null)
|
||||
return false;
|
||||
|
||||
user.EmailVerifiedDate = DateTime.Now;
|
||||
context.SaveChanges();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
using Microsoft.Extensions.Options;
|
||||
using OFBButte.Application.Configuration;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Application.Email;
|
||||
using OFBButte.Application.Users;
|
||||
using OFBButte.Infrastructure.Hashing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Console
|
||||
{
|
||||
public class App
|
||||
{
|
||||
private readonly AppSettings appSettings;
|
||||
private readonly IEmailSender emailSender;
|
||||
private readonly IOFBContext context;
|
||||
private string user = "djabsher@gmail.com";
|
||||
private string pass = "my password";
|
||||
|
||||
public App(IOptions<AppSettings> appSettings, IOFBContext context, IEmailSender emailSender)
|
||||
{
|
||||
this.appSettings = appSettings.Value;
|
||||
this.emailSender = emailSender;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public async Task Run()
|
||||
{
|
||||
var env = appSettings.Environment;
|
||||
try
|
||||
{
|
||||
await SendVerificationEmail();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw ex;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void AddUser()
|
||||
{
|
||||
var adder = new AddUser(context, new PasswordHasher());
|
||||
var result = adder.Handle(user, pass);
|
||||
}
|
||||
|
||||
private async Task SendVerificationEmail()
|
||||
{
|
||||
var adder = new SendEmailValidation(context, emailSender, new Infrastructure.Codes.CodeGenerator());
|
||||
await adder.Handle(user);
|
||||
}
|
||||
|
||||
private void LoginUser()
|
||||
{
|
||||
var login = new LoginUser(context, new PasswordHasher());
|
||||
var result = login.Handle(user, pass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OFBButte.Application\OFBButte.Application.csproj" />
|
||||
<ProjectReference Include="..\OFBButte.Database\OFBButte.Database.csproj" />
|
||||
<ProjectReference Include="..\OFBButte.Infrastructure\OFBButte.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using OFBButte.Application.Configuration;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Application.Email;
|
||||
using OFBButte.Database;
|
||||
using OFBButte.Infrastructure.Email;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Console
|
||||
{
|
||||
class Program
|
||||
{
|
||||
|
||||
static ServiceProvider services;
|
||||
|
||||
static async Task Main(string[] args)
|
||||
{
|
||||
SetupDI();
|
||||
|
||||
await services.GetService<App>().Run();
|
||||
}
|
||||
|
||||
static void SetupDI()
|
||||
{
|
||||
var builder = new ConfigurationBuilder();
|
||||
builder.AddJsonFile("appsettings.json", false, true);
|
||||
var config = builder.Build();
|
||||
|
||||
|
||||
var serviceCollection = new ServiceCollection();
|
||||
serviceCollection.Configure<AppSettings>(a => config.GetSection("app").Bind(a));
|
||||
|
||||
serviceCollection.AddSingleton<IEmailSender>(new EmailSender());
|
||||
serviceCollection.AddDbContext<OFBContext>(o => OFBContext.UseMySql(o, config.GetConnectionString("OFBContext")));
|
||||
serviceCollection.AddScoped<IOFBContext, OFBContext>(s => s.GetService<OFBContext>());
|
||||
serviceCollection.AddTransient<App>();
|
||||
services = serviceCollection.BuildServiceProvider();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using OFBButte.Database;
|
||||
|
||||
namespace OFBButte.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(OFBContext))]
|
||||
[Migration("20190717032510_Initial")]
|
||||
partial class Initial
|
||||
{
|
||||
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.EmailVerificationCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("EmailVerificationCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryChild", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("MissionarySupportId");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MissionarySupportId");
|
||||
|
||||
b.ToTable("MissionaryChild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryCollegeRecommendation", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("MissionarySupportId");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MissionarySupportId");
|
||||
|
||||
b.ToTable("MissionaryCollegeRecommendation");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionarySupport", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("AdmittedWrong");
|
||||
|
||||
b.Property<bool>("Alcohol");
|
||||
|
||||
b.Property<string>("AloneOrTeam");
|
||||
|
||||
b.Property<string>("BibleVersionOpinion");
|
||||
|
||||
b.Property<string>("BibleVersionsUsed");
|
||||
|
||||
b.Property<string>("BillsOnTime");
|
||||
|
||||
b.Property<string>("CallToField");
|
||||
|
||||
b.Property<string>("CellPhone");
|
||||
|
||||
b.Property<string>("Charasmaticism");
|
||||
|
||||
b.Property<int>("ChildrenSchool");
|
||||
|
||||
b.Property<bool>("ContemporaryMusic");
|
||||
|
||||
b.Property<string>("CorrectWrongOfAnotherMissionary");
|
||||
|
||||
b.Property<decimal>("CurrentMonthlySupport");
|
||||
|
||||
b.Property<int>("DailyBible");
|
||||
|
||||
b.Property<bool>("Dance");
|
||||
|
||||
b.Property<bool>("Divorced");
|
||||
|
||||
b.Property<string>("EvaluationOfNationals");
|
||||
|
||||
b.Property<string>("FellowshipAssociation");
|
||||
|
||||
b.Property<bool>("FemaleDressStandard");
|
||||
|
||||
b.Property<int>("FemaleShorts");
|
||||
|
||||
b.Property<int>("FemaleSlacks");
|
||||
|
||||
b.Property<string>("FieldOfService");
|
||||
|
||||
b.Property<string>("FieldPhone");
|
||||
|
||||
b.Property<string>("FinancialStatementPrevYear");
|
||||
|
||||
b.Property<bool>("Fundamentalist");
|
||||
|
||||
b.Property<bool>("GroundsForRemarry");
|
||||
|
||||
b.Property<string>("HomePhone");
|
||||
|
||||
b.Property<string>("LateBillActionTaken");
|
||||
|
||||
b.Property<string>("LateBills");
|
||||
|
||||
b.Property<bool>("MaleHair");
|
||||
|
||||
b.Property<bool>("MarryADivorcee");
|
||||
|
||||
b.Property<bool>("MasonicLodge");
|
||||
|
||||
b.Property<decimal>("MonthlySupportNeeded");
|
||||
|
||||
b.Property<bool>("MovieTheaters");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<double>("NumberLedToChrist");
|
||||
|
||||
b.Property<double>("NumberWeeklyTracts");
|
||||
|
||||
b.Property<double>("NumberWitnessedTo");
|
||||
|
||||
b.Property<string>("Plans");
|
||||
|
||||
b.Property<string>("PotentialHarvest");
|
||||
|
||||
b.Property<string>("Predestination");
|
||||
|
||||
b.Property<string>("RateOfSuccess");
|
||||
|
||||
b.Property<string>("RepentanceDefinition");
|
||||
|
||||
b.Property<bool>("RepentanceNecessary");
|
||||
|
||||
b.Property<string>("RestAndRelaxation");
|
||||
|
||||
b.Property<string>("SendingChurch");
|
||||
|
||||
b.Property<bool>("Smoking");
|
||||
|
||||
b.Property<string>("SwimmingClothing");
|
||||
|
||||
b.Property<string>("Television");
|
||||
|
||||
b.Property<string>("Testimony");
|
||||
|
||||
b.Property<string>("TimeInCountry");
|
||||
|
||||
b.Property<bool>("Tongues");
|
||||
|
||||
b.Property<string>("WifesName");
|
||||
|
||||
b.Property<bool>("WorldlyMusic");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MissionarySupportForms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.PasswordResetCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PasswordResetCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("City");
|
||||
|
||||
b.Property<string>("Country");
|
||||
|
||||
b.Property<string>("FirstName");
|
||||
|
||||
b.Property<string>("LastName");
|
||||
|
||||
b.Property<DateTime>("ModifiedDate");
|
||||
|
||||
b.Property<int?>("ProfileFederationCodeId");
|
||||
|
||||
b.Property<string>("State");
|
||||
|
||||
b.Property<string>("Street");
|
||||
|
||||
b.Property<string>("Zip");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileFederationCodeId");
|
||||
|
||||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.ProfileFederationCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ProfileFederationCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.Property<DateTime?>("DeletedDate");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("EmailVerificationCodeId");
|
||||
|
||||
b.Property<DateTime?>("EmailVerifiedDate");
|
||||
|
||||
b.Property<int?>("PassswordResetCodeId");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ProfileId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Email");
|
||||
|
||||
b.HasIndex("EmailVerificationCodeId");
|
||||
|
||||
b.HasIndex("PassswordResetCodeId");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryChild", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.MissionarySupport")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("MissionarySupportId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryCollegeRecommendation", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.MissionarySupport")
|
||||
.WithMany("CollegeRecommendations")
|
||||
.HasForeignKey("MissionarySupportId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.Profile", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.ProfileFederationCode", "ProfileFederationCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileFederationCodeId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.User", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.EmailVerificationCode", "EmailVerificationCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("EmailVerificationCodeId");
|
||||
|
||||
b.HasOne("OFBButte.Entities.PasswordResetCode", "PassswordResetCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("PassswordResetCodeId");
|
||||
|
||||
b.HasOne("OFBButte.Entities.Profile", "Profile")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,287 @@
|
|||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Metadata;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
namespace OFBButte.Database.Migrations
|
||||
{
|
||||
public partial class Initial : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "EmailVerificationCodes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Code = table.Column<string>(nullable: true),
|
||||
CreatedDate = table.Column<DateTime>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_EmailVerificationCodes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "MissionarySupportForms",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
HomePhone = table.Column<string>(nullable: true),
|
||||
CellPhone = table.Column<string>(nullable: true),
|
||||
FieldPhone = table.Column<string>(nullable: true),
|
||||
WifesName = table.Column<string>(nullable: true),
|
||||
Testimony = table.Column<string>(nullable: true),
|
||||
CallToField = table.Column<string>(nullable: true),
|
||||
SendingChurch = table.Column<string>(nullable: true),
|
||||
FieldOfService = table.Column<string>(nullable: true),
|
||||
Plans = table.Column<string>(nullable: true),
|
||||
EvaluationOfNationals = table.Column<string>(nullable: true),
|
||||
TimeInCountry = table.Column<string>(nullable: true),
|
||||
CorrectWrongOfAnotherMissionary = table.Column<string>(nullable: true),
|
||||
FinancialStatementPrevYear = table.Column<string>(nullable: true),
|
||||
CurrentMonthlySupport = table.Column<decimal>(nullable: false),
|
||||
MonthlySupportNeeded = table.Column<decimal>(nullable: false),
|
||||
RestAndRelaxation = table.Column<string>(nullable: true),
|
||||
AloneOrTeam = table.Column<string>(nullable: true),
|
||||
ChildrenSchool = table.Column<int>(nullable: false),
|
||||
Dance = table.Column<bool>(nullable: false),
|
||||
WorldlyMusic = table.Column<bool>(nullable: false),
|
||||
MovieTheaters = table.Column<bool>(nullable: false),
|
||||
Alcohol = table.Column<bool>(nullable: false),
|
||||
Smoking = table.Column<bool>(nullable: false),
|
||||
MaleHair = table.Column<bool>(nullable: false),
|
||||
FemaleSlacks = table.Column<int>(nullable: false),
|
||||
FemaleShorts = table.Column<int>(nullable: false),
|
||||
FemaleDressStandard = table.Column<bool>(nullable: false),
|
||||
SwimmingClothing = table.Column<string>(nullable: true),
|
||||
Television = table.Column<string>(nullable: true),
|
||||
DailyBible = table.Column<int>(nullable: false),
|
||||
NumberLedToChrist = table.Column<double>(nullable: false),
|
||||
NumberWitnessedTo = table.Column<double>(nullable: false),
|
||||
NumberWeeklyTracts = table.Column<double>(nullable: false),
|
||||
RateOfSuccess = table.Column<string>(nullable: true),
|
||||
Predestination = table.Column<string>(nullable: true),
|
||||
FellowshipAssociation = table.Column<string>(nullable: true),
|
||||
AdmittedWrong = table.Column<string>(nullable: true),
|
||||
Divorced = table.Column<bool>(nullable: false),
|
||||
GroundsForRemarry = table.Column<bool>(nullable: false),
|
||||
MarryADivorcee = table.Column<bool>(nullable: false),
|
||||
MasonicLodge = table.Column<bool>(nullable: false),
|
||||
BibleVersionsUsed = table.Column<string>(nullable: true),
|
||||
BibleVersionOpinion = table.Column<string>(nullable: true),
|
||||
ContemporaryMusic = table.Column<bool>(nullable: false),
|
||||
Charasmaticism = table.Column<string>(nullable: true),
|
||||
Tongues = table.Column<bool>(nullable: false),
|
||||
RepentanceNecessary = table.Column<bool>(nullable: false),
|
||||
RepentanceDefinition = table.Column<string>(nullable: true),
|
||||
Fundamentalist = table.Column<bool>(nullable: false),
|
||||
BillsOnTime = table.Column<string>(nullable: true),
|
||||
LateBills = table.Column<string>(nullable: true),
|
||||
LateBillActionTaken = table.Column<string>(nullable: true),
|
||||
PotentialHarvest = table.Column<string>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_MissionarySupportForms", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "PasswordResetCodes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Code = table.Column<string>(nullable: true),
|
||||
CreatedDate = table.Column<DateTime>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_PasswordResetCodes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "ProfileFederationCodes",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Code = table.Column<string>(nullable: true),
|
||||
CreatedDate = table.Column<DateTime>(nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_ProfileFederationCodes", x => x.Id);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "MissionaryChild",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
MissionarySupportId = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_MissionaryChild", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_MissionaryChild_MissionarySupportForms_MissionarySupportId",
|
||||
column: x => x.MissionarySupportId,
|
||||
principalTable: "MissionarySupportForms",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "MissionaryCollegeRecommendation",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Name = table.Column<string>(nullable: true),
|
||||
MissionarySupportId = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_MissionaryCollegeRecommendation", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_MissionaryCollegeRecommendation_MissionarySupportForms_Missi~",
|
||||
column: x => x.MissionarySupportId,
|
||||
principalTable: "MissionarySupportForms",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Profiles",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
ModifiedDate = table.Column<DateTime>(nullable: false),
|
||||
FirstName = table.Column<string>(nullable: true),
|
||||
LastName = table.Column<string>(nullable: true),
|
||||
Street = table.Column<string>(nullable: true),
|
||||
City = table.Column<string>(nullable: true),
|
||||
State = table.Column<string>(nullable: true),
|
||||
Zip = table.Column<string>(nullable: true),
|
||||
Country = table.Column<string>(nullable: true),
|
||||
ProfileFederationCodeId = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Profiles", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Profiles_ProfileFederationCodes_ProfileFederationCodeId",
|
||||
column: x => x.ProfileFederationCodeId,
|
||||
principalTable: "ProfileFederationCodes",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "Users",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(nullable: false)
|
||||
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
|
||||
Email = table.Column<string>(nullable: false),
|
||||
Password = table.Column<string>(nullable: false),
|
||||
EmailVerifiedDate = table.Column<DateTime>(nullable: true),
|
||||
CreatedDate = table.Column<DateTime>(nullable: false),
|
||||
DeletedDate = table.Column<DateTime>(nullable: true),
|
||||
ProfileId = table.Column<int>(nullable: true),
|
||||
EmailVerificationCodeId = table.Column<int>(nullable: true),
|
||||
PassswordResetCodeId = table.Column<int>(nullable: true)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_Users", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_Users_EmailVerificationCodes_EmailVerificationCodeId",
|
||||
column: x => x.EmailVerificationCodeId,
|
||||
principalTable: "EmailVerificationCodes",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Users_PasswordResetCodes_PassswordResetCodeId",
|
||||
column: x => x.PassswordResetCodeId,
|
||||
principalTable: "PasswordResetCodes",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
table.ForeignKey(
|
||||
name: "FK_Users_Profiles_ProfileId",
|
||||
column: x => x.ProfileId,
|
||||
principalTable: "Profiles",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
});
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_MissionaryChild_MissionarySupportId",
|
||||
table: "MissionaryChild",
|
||||
column: "MissionarySupportId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_MissionaryCollegeRecommendation_MissionarySupportId",
|
||||
table: "MissionaryCollegeRecommendation",
|
||||
column: "MissionarySupportId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Profiles_ProfileFederationCodeId",
|
||||
table: "Profiles",
|
||||
column: "ProfileFederationCodeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_Email",
|
||||
table: "Users",
|
||||
column: "Email");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_EmailVerificationCodeId",
|
||||
table: "Users",
|
||||
column: "EmailVerificationCodeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_PassswordResetCodeId",
|
||||
table: "Users",
|
||||
column: "PassswordResetCodeId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Users_ProfileId",
|
||||
table: "Users",
|
||||
column: "ProfileId");
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "MissionaryChild");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "MissionaryCollegeRecommendation");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Users");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "MissionarySupportForms");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "EmailVerificationCodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "PasswordResetCodes");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "Profiles");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "ProfileFederationCodes");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,316 @@
|
|||
// <auto-generated />
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using OFBButte.Database;
|
||||
|
||||
namespace OFBButte.Database.Migrations
|
||||
{
|
||||
[DbContext(typeof(OFBContext))]
|
||||
partial class OFBContextModelSnapshot : ModelSnapshot
|
||||
{
|
||||
protected override void BuildModel(ModelBuilder modelBuilder)
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "2.2.6-servicing-10079")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 64);
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.EmailVerificationCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("EmailVerificationCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryChild", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("MissionarySupportId");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MissionarySupportId");
|
||||
|
||||
b.ToTable("MissionaryChild");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryCollegeRecommendation", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<int?>("MissionarySupportId");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("MissionarySupportId");
|
||||
|
||||
b.ToTable("MissionaryCollegeRecommendation");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionarySupport", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("AdmittedWrong");
|
||||
|
||||
b.Property<bool>("Alcohol");
|
||||
|
||||
b.Property<string>("AloneOrTeam");
|
||||
|
||||
b.Property<string>("BibleVersionOpinion");
|
||||
|
||||
b.Property<string>("BibleVersionsUsed");
|
||||
|
||||
b.Property<string>("BillsOnTime");
|
||||
|
||||
b.Property<string>("CallToField");
|
||||
|
||||
b.Property<string>("CellPhone");
|
||||
|
||||
b.Property<string>("Charasmaticism");
|
||||
|
||||
b.Property<int>("ChildrenSchool");
|
||||
|
||||
b.Property<bool>("ContemporaryMusic");
|
||||
|
||||
b.Property<string>("CorrectWrongOfAnotherMissionary");
|
||||
|
||||
b.Property<decimal>("CurrentMonthlySupport");
|
||||
|
||||
b.Property<int>("DailyBible");
|
||||
|
||||
b.Property<bool>("Dance");
|
||||
|
||||
b.Property<bool>("Divorced");
|
||||
|
||||
b.Property<string>("EvaluationOfNationals");
|
||||
|
||||
b.Property<string>("FellowshipAssociation");
|
||||
|
||||
b.Property<bool>("FemaleDressStandard");
|
||||
|
||||
b.Property<int>("FemaleShorts");
|
||||
|
||||
b.Property<int>("FemaleSlacks");
|
||||
|
||||
b.Property<string>("FieldOfService");
|
||||
|
||||
b.Property<string>("FieldPhone");
|
||||
|
||||
b.Property<string>("FinancialStatementPrevYear");
|
||||
|
||||
b.Property<bool>("Fundamentalist");
|
||||
|
||||
b.Property<bool>("GroundsForRemarry");
|
||||
|
||||
b.Property<string>("HomePhone");
|
||||
|
||||
b.Property<string>("LateBillActionTaken");
|
||||
|
||||
b.Property<string>("LateBills");
|
||||
|
||||
b.Property<bool>("MaleHair");
|
||||
|
||||
b.Property<bool>("MarryADivorcee");
|
||||
|
||||
b.Property<bool>("MasonicLodge");
|
||||
|
||||
b.Property<decimal>("MonthlySupportNeeded");
|
||||
|
||||
b.Property<bool>("MovieTheaters");
|
||||
|
||||
b.Property<string>("Name");
|
||||
|
||||
b.Property<double>("NumberLedToChrist");
|
||||
|
||||
b.Property<double>("NumberWeeklyTracts");
|
||||
|
||||
b.Property<double>("NumberWitnessedTo");
|
||||
|
||||
b.Property<string>("Plans");
|
||||
|
||||
b.Property<string>("PotentialHarvest");
|
||||
|
||||
b.Property<string>("Predestination");
|
||||
|
||||
b.Property<string>("RateOfSuccess");
|
||||
|
||||
b.Property<string>("RepentanceDefinition");
|
||||
|
||||
b.Property<bool>("RepentanceNecessary");
|
||||
|
||||
b.Property<string>("RestAndRelaxation");
|
||||
|
||||
b.Property<string>("SendingChurch");
|
||||
|
||||
b.Property<bool>("Smoking");
|
||||
|
||||
b.Property<string>("SwimmingClothing");
|
||||
|
||||
b.Property<string>("Television");
|
||||
|
||||
b.Property<string>("Testimony");
|
||||
|
||||
b.Property<string>("TimeInCountry");
|
||||
|
||||
b.Property<bool>("Tongues");
|
||||
|
||||
b.Property<string>("WifesName");
|
||||
|
||||
b.Property<bool>("WorldlyMusic");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("MissionarySupportForms");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.PasswordResetCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("PasswordResetCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.Profile", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("City");
|
||||
|
||||
b.Property<string>("Country");
|
||||
|
||||
b.Property<string>("FirstName");
|
||||
|
||||
b.Property<string>("LastName");
|
||||
|
||||
b.Property<DateTime>("ModifiedDate");
|
||||
|
||||
b.Property<int?>("ProfileFederationCodeId");
|
||||
|
||||
b.Property<string>("State");
|
||||
|
||||
b.Property<string>("Street");
|
||||
|
||||
b.Property<string>("Zip");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("ProfileFederationCodeId");
|
||||
|
||||
b.ToTable("Profiles");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.ProfileFederationCode", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<string>("Code");
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("ProfileFederationCodes");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.User", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd();
|
||||
|
||||
b.Property<DateTime>("CreatedDate");
|
||||
|
||||
b.Property<DateTime?>("DeletedDate");
|
||||
|
||||
b.Property<string>("Email")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("EmailVerificationCodeId");
|
||||
|
||||
b.Property<DateTime?>("EmailVerifiedDate");
|
||||
|
||||
b.Property<int?>("PassswordResetCodeId");
|
||||
|
||||
b.Property<string>("Password")
|
||||
.IsRequired();
|
||||
|
||||
b.Property<int?>("ProfileId");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("Email");
|
||||
|
||||
b.HasIndex("EmailVerificationCodeId");
|
||||
|
||||
b.HasIndex("PassswordResetCodeId");
|
||||
|
||||
b.HasIndex("ProfileId");
|
||||
|
||||
b.ToTable("Users");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryChild", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.MissionarySupport")
|
||||
.WithMany("Children")
|
||||
.HasForeignKey("MissionarySupportId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.MissionaryCollegeRecommendation", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.MissionarySupport")
|
||||
.WithMany("CollegeRecommendations")
|
||||
.HasForeignKey("MissionarySupportId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.Profile", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.ProfileFederationCode", "ProfileFederationCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileFederationCodeId");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("OFBButte.Entities.User", b =>
|
||||
{
|
||||
b.HasOne("OFBButte.Entities.EmailVerificationCode", "EmailVerificationCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("EmailVerificationCodeId");
|
||||
|
||||
b.HasOne("OFBButte.Entities.PasswordResetCode", "PassswordResetCode")
|
||||
.WithMany()
|
||||
.HasForeignKey("PassswordResetCodeId");
|
||||
|
||||
b.HasOne("OFBButte.Entities.Profile", "Profile")
|
||||
.WithMany()
|
||||
.HasForeignKey("ProfileId");
|
||||
});
|
||||
#pragma warning restore 612, 618
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.2.6" />
|
||||
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OFBButte.Application\OFBButte.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
using Microsoft.EntityFrameworkCore;
|
||||
using OFBButte.Application.Database;
|
||||
using OFBButte.Entities;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Database
|
||||
{
|
||||
public class OFBContext : DbContext, IOFBContext
|
||||
{
|
||||
public OFBContext(DbContextOptions<OFBContext> options)
|
||||
: base(options)
|
||||
{ }
|
||||
|
||||
public static void UseMySql(DbContextOptionsBuilder optionsBuilder, string connString)
|
||||
{
|
||||
optionsBuilder.UseMySql(connString);
|
||||
}
|
||||
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<Profile> Profiles { get; set; }
|
||||
public DbSet<ProfileFederationCode> ProfileFederationCodes { get; set; }
|
||||
public DbSet<EmailVerificationCode> EmailVerificationCodes { get; set; }
|
||||
public DbSet<PasswordResetCode> PasswordResetCodes { get; set; }
|
||||
public DbSet<MissionarySupport> MissionarySupportForms { get; set; }
|
||||
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
{
|
||||
base.OnModelCreating(modelBuilder);
|
||||
|
||||
modelBuilder.Entity<User>(e =>
|
||||
{
|
||||
e.HasKey(x => x.Id);
|
||||
e.HasIndex(x => x.Email);
|
||||
e.Property(x => x.Email).IsRequired();
|
||||
e.Property(x => x.Password).IsRequired();
|
||||
e.Property(x => x.CreatedDate).IsRequired();
|
||||
e.HasOne(x => x.EmailVerificationCode);
|
||||
e.HasOne(x => x.Profile);
|
||||
e.HasOne(x => x.PassswordResetCode);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<EmailVerificationCode>(e => {
|
||||
e.HasKey(x => x.Id);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<Profile>(e => {
|
||||
e.HasKey(x => x.Id);
|
||||
e.HasOne(x => x.ProfileFederationCode);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<ProfileFederationCode>(e => {
|
||||
e.HasKey(x => x.Id);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PasswordResetCode>(e => {
|
||||
e.HasKey(x => x.Id);
|
||||
});
|
||||
|
||||
modelBuilder.Entity<MissionarySupport>(e => {
|
||||
e.HasKey(x => x.Id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class EmailVerificationCode
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Code { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
namespace OFBButte.Entities
|
||||
{
|
||||
public enum BibleReading
|
||||
{
|
||||
Always = 1,
|
||||
Sometimes = 2,
|
||||
Rarely = 3
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace OFBButte.Entities
|
||||
{
|
||||
public enum ChildrenSchool
|
||||
{
|
||||
Christian = 1,
|
||||
Public = 2,
|
||||
Home = 3,
|
||||
Other = 5
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace OFBButte.Entities
|
||||
{
|
||||
public enum FemaleShorts
|
||||
{
|
||||
Rarely = 1,
|
||||
Often = 2,
|
||||
Sports = 3,
|
||||
Never = 4
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
namespace OFBButte.Entities
|
||||
{
|
||||
public enum FemaleSlacks
|
||||
{
|
||||
Rarely = 1,
|
||||
Often = 2,
|
||||
Sports = 3,
|
||||
Never = 4
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class MissionaryChild
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class MissionaryCollegeRecommendation
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class MissionarySupport
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string HomePhone { get; set; }
|
||||
public string CellPhone { get; set; }
|
||||
public string FieldPhone { get; set; }
|
||||
public string WifesName { get; set; }
|
||||
public MissionaryChild[] Children { get; set; }
|
||||
public string Testimony { get; set; }
|
||||
public string CallToField { get; set; }
|
||||
public string SendingChurch { get; set; }
|
||||
public string FieldOfService { get; set; }
|
||||
public string Plans { get; set; }
|
||||
public string EvaluationOfNationals { get; set; }
|
||||
public string TimeInCountry { get; set; }
|
||||
public string CorrectWrongOfAnotherMissionary { get; set; }
|
||||
public string FinancialStatementPrevYear { get; set; }
|
||||
public decimal CurrentMonthlySupport { get; set; }
|
||||
public decimal MonthlySupportNeeded { get; set; }
|
||||
public string RestAndRelaxation { get; set; }
|
||||
public string AloneOrTeam { get; set; }
|
||||
public ChildrenSchool ChildrenSchool { get; set; }
|
||||
public bool Dance { get; set; }
|
||||
public bool WorldlyMusic { get; set; }
|
||||
public bool MovieTheaters { get; set; }
|
||||
public bool Alcohol { get; set; }
|
||||
public bool Smoking { get; set; }
|
||||
public bool MaleHair { get; set; }
|
||||
public FemaleSlacks FemaleSlacks { get; set; }
|
||||
public FemaleShorts FemaleShorts { get; set; }
|
||||
public bool FemaleDressStandard { get; set; }
|
||||
public string SwimmingClothing { get; set; }
|
||||
public string Television { get; set; }
|
||||
public BibleReading DailyBible { get; set; }
|
||||
public double NumberLedToChrist { get; set; }
|
||||
public double NumberWitnessedTo { get; set; }
|
||||
public double NumberWeeklyTracts { get; set; }
|
||||
public string RateOfSuccess { get; set; }
|
||||
public string Predestination { get; set; }
|
||||
public string FellowshipAssociation { get; set; }
|
||||
public MissionaryCollegeRecommendation[] CollegeRecommendations { get; set; }
|
||||
public string AdmittedWrong { get; set; }
|
||||
public bool Divorced { get; set; }
|
||||
public bool GroundsForRemarry { get; set; }
|
||||
public bool MarryADivorcee { get; set; }
|
||||
public bool MasonicLodge { get; set; }
|
||||
public string BibleVersionsUsed { get; set; }
|
||||
public string BibleVersionOpinion { get; set; }
|
||||
public bool ContemporaryMusic { get; set; }
|
||||
public string Charasmaticism { get; set; }
|
||||
public bool Tongues { get; set; }
|
||||
public bool RepentanceNecessary { get; set; }
|
||||
public string RepentanceDefinition { get; set; }
|
||||
public bool Fundamentalist { get; set; }
|
||||
public string BillsOnTime { get; set; }
|
||||
public string LateBills { get; set; }
|
||||
public string LateBillActionTaken { get; set; }
|
||||
public string PotentialHarvest { get; set; }
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class PasswordResetCode
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Code { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class Profile
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public DateTime ModifiedDate { get; set; }
|
||||
public string FirstName { get; set; }
|
||||
public string LastName { get; set; }
|
||||
public string Street { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string Zip { get; set; }
|
||||
public string Country { get; set; }
|
||||
|
||||
public ProfileFederationCode ProfileFederationCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class ProfileFederationCode
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Code { get; set; }
|
||||
public DateTime CreatedDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Entities
|
||||
{
|
||||
public class User
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Email { get; set; }
|
||||
public string Password { get; set; }
|
||||
public DateTime? EmailVerifiedDate { get; set; }
|
||||
|
||||
public DateTime CreatedDate { get; set; }
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
|
||||
public Profile Profile { get; set; }
|
||||
public EmailVerificationCode EmailVerificationCode { get; set; }
|
||||
public PasswordResetCode PassswordResetCode { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
using OFBButte.Application.Codes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Infrastructure.Codes
|
||||
{
|
||||
public class CodeGenerator: ICodeGenerator
|
||||
{
|
||||
public string Generate(int byteSize = 16)
|
||||
{
|
||||
byte[] codeBytes = new byte[byteSize];
|
||||
RandomNumberGenerator.Create().GetBytes(codeBytes);
|
||||
string code = Convert.ToBase64String(codeBytes).TrimEnd('=').Replace('+', '-').Replace('/', '_');
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
using MailKit.Net.Smtp;
|
||||
using MimeKit;
|
||||
using OFBButte.Application.Email;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace OFBButte.Infrastructure.Email
|
||||
{
|
||||
public class EmailSender : IEmailSender, IDisposable
|
||||
{
|
||||
private readonly SmtpClient client;
|
||||
private readonly bool isTest;
|
||||
|
||||
public EmailSender(bool isTest = true)
|
||||
{
|
||||
this.isTest = isTest;
|
||||
client = new SmtpClient();
|
||||
}
|
||||
|
||||
public async Task Send(EmailMessage message)
|
||||
{
|
||||
message.SetBodyFromTemplate(isTest);
|
||||
var mm = new MimeMessage();
|
||||
mm.From.Add(new MailboxAddress(message.From));
|
||||
mm.To.Add(new MailboxAddress(message.To));
|
||||
mm.Subject = message.Subject;
|
||||
var bodyBuilder = new BodyBuilder();
|
||||
bodyBuilder.HtmlBody = message.Body;
|
||||
mm.Body = bodyBuilder.ToMessageBody();
|
||||
|
||||
client.Connect("smtp.webfaction.com", 465, true);
|
||||
client.Authenticate("ofbcontact", "2014OfbPwd");
|
||||
await client.SendAsync(mm);
|
||||
client.Disconnect(true);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,215 @@
|
|||
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
|
||||
using OFBButte.Application.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Infrastructure.Hashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements the standard Identity password hashing.
|
||||
/// </summary>
|
||||
public class PasswordHasher: IPasswordHasher
|
||||
{
|
||||
/* =======================
|
||||
* HASHED PASSWORD FORMATS
|
||||
* =======================
|
||||
*
|
||||
* Version 3:
|
||||
* PBKDF2 with HMAC-SHA256, 128-bit salt, 256-bit subkey, 10000 iterations.
|
||||
* Format: { 0x01, prf (UInt32), iter count (UInt32), salt length (UInt32), salt, subkey }
|
||||
* (All UInt32s are stored big-endian.)
|
||||
*/
|
||||
|
||||
private readonly int _iterCount;
|
||||
private readonly RandomNumberGenerator _rng;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="PasswordHasher{TUser}"/>.
|
||||
/// </summary>
|
||||
/// <param name="optionsAccessor">The options for this instance.</param>
|
||||
public PasswordHasher(PasswordHasherOptions optionsAccessor = null)
|
||||
{
|
||||
var options = optionsAccessor ?? new PasswordHasherOptions();
|
||||
|
||||
_iterCount = options.IterationCount;
|
||||
_rng = options.Rng;
|
||||
}
|
||||
|
||||
// Compares two byte arrays for equality. The method is specifically written so that the loop is not optimized.
|
||||
[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
|
||||
private static bool ByteArraysEqual(byte[] a, byte[] b)
|
||||
{
|
||||
if (a == null && b == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (a == null || b == null || a.Length != b.Length)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var areSame = true;
|
||||
for (var i = 0; i < a.Length; i++)
|
||||
{
|
||||
areSame &= (a[i] == b[i]);
|
||||
}
|
||||
return areSame;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.
|
||||
/// </summary>
|
||||
/// <param name="password">The password to hash.</param>
|
||||
/// <returns>A hashed representation of the supplied <paramref name="password"/> for the specified <paramref name="user"/>.</returns>
|
||||
public virtual string HashPassword(string password)
|
||||
{
|
||||
if (password == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(password));
|
||||
}
|
||||
|
||||
return Convert.ToBase64String(HashPasswordV3(password, _rng));
|
||||
}
|
||||
|
||||
private byte[] HashPasswordV3(string password, RandomNumberGenerator rng)
|
||||
{
|
||||
return HashPasswordV3(password, rng,
|
||||
prf: KeyDerivationPrf.HMACSHA256,
|
||||
iterCount: _iterCount,
|
||||
saltSize: 128 / 8,
|
||||
numBytesRequested: 256 / 8);
|
||||
}
|
||||
|
||||
private static byte[] HashPasswordV3(string password, RandomNumberGenerator rng, KeyDerivationPrf prf, int iterCount, int saltSize, int numBytesRequested)
|
||||
{
|
||||
// Produce a version 3 (see comment above) text hash.
|
||||
byte[] salt = new byte[saltSize];
|
||||
rng.GetBytes(salt);
|
||||
byte[] subkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, numBytesRequested);
|
||||
|
||||
var outputBytes = new byte[13 + salt.Length + subkey.Length];
|
||||
outputBytes[0] = 0x01; // format marker
|
||||
WriteNetworkByteOrder(outputBytes, 1, (uint)prf);
|
||||
WriteNetworkByteOrder(outputBytes, 5, (uint)iterCount);
|
||||
WriteNetworkByteOrder(outputBytes, 9, (uint)saltSize);
|
||||
Buffer.BlockCopy(salt, 0, outputBytes, 13, salt.Length);
|
||||
Buffer.BlockCopy(subkey, 0, outputBytes, 13 + saltSize, subkey.Length);
|
||||
return outputBytes;
|
||||
}
|
||||
|
||||
private static uint ReadNetworkByteOrder(byte[] buffer, int offset)
|
||||
{
|
||||
return ((uint)(buffer[offset + 0]) << 24)
|
||||
| ((uint)(buffer[offset + 1]) << 16)
|
||||
| ((uint)(buffer[offset + 2]) << 8)
|
||||
| ((uint)(buffer[offset + 3]));
|
||||
}
|
||||
|
||||
public bool VerifyPassword(string hashedPassword, string password)
|
||||
{
|
||||
var result = VerifyHashedPassword(hashedPassword, password);
|
||||
return result == PasswordVerificationResult.Success;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.
|
||||
/// </summary>
|
||||
/// <param name="user">The user whose password should be verified.</param>
|
||||
/// <param name="hashedPassword">The hash value for a user's stored password.</param>
|
||||
/// <param name="providedPassword">The password supplied for comparison.</param>
|
||||
/// <returns>A <see cref="PasswordVerificationResult"/> indicating the result of a password hash comparison.</returns>
|
||||
/// <remarks>Implementations of this method should be time consistent.</remarks>
|
||||
public virtual PasswordVerificationResult VerifyHashedPassword(string hashedPassword, string providedPassword)
|
||||
{
|
||||
if (hashedPassword == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(hashedPassword));
|
||||
}
|
||||
if (providedPassword == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(providedPassword));
|
||||
}
|
||||
|
||||
byte[] decodedHashedPassword = Convert.FromBase64String(hashedPassword);
|
||||
|
||||
// read the format marker from the hashed password
|
||||
if (decodedHashedPassword.Length == 0)
|
||||
{
|
||||
return PasswordVerificationResult.Failed;
|
||||
}
|
||||
switch (decodedHashedPassword[0])
|
||||
{
|
||||
case 0x00:
|
||||
return PasswordVerificationResult.Failed;
|
||||
|
||||
case 0x01:
|
||||
int embeddedIterCount;
|
||||
if (VerifyHashedPasswordV3(decodedHashedPassword, providedPassword, out embeddedIterCount))
|
||||
{
|
||||
// If this hasher was configured with a higher iteration count, change the entry now.
|
||||
return (embeddedIterCount < _iterCount)
|
||||
? PasswordVerificationResult.SuccessRehashNeeded
|
||||
: PasswordVerificationResult.Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
return PasswordVerificationResult.Failed;
|
||||
}
|
||||
|
||||
default:
|
||||
return PasswordVerificationResult.Failed; // unknown format marker
|
||||
}
|
||||
}
|
||||
|
||||
private static bool VerifyHashedPasswordV3(byte[] hashedPassword, string password, out int iterCount)
|
||||
{
|
||||
iterCount = default(int);
|
||||
|
||||
try
|
||||
{
|
||||
// Read header information
|
||||
KeyDerivationPrf prf = (KeyDerivationPrf)ReadNetworkByteOrder(hashedPassword, 1);
|
||||
iterCount = (int)ReadNetworkByteOrder(hashedPassword, 5);
|
||||
int saltLength = (int)ReadNetworkByteOrder(hashedPassword, 9);
|
||||
|
||||
// Read the salt: must be >= 128 bits
|
||||
if (saltLength < 128 / 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] salt = new byte[saltLength];
|
||||
Buffer.BlockCopy(hashedPassword, 13, salt, 0, salt.Length);
|
||||
|
||||
// Read the subkey (the rest of the payload): must be >= 128 bits
|
||||
int subkeyLength = hashedPassword.Length - 13 - salt.Length;
|
||||
if (subkeyLength < 128 / 8)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
byte[] expectedSubkey = new byte[subkeyLength];
|
||||
Buffer.BlockCopy(hashedPassword, 13 + salt.Length, expectedSubkey, 0, expectedSubkey.Length);
|
||||
|
||||
// Hash the incoming password and verify it
|
||||
byte[] actualSubkey = KeyDerivation.Pbkdf2(password, salt, prf, iterCount, subkeyLength);
|
||||
return ByteArraysEqual(actualSubkey, expectedSubkey);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// This should never occur except in the case of a malformed payload, where
|
||||
// we might go off the end of the array. Regardless, a malformed payload
|
||||
// implies verification failed.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteNetworkByteOrder(byte[] buffer, int offset, uint value)
|
||||
{
|
||||
buffer[offset + 0] = (byte)(value >> 24);
|
||||
buffer[offset + 1] = (byte)(value >> 16);
|
||||
buffer[offset + 2] = (byte)(value >> 8);
|
||||
buffer[offset + 3] = (byte)(value >> 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Infrastructure.Hashing
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies options for password hashing.
|
||||
/// </summary>
|
||||
public class PasswordHasherOptions
|
||||
{
|
||||
private static readonly RandomNumberGenerator _defaultRng = RandomNumberGenerator.Create(); // secure PRNG
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of iterations used when hashing passwords using PBKDF2. Default is 10,000.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The number of iterations used when hashing passwords using PBKDF2.
|
||||
/// </value>
|
||||
/// <remarks>
|
||||
/// This value is only used when the compatibility mode is set to 'V3'.
|
||||
/// The value must be a positive integer.
|
||||
/// </remarks>
|
||||
public int IterationCount { get; set; } = 10000;
|
||||
|
||||
// for unit testing
|
||||
internal RandomNumberGenerator Rng { get; set; } = _defaultRng;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OFBButte.Infrastructure.Hashing
|
||||
{
|
||||
// <summary>
|
||||
/// Specifies the results for password verification.
|
||||
/// </summary>
|
||||
public enum PasswordVerificationResult
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates password verification failed.
|
||||
/// </summary>
|
||||
Failed = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates password verification was successful.
|
||||
/// </summary>
|
||||
Success = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates password verification was successful however the password was encoded using a deprecated algorithm
|
||||
/// and should be rehashed and updated.
|
||||
/// </summary>
|
||||
SuccessRehashNeeded = 2
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MailKit" Version="2.2.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Cryptography.KeyDerivation" Version="2.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\OFBButte.Application\OFBButte.Application.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29102.190
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Api", "OFBButte.Api\OFBButte.Api.csproj", "{FF5F4D78-6419-47E4-A7CE-5B25503BE2D7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Application", "OFBButte.Application\OFBButte.Application.csproj", "{8BCA31C6-C10D-4865-BAE8-6DC932B4797D}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Console", "OFBButte.Console\OFBButte.Console.csproj", "{82FA36EC-1CBC-4F9A-B436-A61D9AA6D1C7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Database", "OFBButte.Database\OFBButte.Database.csproj", "{64A05F44-4BB2-45CE-A343-6307EA8F099A}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Infrastructure", "OFBButte.Infrastructure\OFBButte.Infrastructure.csproj", "{157A1CB3-9320-4FE6-ABC5-1C9EF1952540}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OFBButte.Entities", "OFBButte.Entities\OFBButte.Entities.csproj", "{39A5BAF9-E108-4B81-8DBB-A7C1A6CEA9EF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Release|Any CPU = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{FF5F4D78-6419-47E4-A7CE-5B25503BE2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{FF5F4D78-6419-47E4-A7CE-5B25503BE2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FF5F4D78-6419-47E4-A7CE-5B25503BE2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FF5F4D78-6419-47E4-A7CE-5B25503BE2D7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8BCA31C6-C10D-4865-BAE8-6DC932B4797D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8BCA31C6-C10D-4865-BAE8-6DC932B4797D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8BCA31C6-C10D-4865-BAE8-6DC932B4797D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8BCA31C6-C10D-4865-BAE8-6DC932B4797D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{82FA36EC-1CBC-4F9A-B436-A61D9AA6D1C7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{82FA36EC-1CBC-4F9A-B436-A61D9AA6D1C7}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{82FA36EC-1CBC-4F9A-B436-A61D9AA6D1C7}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{82FA36EC-1CBC-4F9A-B436-A61D9AA6D1C7}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{64A05F44-4BB2-45CE-A343-6307EA8F099A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{64A05F44-4BB2-45CE-A343-6307EA8F099A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{64A05F44-4BB2-45CE-A343-6307EA8F099A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{64A05F44-4BB2-45CE-A343-6307EA8F099A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{157A1CB3-9320-4FE6-ABC5-1C9EF1952540}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{157A1CB3-9320-4FE6-ABC5-1C9EF1952540}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{157A1CB3-9320-4FE6-ABC5-1C9EF1952540}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{157A1CB3-9320-4FE6-ABC5-1C9EF1952540}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{39A5BAF9-E108-4B81-8DBB-A7C1A6CEA9EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{39A5BAF9-E108-4B81-8DBB-A7C1A6CEA9EF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{39A5BAF9-E108-4B81-8DBB-A7C1A6CEA9EF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{39A5BAF9-E108-4B81-8DBB-A7C1A6CEA9EF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {CD719D07-AABB-44D8-84CD-705EDF224EB9}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
Loading…
Reference in New Issue