Upload project.

This commit is contained in:
StevenJW
2020-06-09 21:28:47 +01:00
parent 36a582d89d
commit 00bf32859f
70 changed files with 38746 additions and 0 deletions

View File

@@ -0,0 +1,20 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Aya_Backend.Tests</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.12.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.15.1" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Aya-Backend\Aya-Backend.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,36 @@
using Aya_Backend.Controllers;
using Aya_Backend.Data;
using Aya_Backend.Data.Repositories.UserRepositories;
using Aya_Backend.Tests.Data;
using Microsoft.AspNetCore.Mvc;
using NUnit.Framework;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Tests
{
[TestFixture]
public class UserControllerTests
{
private readonly int validUserID = 2;
[Test]
public async Task GetUser_CorrectUserReturned()
{
var expected = MockData.Users.FirstOrDefault(u => u.ID == validUserID);
var mockContext = new MockRepository(MockData.Users, null, null);
var controller = new UserController(mockContext);
var result = await controller.GetUser(validUserID);
Assert.IsNotNull(result);
var objectResult = result as OkObjectResult;
Assert.IsNotNull(objectResult);
var modelResult = objectResult.Value as User;
Assert.IsNotNull(modelResult);
Assert.AreEqual(expected.ID, modelResult.ID);
Assert.AreEqual(expected.Username, modelResult.Username);
}
}
}

View File

@@ -0,0 +1,14 @@
using NUnit.Framework;
namespace Aya_Backend.Tests
{
[TestFixture]
public class WorkbookControllerTests
{
[Test]
public void Test1()
{
Assert.Pass();
}
}
}

View File

@@ -0,0 +1,14 @@
using NUnit.Framework;
namespace Aya_Backend.Tests
{
[TestFixture]
public class WorkpageControllerTests
{
[Test]
public void Test1()
{
Assert.Pass();
}
}
}

View File

@@ -0,0 +1,17 @@
using Aya_Backend.Data;
using System;
using System.Collections.Generic;
using System.Text;
namespace Aya_Backend.Tests.Data
{
public static class MockData
{
public static List<User> Users = new List<User>
{
new User() { ID = 1, Username = "User 1" },
new User() { ID = 2, Username = "User 2" },
new User() { ID = 3, Username = "User 3" }
};
}
}

View File

@@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Aya-Backend.Tests")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("Aya-Backend.Tests")]
[assembly: System.Reflection.AssemblyTitleAttribute("Aya-Backend.Tests")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@@ -0,0 +1,31 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29728.190
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Aya-Backend", "Aya-Backend\Aya-Backend.csproj", "{150093C3-BCCB-49E6-B39E-74E2BC7831E5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aya-Backend.Tests", "Aya-Backend.Tests\Aya-Backend.Tests.csproj", "{ADE9EB7C-FBCE-4498-B9F2-8164115F0492}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{150093C3-BCCB-49E6-B39E-74E2BC7831E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{150093C3-BCCB-49E6-B39E-74E2BC7831E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{150093C3-BCCB-49E6-B39E-74E2BC7831E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{150093C3-BCCB-49E6-B39E-74E2BC7831E5}.Release|Any CPU.Build.0 = Release|Any CPU
{ADE9EB7C-FBCE-4498-B9F2-8164115F0492}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ADE9EB7C-FBCE-4498-B9F2-8164115F0492}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ADE9EB7C-FBCE-4498-B9F2-8164115F0492}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ADE9EB7C-FBCE-4498-B9F2-8164115F0492}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {288D4B34-3BEA-4CF7-8E3F-7F7AED944F18}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,34 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Aya_Backend</RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Data\Migrations\20200503195721_InitialCreate.cs" />
<Compile Remove="Data\Migrations\20200503195721_InitialCreate.Designer.cs" />
<Compile Remove="Data\Migrations\20200503223253_AddContentToWorkpage.cs" />
<Compile Remove="Data\Migrations\20200503223253_AddContentToWorkpage.Designer.cs" />
<Compile Remove="Data\Migrations\20200504225546_BetterWorkpageSeedData.cs" />
<Compile Remove="Data\Migrations\20200504225546_BetterWorkpageSeedData.Designer.cs" />
<Compile Remove="Data\Migrations\20200505163516_PrimaryKeysIdToInt.cs" />
<Compile Remove="Data\Migrations\20200505163516_PrimaryKeysIdToInt.Designer.cs" />
<Compile Remove="Data\Migrations\20200505223715_User-Store.cs" />
<Compile Remove="Data\Migrations\20200505223715_User-Store.Designer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.1.3" />
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.3" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.3">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,67 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Aya_Backend.Data;
using Aya_Backend.Data.Repositories.UserRepositories;
using Aya_Backend.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Aya_Backend.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class UserController : ControllerBase
{
private readonly IRepository _context;
private readonly IUserService _userService;
public UserController(IRepository context, IUserService userService)
{
_context = context;
_userService = userService;
}
//Returns the user object of the user currently logged in (from token passed).
[Route("get")]
[HttpGet]
public async Task<IActionResult> GetUser()
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
var user = _context.GetUser(Int32.Parse(userId));
if (user == null)
return NotFound();
return Ok(user);
}
//Returns the user object if login credentials are valid (user object includes jwt token).
[AllowAnonymous]
[Route("login")]
[HttpPost]
public async Task<IActionResult> Login([FromBody] LoginDTO login)
{
var user = _userService.Authenticate(login.Username, login.Password);
if (user == null)
return BadRequest();
return Ok(user);
}
//Creates a new user object with the credentials passed and authenticates them.
[AllowAnonymous]
[Route("create")]
[HttpPost]
public async Task<IActionResult> CreateAccount([FromBody] LoginDTO account)
{
var user = _context.AddUser(new User() { Username = account.Username, Password = account.Password });
return Ok(user);
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Aya_Backend.Data.Repositories.UserRepositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Aya_Backend.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class WorkbookController : ControllerBase
{
private readonly IRepository _context;
public WorkbookController(IRepository context)
{
_context = context;
}
//Gets a workbook if the logged in user is owner of the workbook.
[Route("get")]
[HttpGet]
public async Task<IActionResult> GetWorkbook(int id)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
var workbook = _context.GetWorkbook(id);
if (workbook.OwnerID != Int32.Parse(userId))
return BadRequest();
return Ok(workbook);
}
//Adds a workbook to the user currently logged in.
[Route("add")]
[HttpPost]
public async Task<IActionResult> AddWorkbook(string name)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
return Ok(_context.AddWorkbook(name, Int32.Parse(userId)));
}
//Gets a list of all of the workbooks that belong to that user.
[Route("userworkbooks")]
[HttpGet]
public async Task<IActionResult> GetUserWorkbooks()
{
Console.WriteLine("workbook");
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
return Ok(_context.GetUserWorkbooks(Int32.Parse(userId)));
}
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Aya_Backend.Data;
using Aya_Backend.Data.Repositories.UserRepositories;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
namespace Aya_Backend.Controllers
{
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class WorkpageController : ControllerBase
{
private readonly IRepository _context;
public WorkpageController(IRepository context)
{
_context = context;
}
//Returns a workpage, aslong as the user is owner.
[Route("get")]
[HttpGet]
public async Task<IActionResult> GetWorkpage(int id)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
int workpageOwner = _context.GetWorkpageOwnerID(id);
if (workpageOwner != Int32.Parse(userId))
return BadRequest();
return Ok(_context.GetWorkpage(id));
}
//Returns a list of the workpages from a workbook (given a workbook id).
//Only returns them if the workbook belongs to the user.
[Route("fromworkbook")]
[HttpGet]
public async Task<IActionResult> GetFromWorkbook(int id)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
var workbook = _context.GetWorkbook(id);
if (workbook.OwnerID != Int32.Parse(userId))
return BadRequest();
return Ok(_context.GetWorkbookWorkpages(id));
}
//Adds a workpage with the given name and workbookid, aslong as they are the owner of the workbook.
[Route("add")]
[HttpPost]
public async Task<IActionResult> AddWorkpage(string name, int workbookid)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
var workbook = _context.GetWorkbook(workbookid);
if (workbook.OwnerID != Int32.Parse(userId))
return BadRequest();
var wp = new Workpage() { Name = name, WorkbookID = workbookid, Content = String.Empty };
_context.AddWorkpage(wp);
return Ok("true");
}
//Updates the content of a workpage from the request body, as long as they are the owner of the workbook.
[Route("updateworkpagecontent")]
[HttpPost]
public async Task<IActionResult> UpdateWorkpageContent(int id, [FromBody] string content)
{
string userId = User.FindFirst(ClaimTypes.Name)?.Value;
var workbook = _context.GetWorkbook(id);
if (workbook.OwnerID != Int32.Parse(userId))
return BadRequest();
_context.UpdateWorkbookContent(id, content);
return Ok("true");
}
}
}

View File

@@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data.Repositories
{
public class AyaContext : DbContext
{
public DbSet<User> Users { get; set; }
public DbSet<Workbook> Workbooks { get; set; }
public DbSet<Workpage> Workpages { get; set; }
private IHostingEnvironment HostEnv { get; }
public AyaContext(DbContextOptions<AyaContext> options, IHostingEnvironment env) : base(options)
{
HostEnv = env;
}
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite("Data Source=aya.db");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
if (HostEnv != null && HostEnv.IsDevelopment())
{
modelBuilder.Entity<User>()
.HasData(
new User() { ID = 1, Username = "User1", Password = "Password1_" },
new User() { ID = 2, Username = "User2", Password = "Password2_" },
new User() { ID = 3, Username = "User3", Password = "Password3_" }
);
modelBuilder.Entity<Workbook>()
.HasData(
new Workbook() { ID = 1, Name = "Workbook 1", OwnerID = 1 },
new Workbook() { ID = 2, Name = "Workbook 2", OwnerID = 1 },
new Workbook() { ID = 3, Name = "Workbook 3", OwnerID = 2 },
new Workbook() { ID = 4, Name = "Workbook 4", OwnerID = 2 },
new Workbook() { ID = 5, Name = "Workbook 5", OwnerID = 3 }
);
modelBuilder.Entity<Workpage>()
.HasData(
new Workpage() { ID = 1, Name = "Workpage 1", WorkbookID = 1, Content = "Content 1" },
new Workpage() { ID = 2, Name = "Workpage 2", WorkbookID = 1, Content = "Content 2" },
new Workpage() { ID = 3, Name = "Workpage 3", WorkbookID = 1, Content = "Content 3" },
new Workpage() { ID = 4, Name = "Workpage 4", WorkbookID = 1, Content = "Content 4" },
new Workpage() { ID = 5, Name = "Workpage 5", WorkbookID = 2, Content = "Content 5" },
new Workpage() { ID = 6, Name = "Workpage 6", WorkbookID = 2, Content = "Content 6" },
new Workpage() { ID = 7, Name = "Workpage 7", WorkbookID = 3, Content = "Content 7" }
);
}
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data
{
public class LoginDTO
{
public string Username { get; set; }
public string Password { get; set; }
}
}

View File

@@ -0,0 +1,195 @@
// <auto-generated />
using Aya_Backend.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Aya_Backend.Data.Migrations
{
[DbContext(typeof(AyaContext))]
[Migration("20200505164438_InitialFix")]
partial class InitialFix
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3");
modelBuilder.Entity("Aya_Backend.Data.User", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Username")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("Users");
b.HasData(
new
{
ID = 1,
Username = "User1"
},
new
{
ID = 2,
Username = "User2"
},
new
{
ID = 3,
Username = "User3"
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("OwnerID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("OwnerID");
b.ToTable("Workbooks");
b.HasData(
new
{
ID = 1,
Name = "Workbook 1",
OwnerID = 1
},
new
{
ID = 2,
Name = "Workbook 2",
OwnerID = 1
},
new
{
ID = 3,
Name = "Workbook 3",
OwnerID = 2
},
new
{
ID = 4,
Name = "Workbook 4",
OwnerID = 2
},
new
{
ID = 5,
Name = "Workbook 5",
OwnerID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("WorkbookID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("WorkbookID");
b.ToTable("Workpages");
b.HasData(
new
{
ID = 1,
Content = "Content 1",
Name = "Workpage 1",
WorkbookID = 1
},
new
{
ID = 2,
Content = "Content 2",
Name = "Workpage 2",
WorkbookID = 1
},
new
{
ID = 3,
Content = "Content 3",
Name = "Workpage 3",
WorkbookID = 1
},
new
{
ID = 4,
Content = "Content 4",
Name = "Workpage 4",
WorkbookID = 1
},
new
{
ID = 5,
Content = "Content 5",
Name = "Workpage 5",
WorkbookID = 2
},
new
{
ID = 6,
Content = "Content 6",
Name = "Workpage 6",
WorkbookID = 2
},
new
{
ID = 7,
Content = "Content 7",
Name = "Workpage 7",
WorkbookID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.HasOne("Aya_Backend.Data.User", "Owner")
.WithMany()
.HasForeignKey("OwnerID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.HasOne("Aya_Backend.Data.Workbook", "Workbook")
.WithMany()
.HasForeignKey("WorkbookID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,161 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Aya_Backend.Data.Migrations
{
public partial class InitialFix : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Users",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Username = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Users", x => x.ID);
});
migrationBuilder.CreateTable(
name: "Workbooks",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: true),
OwnerID = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Workbooks", x => x.ID);
table.ForeignKey(
name: "FK_Workbooks_Users_OwnerID",
column: x => x.OwnerID,
principalTable: "Users",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Workpages",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: true),
Content = table.Column<string>(nullable: true),
WorkbookID = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Workpages", x => x.ID);
table.ForeignKey(
name: "FK_Workpages_Workbooks_WorkbookID",
column: x => x.WorkbookID,
principalTable: "Workbooks",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.InsertData(
table: "Users",
columns: new[] { "ID", "Username" },
values: new object[] { 1, "User1" });
migrationBuilder.InsertData(
table: "Users",
columns: new[] { "ID", "Username" },
values: new object[] { 2, "User2" });
migrationBuilder.InsertData(
table: "Users",
columns: new[] { "ID", "Username" },
values: new object[] { 3, "User3" });
migrationBuilder.InsertData(
table: "Workbooks",
columns: new[] { "ID", "Name", "OwnerID" },
values: new object[] { 1, "Workbook 1", 1 });
migrationBuilder.InsertData(
table: "Workbooks",
columns: new[] { "ID", "Name", "OwnerID" },
values: new object[] { 2, "Workbook 2", 1 });
migrationBuilder.InsertData(
table: "Workbooks",
columns: new[] { "ID", "Name", "OwnerID" },
values: new object[] { 3, "Workbook 3", 2 });
migrationBuilder.InsertData(
table: "Workbooks",
columns: new[] { "ID", "Name", "OwnerID" },
values: new object[] { 4, "Workbook 4", 2 });
migrationBuilder.InsertData(
table: "Workbooks",
columns: new[] { "ID", "Name", "OwnerID" },
values: new object[] { 5, "Workbook 5", 3 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 1, "Content 1", "Workpage 1", 1 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 2, "Content 2", "Workpage 2", 1 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 3, "Content 3", "Workpage 3", 1 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 4, "Content 4", "Workpage 4", 1 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 5, "Content 5", "Workpage 5", 2 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 6, "Content 6", "Workpage 6", 2 });
migrationBuilder.InsertData(
table: "Workpages",
columns: new[] { "ID", "Content", "Name", "WorkbookID" },
values: new object[] { 7, "Content 7", "Workpage 7", 3 });
migrationBuilder.CreateIndex(
name: "IX_Workbooks_OwnerID",
table: "Workbooks",
column: "OwnerID");
migrationBuilder.CreateIndex(
name: "IX_Workpages_WorkbookID",
table: "Workpages",
column: "WorkbookID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Workpages");
migrationBuilder.DropTable(
name: "Workbooks");
migrationBuilder.DropTable(
name: "Users");
}
}
}

View File

@@ -0,0 +1,204 @@
// <auto-generated />
using Aya_Backend.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Aya_Backend.Data.Migrations
{
[DbContext(typeof(AyaContext))]
[Migration("20200505223849_User-Store")]
partial class UserStore
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3");
modelBuilder.Entity("Aya_Backend.Data.User", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Password")
.HasColumnType("TEXT");
b.Property<string>("Token")
.HasColumnType("TEXT");
b.Property<string>("Username")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("Users");
b.HasData(
new
{
ID = 1,
Password = "Password1_",
Username = "User1"
},
new
{
ID = 2,
Password = "Password2_",
Username = "User2"
},
new
{
ID = 3,
Password = "Password3_",
Username = "User3"
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("OwnerID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("OwnerID");
b.ToTable("Workbooks");
b.HasData(
new
{
ID = 1,
Name = "Workbook 1",
OwnerID = 1
},
new
{
ID = 2,
Name = "Workbook 2",
OwnerID = 1
},
new
{
ID = 3,
Name = "Workbook 3",
OwnerID = 2
},
new
{
ID = 4,
Name = "Workbook 4",
OwnerID = 2
},
new
{
ID = 5,
Name = "Workbook 5",
OwnerID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("WorkbookID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("WorkbookID");
b.ToTable("Workpages");
b.HasData(
new
{
ID = 1,
Content = "Content 1",
Name = "Workpage 1",
WorkbookID = 1
},
new
{
ID = 2,
Content = "Content 2",
Name = "Workpage 2",
WorkbookID = 1
},
new
{
ID = 3,
Content = "Content 3",
Name = "Workpage 3",
WorkbookID = 1
},
new
{
ID = 4,
Content = "Content 4",
Name = "Workpage 4",
WorkbookID = 1
},
new
{
ID = 5,
Content = "Content 5",
Name = "Workpage 5",
WorkbookID = 2
},
new
{
ID = 6,
Content = "Content 6",
Name = "Workpage 6",
WorkbookID = 2
},
new
{
ID = 7,
Content = "Content 7",
Name = "Workpage 7",
WorkbookID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.HasOne("Aya_Backend.Data.User", "Owner")
.WithMany()
.HasForeignKey("OwnerID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.HasOne("Aya_Backend.Data.Workbook", "Workbook")
.WithMany()
.HasForeignKey("WorkbookID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,52 @@
using Microsoft.EntityFrameworkCore.Migrations;
namespace Aya_Backend.Data.Migrations
{
public partial class UserStore : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>(
name: "Password",
table: "Users",
nullable: true);
migrationBuilder.AddColumn<string>(
name: "Token",
table: "Users",
nullable: true);
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "ID",
keyValue: 1,
column: "Password",
value: "Password1_");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "ID",
keyValue: 2,
column: "Password",
value: "Password2_");
migrationBuilder.UpdateData(
table: "Users",
keyColumn: "ID",
keyValue: 3,
column: "Password",
value: "Password3_");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Password",
table: "Users");
migrationBuilder.DropColumn(
name: "Token",
table: "Users");
}
}
}

View File

@@ -0,0 +1,202 @@
// <auto-generated />
using Aya_Backend.Data.Repositories;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Aya_Backend.Data.Migrations
{
[DbContext(typeof(AyaContext))]
partial class AyaContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "3.1.3");
modelBuilder.Entity("Aya_Backend.Data.User", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Password")
.HasColumnType("TEXT");
b.Property<string>("Token")
.HasColumnType("TEXT");
b.Property<string>("Username")
.HasColumnType("TEXT");
b.HasKey("ID");
b.ToTable("Users");
b.HasData(
new
{
ID = 1,
Password = "Password1_",
Username = "User1"
},
new
{
ID = 2,
Password = "Password2_",
Username = "User2"
},
new
{
ID = 3,
Password = "Password3_",
Username = "User3"
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("OwnerID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("OwnerID");
b.ToTable("Workbooks");
b.HasData(
new
{
ID = 1,
Name = "Workbook 1",
OwnerID = 1
},
new
{
ID = 2,
Name = "Workbook 2",
OwnerID = 1
},
new
{
ID = 3,
Name = "Workbook 3",
OwnerID = 2
},
new
{
ID = 4,
Name = "Workbook 4",
OwnerID = 2
},
new
{
ID = 5,
Name = "Workbook 5",
OwnerID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd()
.HasColumnType("INTEGER");
b.Property<string>("Content")
.HasColumnType("TEXT");
b.Property<string>("Name")
.HasColumnType("TEXT");
b.Property<int>("WorkbookID")
.HasColumnType("INTEGER");
b.HasKey("ID");
b.HasIndex("WorkbookID");
b.ToTable("Workpages");
b.HasData(
new
{
ID = 1,
Content = "Content 1",
Name = "Workpage 1",
WorkbookID = 1
},
new
{
ID = 2,
Content = "Content 2",
Name = "Workpage 2",
WorkbookID = 1
},
new
{
ID = 3,
Content = "Content 3",
Name = "Workpage 3",
WorkbookID = 1
},
new
{
ID = 4,
Content = "Content 4",
Name = "Workpage 4",
WorkbookID = 1
},
new
{
ID = 5,
Content = "Content 5",
Name = "Workpage 5",
WorkbookID = 2
},
new
{
ID = 6,
Content = "Content 6",
Name = "Workpage 6",
WorkbookID = 2
},
new
{
ID = 7,
Content = "Content 7",
Name = "Workpage 7",
WorkbookID = 3
});
});
modelBuilder.Entity("Aya_Backend.Data.Workbook", b =>
{
b.HasOne("Aya_Backend.Data.User", "Owner")
.WithMany()
.HasForeignKey("OwnerID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
modelBuilder.Entity("Aya_Backend.Data.Workpage", b =>
{
b.HasOne("Aya_Backend.Data.Workbook", "Workbook")
.WithMany()
.HasForeignKey("WorkbookID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data.Repositories.UserRepositories
{
public interface IRepository
{
//Interface for getting values from a dataset (Database/Mocked data).
//User
public User GetUser(int id);
public User GetUserAuth(string username, string password);
public User AddUser(User user);
public void UpdateUser(User user);
//Workbook
public Workbook GetWorkbook(int id);
public Workbook AddWorkbook(string name, int ownerid);
public List<Workbook> GetUserWorkbooks(int id);
//Workpage
public Workpage GetWorkpage(int id);
public void AddWorkpage(Workpage wp);
public List<Workpage> GetWorkbookWorkpages(int id);
public void UpdateWorkbookContent(int id, string content);
public int GetWorkpageOwnerID(int id);
}
}

View File

@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data.Repositories.UserRepositories
{
//Mock repository to use for testing. Gets passed mock data in the form of lists upon construction.
public class MockRepository : IRepository
{
private List<User> MockUsers { get; }
private List<Workbook> MockWorkbooks { get; }
private List<Workpage> MockWorkpages { get; }
public MockRepository(List<User> users, List<Workbook> workbooks, List<Workpage> workpages)
{
MockUsers = users;
MockWorkbooks = workbooks;
MockWorkpages = workpages;
}
//User
public User GetUser(int id)
{
return MockUsers.FirstOrDefault(user => user.ID == id);
}
public User AddUser(User user)
{
MockUsers.Add(user);
return user;
}
//Workbook
public Workbook GetWorkbook(int id)
{
return MockWorkbooks.FirstOrDefault(wb => wb.ID == id);
}
public Workbook AddWorkbook(string name, int ownerid)
{
var workbook = new Workbook() { ID = 10, Name = name, OwnerID = ownerid };
MockWorkbooks.Add(workbook);
return workbook;
}
public List<Workbook> GetUserWorkbooks(int id)
{
return MockWorkbooks.Where(wb => wb.OwnerID == id).ToList();
}
public Workpage GetWorkpage(int id)
{
return MockWorkpages.FirstOrDefault(wp => wp.ID == id);
}
public void AddWorkpage(Workpage wp)
{
MockWorkpages.Add(wp);
}
public List<Workpage> GetWorkbookWorkpages(int id)
{
return MockWorkpages.Where(wp => wp.WorkbookID == id).ToList();
}
public void UpdateWorkbookContent(int id, string content)
{
var workpage = MockWorkpages.FirstOrDefault(wp => wp.ID == id);
workpage.Content = content;
}
public Workbook AddWorkbook(string name, string ownerid)
{
throw new NotImplementedException();
}
public User GetUserAuth(string username, string password)
{
throw new NotImplementedException();
}
public void UpdateUser(User user)
{
throw new NotImplementedException();
}
public int GetWorkpageOwnerID(int id)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,94 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data.Repositories.UserRepositories
{
public class Repository : IRepository
{
private readonly AyaContext _context;
public Repository(AyaContext context)
{
_context = context;
}
//User
public User GetUser(int id)
{
return _context.Users.FirstOrDefault(u => u.ID == id);
}
public User GetUserAuth(string username, string password)
{
return _context.Users.FirstOrDefault(u => u.Username == username && u.Password == password);
}
public User AddUser(User user)
{
var u = _context.Add(user);
_context.SaveChanges();
return u.Entity;
}
public void UpdateUser(User user)
{
_context.Update(user);
_context.SaveChanges();
}
//Workbook
public Workbook GetWorkbook(int id)
{
return _context.Workbooks.FirstOrDefault(u => u.ID == id);
}
public Workbook AddWorkbook(string name, int ownerid)
{
var added = _context.Add(new Workbook { Name = name, OwnerID = ownerid });
_context.SaveChangesAsync();
return added.Entity;
}
public List<Workbook> GetUserWorkbooks(int id)
{
return _context.Workbooks.Where(wb => wb.OwnerID == id).ToList();
}
//Workpage
public Workpage GetWorkpage(int id)
{
return _context.Workpages.FirstOrDefault(wp => wp.ID == id);
}
public void AddWorkpage(Workpage wp)
{
_context.Add(wp);
_context.SaveChanges();
}
public List<Workpage> GetWorkbookWorkpages(int id)
{
return _context.Workpages.Where(wp => wp.WorkbookID == id).ToList();
}
public void UpdateWorkbookContent(int id, string content)
{
var original = _context.Workpages.FirstOrDefault(wp => wp.ID == id);
if (original == null)
return;
original.Content = content;
_context.Update(original);
_context.SaveChanges();
}
public int GetWorkpageOwnerID(int id)
{
var workbook = _context.Workpages.Include(wp => wp.Workbook).FirstOrDefault(wp => wp.ID == id);
return workbook.Workbook.OwnerID;
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data
{
public class TokenDTO
{
public string Token { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
namespace Aya_Backend.Data
{
public class User
{
public int ID { get; set; }
public string Username { get; set; }
[JsonIgnore]
public string Password { get; set; }
public string Token { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data
{
public class Workbook
{
public int ID { get; set; }
public string Name { get; set; }
public int OwnerID { get; set; }
public User Owner { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Aya_Backend.Data
{
public class Workpage
{
public int ID { get; set; }
public string Name { get; set; }
public string Content { get; set; }
public int WorkbookID { get; set; }
public Workbook Workbook { get; set; }
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Aya_Backend.Data.Repositories;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHostingEnvironment = Microsoft.AspNetCore.Hosting.IHostingEnvironment;
namespace Aya_Backend
{
public class Program
{
public static void Main(string[] args)
{
var host = CreateHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var env = services.GetRequiredService<IHostingEnvironment>();
if (env.IsDevelopment())
{
var context = services.GetRequiredService<AyaContext>();
context.Database.EnsureDeleted();
context.Database.Migrate();
}
}
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

View File

@@ -0,0 +1,30 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:63581",
"sslPort": 44394
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"Aya_Backend": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "",
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Text;
using System.Text.Json.Serialization;
using Aya_Backend.Data;
using Aya_Backend.Data.Repositories;
using Aya_Backend.Data.Repositories.UserRepositories;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
namespace Aya_Backend.Services
{
public interface IUserService
{
User Authenticate(string username, string password);
}
public class UserService : IUserService
{
private readonly IRepository _context;
public UserService(IRepository repository)
{
_context = repository;
}
public User Authenticate(string username, string password)
{
var user = _context.GetUserAuth(username, password);
// return null if user not found
if (user == null)
return null;
// authentication successful so generate jwt token
var tokenHandler = new JwtSecurityTokenHandler();
var key = Encoding.ASCII.GetBytes("VmdjieSvw6co7huHZtyn");
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, user.ID.ToString())
}),
Expires = DateTime.UtcNow.AddDays(7),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
var token = tokenHandler.CreateToken(tokenDescriptor);
user.Token = tokenHandler.WriteToken(token);
return user;
}
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aya_Backend.Data.Repositories;
using Aya_Backend.Data.Repositories.UserRepositories;
using Aya_Backend.Services;
using Microsoft.AspNetCore.Authentication.JwtBearer;
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.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
namespace Aya_Backend
{
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.AddControllers();
services.AddDbContext<AyaContext>();
var key = Encoding.ASCII.GetBytes("VmdjieSvw6co7huHZtyn");
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false
};
});
services.AddScoped<IRepository, Repository>();
services.AddScoped<IUserService, UserService>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(builder => builder
.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

View File

@@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

Binary file not shown.

View File

@@ -0,0 +1,23 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Aya-Backend")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0")]
[assembly: System.Reflection.AssemblyProductAttribute("Aya-Backend")]
[assembly: System.Reflection.AssemblyTitleAttribute("Aya-Backend")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
// Generated by the MSBuild WriteCodeFragment class.

File diff suppressed because it is too large Load Diff

2
Aya-Backend/README.md Normal file
View File

@@ -0,0 +1,2 @@
# Aya-Backend
The backend/API for Aya, written in C# ASP.NET.