Browse Source

Merge branch 'develop' into 'f/raum-übersicht'

# Conflicts:
#   Frontend/src/components/App.js
f/raum-übersicht
Levin Faber 7 years ago
parent
commit
11738e8ba5
  1. 27
      Backend/EVABackend/EVABackend/Areas/Identity/Data/EVABackendIdentityContext.cs
  2. 13
      Backend/EVABackend/EVABackend/Areas/Identity/Data/EVABackendUser.cs
  3. 36
      Backend/EVABackend/EVABackend/Areas/Identity/IdentityHostingStartup.cs
  4. 194
      Backend/EVABackend/EVABackend/Controllers/EVAController.cs
  5. 45
      Backend/EVABackend/EVABackend/Controllers/ValuesController.cs
  6. 3
      Backend/EVABackend/EVABackend/EVABackend.csproj
  7. 229
      Backend/EVABackend/EVABackend/Migrations/20190612100741_CreateIdentitySchema.Designer.cs
  8. 217
      Backend/EVABackend/EVABackend/Migrations/20190612100741_CreateIdentitySchema.cs
  9. 388
      Backend/EVABackend/EVABackend/Migrations/EVA/20190612101730_InitialCreate.Designer.cs
  10. 403
      Backend/EVABackend/EVABackend/Migrations/EVA/20190612101730_InitialCreate.cs
  11. 386
      Backend/EVABackend/EVABackend/Migrations/EVA/EVAContextModelSnapshot.cs
  12. 227
      Backend/EVABackend/EVABackend/Migrations/EVABackendIdentityContextModelSnapshot.cs
  13. 42
      Backend/EVABackend/EVABackend/Models/Aufnahmeantrag.cs
  14. 13
      Backend/EVABackend/EVABackend/Models/CreateRooms.cs
  15. 227
      Backend/EVABackend/EVABackend/Models/EVAContext.cs
  16. 6
      Backend/EVABackend/EVABackend/Properties/launchSettings.json
  17. 26
      Backend/EVABackend/EVABackend/ScaffoldingReadme.txt
  18. 11
      Backend/EVABackend/EVABackend/Startup.cs
  19. 7
      Backend/EVABackend/EVABackend/appsettings.json
  20. BIN
      Backend/EVABackend/EVABackend/eva_ls.db
  21. BIN
      Backend/EVABackend/EVABackend/eva_users.db
  22. 15
      Frontend/src/components/App.js
  23. 4
      Frontend/src/components/Aufnahmeantrag.js
  24. 98
      Frontend/src/components/Login.js
  25. 5
      Frontend/src/style/index.css
  26. 22
      _Dokumente/Ausgearbeitete Dokumente/Endpoints.md
  27. BIN
      _Dokumente/Ausgearbeitete Dokumente/LS Musikschule. PROJEKTSTRUKTURPLAN.xlsx
  28. 216
      _Dokumente/Ausgearbeitete Dokumente/Pflichtenheft.md
  29. BIN
      _Dokumente/Ausgearbeitete Dokumente/Pflichtenheft.pdf
  30. BIN
      _Dokumente/Ausgearbeitete Dokumente/Zeitplan.jpg
  31. 2
      _Dokumente/Protokolle/2019-05-15_Protokoll.md
  32. 3
      _Dokumente/Protokolle/2019-05-22_Protokoll.md
  33. 6
      _Dokumente/Protokolle/2019-05-29_Protokoll.md
  34. 2
      _Dokumente/Protokolle/2019-06-05_Protokoll.md
  35. 8
      _Dokumente/Protokolle/2019-06-12_Protokoll.md
  36. 17
      _Dokumente/Protokolle/2019-06-19_Protokoll.md

27
Backend/EVABackend/EVABackend/Areas/Identity/Data/EVABackendIdentityContext.cs

@ -0,0 +1,27 @@
using EVABackend.Areas.Identity.Data;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace EVABackend.Models
{
public class EVABackendIdentityContext : IdentityDbContext<EVABackendUser>
{
public EVABackendIdentityContext(DbContextOptions<EVABackendIdentityContext> options)
: base(options)
{
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=eva_users.db");
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
}
}
}

13
Backend/EVABackend/EVABackend/Areas/Identity/Data/EVABackendUser.cs

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Identity;
namespace EVABackend.Areas.Identity.Data
{
// Add profile data for application users by adding properties to the EVABackendUser class
public class EVABackendUser : IdentityUser
{
}
}

36
Backend/EVABackend/EVABackend/Areas/Identity/IdentityHostingStartup.cs

@ -0,0 +1,36 @@
using EVABackend.Areas.Identity.Data;
using EVABackend.Models;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using System;
[assembly: HostingStartup(typeof(EVABackend.Areas.Identity.IdentityHostingStartup))]
namespace EVABackend.Areas.Identity
{
public class IdentityHostingStartup : IHostingStartup
{
public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) =>
{
services.AddDbContext<EVABackendIdentityContext>(options =>
options.UseSqlite(
context.Configuration.GetConnectionString("EVABackendIdentityContextConnection")));
services.AddDefaultIdentity<EVABackendUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<EVABackendIdentityContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "EVABackend_Token";
});
});
}
}
}

194
Backend/EVABackend/EVABackend/Controllers/EVAController.cs

@ -0,0 +1,194 @@
using EVABackend.Areas.Identity.Data;
using EVABackend.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using System.Linq;
using System.Threading.Tasks;
namespace EVABackend.Controllers
{
[ApiController]
public class EVAController : ControllerBase
{
private readonly EVAContext _context;
private readonly UserManager<EVABackendUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
private readonly SignInManager<EVABackendUser> _signInManager;
public EVAController(UserManager<EVABackendUser> userManager, RoleManager<IdentityRole> roleManager, SignInManager<EVABackendUser> signInManager)
{
_userManager = userManager;
_roleManager = roleManager;
_signInManager = signInManager;
_context = new EVAContext();
}
[HttpGet]
[Route("login")]
[AllowAnonymous]
public ActionResult Login()
{
return Ok(new { status = "Nicht unterstützt" });
}
[HttpGet]
[Route("create_dummy_data")]
[Authorize]
public async Task<ActionResult> CreateDummyData()
{
if (_userManager.FindByNameAsync("Test") == null)
{
var user = new EVABackendUser
{
UserName = "Test",
Email = "info@test.de"
};
await _userManager.CreateAsync(user, "123Abc!&");
}
var roleNames = new string[] { "Schueler", "Verwaltung", "Admin" };
foreach (var roleName in roleNames)
{
if (!(await _roleManager.RoleExistsAsync(roleName)))
{
await _roleManager.CreateAsync(new IdentityRole(roleName));
}
}
await _userManager.AddToRolesAsync((await _userManager.FindByNameAsync("Test")), roleNames);
return Ok();
}
[HttpPost]
[Route("login")]
[AllowAnonymous]
public async Task<ActionResult> Login([FromForm] string username, [FromForm] string password)
{
var result = await _signInManager.PasswordSignInAsync(username, password, false, false);
if (result.Succeeded)
{
return Ok();
}
return Unauthorized();
}
[HttpPost]
[Route("logout")]
[Authorize]
public async Task<ActionResult> Logout()
{
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return Ok();
}
[HttpPost]
[Route("aufnahmeantrag")]
[AllowAnonymous]
public async Task<ActionResult> Aufnahmeantrag(Aufnahmeantrag model)
{
var schueler = new Schueler
{
Name = model.Name,
Vorname = model.Vonname,
IstErmaessigt = model.IstErmaessigt,
Ort = model.Ort,
Bankname = model.Bankname,
BLZ = model.BLZ,
Geburtsdatum = model.Geburtsdatum,
Geburtsort = model.Geburtsort,
Telefon = model.Telefon,
EMail = model.EMail,
PLZ = model.PLZ,
KontoNr = model.KontoNr,
Strasse = model.StrasseHNR
};
await _context.Schueler.AddAsync(schueler);
await _context.SaveChangesAsync();
var instrumente = _context.Instrumente.Where(i => model.Instrumente.Contains(i.Id)).ToList();
var kurs = new Kurs
{
Bestaetigt = false,
Name = model.Name,
Kuendigungsfrist = 2,
UnterrichtsTyp = model.Typ,
Laufzeit = 6
};
await _context.Kurse.AddAsync(kurs);
await _context.SaveChangesAsync();
kurs.Instrumente = instrumente.Select(i => new KursInstrument { InstrumentId = i.Id, KursId = kurs.Id }).ToList();
await _context.KursSchueler.AddAsync(new KursSchueler { KursId = kurs.Id, SchuelerId = schueler.Id });
await _context.SaveChangesAsync();
var antrag = new Antrag
{
UnterrichtTyp = model.Typ,
Schueler = schueler,
KursId = kurs.Id
};
await _context.Antraege.AddAsync(antrag);
await _context.SaveChangesAsync();
antrag.Instrumente = instrumente.Select(i => new AntragInstrument { AntragId = antrag.Id, InstrumentId = i.Id }).ToList();
await _context.SaveChangesAsync();
return Ok();
}
[HttpGet]
[Route("instruments")]
[Authorize]
public ActionResult Instruments()
{
var instruments = _context.Instrumente.ToList();
return Ok(instruments.ToArray());
}
[HttpGet]
[Route("rooms")]
[Authorize(Roles = "Verwaltung")]
public ActionResult Rooms()
{
var rooms = _context.Raeume.ToList();
var model = rooms.Select(r => new
{
RaumID = r.Id,
RaumName= r.Name,
Instrumente = r.Instrumente.Select(i => new
{
InstrumentID = i.InstrumentId,
InstrumentName = i.Instrument.Name
})
});
return Ok(model.ToArray());
}
[HttpPut]
[Route("create_rooms")]
[Authorize(Roles = "Verwaltung")]
public async Task<ActionResult> CreateRooms(CreateRooms model)
{
}
}
}

45
Backend/EVABackend/EVABackend/Controllers/ValuesController.cs

@ -1,45 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
namespace EVABackend.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)
{
}
}
}

3
Backend/EVABackend/EVABackend/EVABackend.csproj

@ -7,7 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Folder Include="wwwroot\" /> <Folder Include="Areas\Identity\Services\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -15,6 +15,7 @@
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.1" PrivateAssets="All" /> <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.1" PrivateAssets="All" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.1.8" />
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.7.8" /> <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.7.8" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.1.9" />
</ItemGroup> </ItemGroup>
</Project> </Project>

229
Backend/EVABackend/EVABackend/Migrations/20190612100741_CreateIdentitySchema.Designer.cs generated

@ -0,0 +1,229 @@
// <auto-generated />
using System;
using EVABackend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EVABackend.Migrations
{
[DbContext(typeof(EVABackendIdentityContext))]
[Migration("20190612100741_CreateIdentitySchema")]
partial class CreateIdentitySchema
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.8-servicing-32085");
modelBuilder.Entity("EVABackend.Areas.Identity.Data.EVABackendUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

217
Backend/EVABackend/EVABackend/Migrations/20190612100741_CreateIdentitySchema.cs

@ -0,0 +1,217 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace EVABackend.Migrations
{
public partial class CreateIdentitySchema : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "AspNetRoles",
columns: table => new
{
Id = table.Column<string>(nullable: false),
Name = table.Column<string>(maxLength: 256, nullable: true),
NormalizedName = table.Column<string>(maxLength: 256, nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoles", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetUsers",
columns: table => new
{
Id = table.Column<string>(nullable: false),
UserName = table.Column<string>(maxLength: 256, nullable: true),
NormalizedUserName = table.Column<string>(maxLength: 256, nullable: true),
Email = table.Column<string>(maxLength: 256, nullable: true),
NormalizedEmail = table.Column<string>(maxLength: 256, nullable: true),
EmailConfirmed = table.Column<bool>(nullable: false),
PasswordHash = table.Column<string>(nullable: true),
SecurityStamp = table.Column<string>(nullable: true),
ConcurrencyStamp = table.Column<string>(nullable: true),
PhoneNumber = table.Column<string>(nullable: true),
PhoneNumberConfirmed = table.Column<bool>(nullable: false),
TwoFactorEnabled = table.Column<bool>(nullable: false),
LockoutEnd = table.Column<DateTimeOffset>(nullable: true),
LockoutEnabled = table.Column<bool>(nullable: false),
AccessFailedCount = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUsers", x => x.Id);
});
migrationBuilder.CreateTable(
name: "AspNetRoleClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
RoleId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetRoleClaims_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserClaims",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
UserId = table.Column<string>(nullable: false),
ClaimType = table.Column<string>(nullable: true),
ClaimValue = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserClaims", x => x.Id);
table.ForeignKey(
name: "FK_AspNetUserClaims_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserLogins",
columns: table => new
{
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
ProviderKey = table.Column<string>(maxLength: 128, nullable: false),
ProviderDisplayName = table.Column<string>(nullable: true),
UserId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey });
table.ForeignKey(
name: "FK_AspNetUserLogins_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserRoles",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
RoleId = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId });
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetRoles_RoleId",
column: x => x.RoleId,
principalTable: "AspNetRoles",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AspNetUserRoles_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "AspNetUserTokens",
columns: table => new
{
UserId = table.Column<string>(nullable: false),
LoginProvider = table.Column<string>(maxLength: 128, nullable: false),
Name = table.Column<string>(maxLength: 128, nullable: false),
Value = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name });
table.ForeignKey(
name: "FK_AspNetUserTokens_AspNetUsers_UserId",
column: x => x.UserId,
principalTable: "AspNetUsers",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_AspNetRoleClaims_RoleId",
table: "AspNetRoleClaims",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "RoleNameIndex",
table: "AspNetRoles",
column: "NormalizedName",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_AspNetUserClaims_UserId",
table: "AspNetUserClaims",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserLogins_UserId",
table: "AspNetUserLogins",
column: "UserId");
migrationBuilder.CreateIndex(
name: "IX_AspNetUserRoles_RoleId",
table: "AspNetUserRoles",
column: "RoleId");
migrationBuilder.CreateIndex(
name: "EmailIndex",
table: "AspNetUsers",
column: "NormalizedEmail");
migrationBuilder.CreateIndex(
name: "UserNameIndex",
table: "AspNetUsers",
column: "NormalizedUserName",
unique: true);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AspNetRoleClaims");
migrationBuilder.DropTable(
name: "AspNetUserClaims");
migrationBuilder.DropTable(
name: "AspNetUserLogins");
migrationBuilder.DropTable(
name: "AspNetUserRoles");
migrationBuilder.DropTable(
name: "AspNetUserTokens");
migrationBuilder.DropTable(
name: "AspNetRoles");
migrationBuilder.DropTable(
name: "AspNetUsers");
}
}
}

388
Backend/EVABackend/EVABackend/Migrations/EVA/20190612101730_InitialCreate.Designer.cs generated

@ -0,0 +1,388 @@
// <auto-generated />
using System;
using EVABackend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EVABackend.Migrations.EVA
{
[DbContext(typeof(EVAContext))]
[Migration("20190612101730_InitialCreate")]
partial class InitialCreate
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.8-servicing-32085");
modelBuilder.Entity("EVABackend.Models.Antrag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("KursId");
b.Property<int?>("SchuelerId");
b.Property<int?>("UnterrichtTypId");
b.HasKey("Id");
b.HasIndex("SchuelerId");
b.HasIndex("UnterrichtTypId");
b.ToTable("Antraege");
});
modelBuilder.Entity("EVABackend.Models.AntragInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("AntragId");
b.HasKey("InstrumentId", "AntragId");
b.HasIndex("AntragId");
b.ToTable("AntragInstrument");
});
modelBuilder.Entity("EVABackend.Models.Dozent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("BLZ")
.IsRequired();
b.Property<string>("Bankname")
.IsRequired();
b.Property<string>("EMail")
.IsRequired();
b.Property<DateTime>("Geburtsdatum");
b.Property<string>("Geburtsort")
.IsRequired();
b.Property<string>("KontoNr")
.IsRequired();
b.Property<string>("Name")
.IsRequired();
b.Property<string>("Ort")
.IsRequired();
b.Property<int>("PLZ");
b.Property<string>("Strasse")
.IsRequired();
b.Property<decimal>("Stundensatz");
b.Property<string>("Telefon")
.IsRequired();
b.Property<string>("Vorname")
.IsRequired();
b.HasKey("Id");
b.ToTable("Donzenten");
});
modelBuilder.Entity("EVABackend.Models.DozentInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("DozentId");
b.HasKey("InstrumentId", "DozentId");
b.HasIndex("DozentId");
b.ToTable("DozentInstrument");
});
modelBuilder.Entity("EVABackend.Models.Instrument", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("Instrumente");
});
modelBuilder.Entity("EVABackend.Models.Kurs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Bestaetigt");
b.Property<int>("Kuendigungsfrist");
b.Property<int>("Laufzeit");
b.Property<string>("Name")
.IsRequired();
b.Property<int?>("UnterrichtsTypId");
b.HasKey("Id");
b.HasIndex("UnterrichtsTypId");
b.ToTable("Kurse");
});
modelBuilder.Entity("EVABackend.Models.KursInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("KursId");
b.HasKey("InstrumentId", "KursId");
b.HasIndex("KursId");
b.ToTable("KursInstrument");
});
modelBuilder.Entity("EVABackend.Models.KursSchueler", b =>
{
b.Property<int>("SchuelerId");
b.Property<int>("KursId");
b.Property<int?>("DozentId");
b.HasKey("SchuelerId", "KursId");
b.HasIndex("DozentId");
b.HasIndex("KursId");
b.ToTable("KursSchueler");
});
modelBuilder.Entity("EVABackend.Models.Raum", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Belegt");
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("Raeume");
});
modelBuilder.Entity("EVABackend.Models.RaumInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("RaumId");
b.HasKey("InstrumentId", "RaumId");
b.HasIndex("RaumId");
b.ToTable("RaumInstrument");
});
modelBuilder.Entity("EVABackend.Models.Schueler", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("BLZ")
.IsRequired();
b.Property<string>("Bankname")
.IsRequired();
b.Property<string>("EMail")
.IsRequired();
b.Property<DateTime>("Geburtsdatum");
b.Property<string>("Geburtsort")
.IsRequired();
b.Property<bool>("IstErmaessigt");
b.Property<string>("KontoNr")
.IsRequired();
b.Property<string>("Name")
.IsRequired();
b.Property<string>("Ort")
.IsRequired();
b.Property<int>("PLZ");
b.Property<string>("Strasse")
.IsRequired();
b.Property<string>("Telefon")
.IsRequired();
b.Property<string>("Vorname")
.IsRequired();
b.HasKey("Id");
b.ToTable("Schueler");
});
modelBuilder.Entity("EVABackend.Models.Unterricht", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("KursId");
b.Property<string>("Notiz");
b.Property<int?>("RaumId");
b.Property<DateTime>("Startzeit");
b.HasKey("Id");
b.HasIndex("KursId");
b.HasIndex("RaumId");
b.ToTable("Unterrichte");
});
modelBuilder.Entity("EVABackend.Models.UnterrichtTyp", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("UnterrichtTypen");
});
modelBuilder.Entity("EVABackend.Models.Antrag", b =>
{
b.HasOne("EVABackend.Models.Schueler", "Schueler")
.WithMany()
.HasForeignKey("SchuelerId");
b.HasOne("EVABackend.Models.UnterrichtTyp", "UnterrichtTyp")
.WithMany()
.HasForeignKey("UnterrichtTypId");
});
modelBuilder.Entity("EVABackend.Models.AntragInstrument", b =>
{
b.HasOne("EVABackend.Models.Antrag", "Antrag")
.WithMany("Instrumente")
.HasForeignKey("AntragId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.DozentInstrument", b =>
{
b.HasOne("EVABackend.Models.Dozent", "Dozent")
.WithMany("Instrumente")
.HasForeignKey("DozentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.Kurs", b =>
{
b.HasOne("EVABackend.Models.UnterrichtTyp", "UnterrichtsTyp")
.WithMany()
.HasForeignKey("UnterrichtsTypId");
});
modelBuilder.Entity("EVABackend.Models.KursInstrument", b =>
{
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Kurs", "Kurs")
.WithMany("Instrumente")
.HasForeignKey("KursId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.KursSchueler", b =>
{
b.HasOne("EVABackend.Models.Dozent")
.WithMany("KursSchueler")
.HasForeignKey("DozentId");
b.HasOne("EVABackend.Models.Kurs", "Kurs")
.WithMany("KursSchueler")
.HasForeignKey("KursId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Schueler", "Schueler")
.WithMany("KursSchueler")
.HasForeignKey("SchuelerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.RaumInstrument", b =>
{
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Raum", "Raum")
.WithMany("Instrumente")
.HasForeignKey("RaumId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.Unterricht", b =>
{
b.HasOne("EVABackend.Models.Kurs")
.WithMany("Unterrichte")
.HasForeignKey("KursId");
b.HasOne("EVABackend.Models.Raum", "Raum")
.WithMany()
.HasForeignKey("RaumId");
});
#pragma warning restore 612, 618
}
}
}

403
Backend/EVABackend/EVABackend/Migrations/EVA/20190612101730_InitialCreate.cs

@ -0,0 +1,403 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace EVABackend.Migrations.EVA
{
public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Donzenten",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false),
Vorname = table.Column<string>(nullable: false),
Geburtsdatum = table.Column<DateTime>(nullable: false),
Geburtsort = table.Column<string>(nullable: false),
PLZ = table.Column<int>(nullable: false),
Ort = table.Column<string>(nullable: false),
Strasse = table.Column<string>(nullable: false),
Telefon = table.Column<string>(nullable: false),
EMail = table.Column<string>(nullable: false),
Bankname = table.Column<string>(nullable: false),
BLZ = table.Column<string>(nullable: false),
KontoNr = table.Column<string>(nullable: false),
Stundensatz = table.Column<decimal>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Donzenten", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Instrumente",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Instrumente", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Raeume",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false),
Belegt = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Raeume", x => x.Id);
});
migrationBuilder.CreateTable(
name: "Schueler",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false),
Vorname = table.Column<string>(nullable: false),
Geburtsdatum = table.Column<DateTime>(nullable: false),
Geburtsort = table.Column<string>(nullable: false),
PLZ = table.Column<int>(nullable: false),
Ort = table.Column<string>(nullable: false),
Strasse = table.Column<string>(nullable: false),
Telefon = table.Column<string>(nullable: false),
EMail = table.Column<string>(nullable: false),
Bankname = table.Column<string>(nullable: false),
BLZ = table.Column<string>(nullable: false),
KontoNr = table.Column<string>(nullable: false),
IstErmaessigt = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Schueler", x => x.Id);
});
migrationBuilder.CreateTable(
name: "UnterrichtTypen",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_UnterrichtTypen", x => x.Id);
});
migrationBuilder.CreateTable(
name: "DozentInstrument",
columns: table => new
{
InstrumentId = table.Column<int>(nullable: false),
DozentId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_DozentInstrument", x => new { x.InstrumentId, x.DozentId });
table.ForeignKey(
name: "FK_DozentInstrument_Donzenten_DozentId",
column: x => x.DozentId,
principalTable: "Donzenten",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_DozentInstrument_Instrumente_InstrumentId",
column: x => x.InstrumentId,
principalTable: "Instrumente",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "RaumInstrument",
columns: table => new
{
InstrumentId = table.Column<int>(nullable: false),
RaumId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_RaumInstrument", x => new { x.InstrumentId, x.RaumId });
table.ForeignKey(
name: "FK_RaumInstrument_Instrumente_InstrumentId",
column: x => x.InstrumentId,
principalTable: "Instrumente",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_RaumInstrument_Raeume_RaumId",
column: x => x.RaumId,
principalTable: "Raeume",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Antraege",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
SchuelerId = table.Column<int>(nullable: true),
UnterrichtTypId = table.Column<int>(nullable: true),
KursId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Antraege", x => x.Id);
table.ForeignKey(
name: "FK_Antraege_Schueler_SchuelerId",
column: x => x.SchuelerId,
principalTable: "Schueler",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Antraege_UnterrichtTypen_UnterrichtTypId",
column: x => x.UnterrichtTypId,
principalTable: "UnterrichtTypen",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "Kurse",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Name = table.Column<string>(nullable: false),
Laufzeit = table.Column<int>(nullable: false),
Kuendigungsfrist = table.Column<int>(nullable: false),
Bestaetigt = table.Column<bool>(nullable: false),
UnterrichtsTypId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Kurse", x => x.Id);
table.ForeignKey(
name: "FK_Kurse_UnterrichtTypen_UnterrichtsTypId",
column: x => x.UnterrichtsTypId,
principalTable: "UnterrichtTypen",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateTable(
name: "AntragInstrument",
columns: table => new
{
InstrumentId = table.Column<int>(nullable: false),
AntragId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_AntragInstrument", x => new { x.InstrumentId, x.AntragId });
table.ForeignKey(
name: "FK_AntragInstrument_Antraege_AntragId",
column: x => x.AntragId,
principalTable: "Antraege",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_AntragInstrument_Instrumente_InstrumentId",
column: x => x.InstrumentId,
principalTable: "Instrumente",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "KursInstrument",
columns: table => new
{
InstrumentId = table.Column<int>(nullable: false),
KursId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_KursInstrument", x => new { x.InstrumentId, x.KursId });
table.ForeignKey(
name: "FK_KursInstrument_Instrumente_InstrumentId",
column: x => x.InstrumentId,
principalTable: "Instrumente",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_KursInstrument_Kurse_KursId",
column: x => x.KursId,
principalTable: "Kurse",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "KursSchueler",
columns: table => new
{
SchuelerId = table.Column<int>(nullable: false),
KursId = table.Column<int>(nullable: false),
DozentId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_KursSchueler", x => new { x.SchuelerId, x.KursId });
table.ForeignKey(
name: "FK_KursSchueler_Donzenten_DozentId",
column: x => x.DozentId,
principalTable: "Donzenten",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_KursSchueler_Kurse_KursId",
column: x => x.KursId,
principalTable: "Kurse",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_KursSchueler_Schueler_SchuelerId",
column: x => x.SchuelerId,
principalTable: "Schueler",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "Unterrichte",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Startzeit = table.Column<DateTime>(nullable: false),
Notiz = table.Column<string>(nullable: true),
RaumId = table.Column<int>(nullable: true),
KursId = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Unterrichte", x => x.Id);
table.ForeignKey(
name: "FK_Unterrichte_Kurse_KursId",
column: x => x.KursId,
principalTable: "Kurse",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
table.ForeignKey(
name: "FK_Unterrichte_Raeume_RaumId",
column: x => x.RaumId,
principalTable: "Raeume",
principalColumn: "Id",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_Antraege_SchuelerId",
table: "Antraege",
column: "SchuelerId");
migrationBuilder.CreateIndex(
name: "IX_Antraege_UnterrichtTypId",
table: "Antraege",
column: "UnterrichtTypId");
migrationBuilder.CreateIndex(
name: "IX_AntragInstrument_AntragId",
table: "AntragInstrument",
column: "AntragId");
migrationBuilder.CreateIndex(
name: "IX_DozentInstrument_DozentId",
table: "DozentInstrument",
column: "DozentId");
migrationBuilder.CreateIndex(
name: "IX_Kurse_UnterrichtsTypId",
table: "Kurse",
column: "UnterrichtsTypId");
migrationBuilder.CreateIndex(
name: "IX_KursInstrument_KursId",
table: "KursInstrument",
column: "KursId");
migrationBuilder.CreateIndex(
name: "IX_KursSchueler_DozentId",
table: "KursSchueler",
column: "DozentId");
migrationBuilder.CreateIndex(
name: "IX_KursSchueler_KursId",
table: "KursSchueler",
column: "KursId");
migrationBuilder.CreateIndex(
name: "IX_RaumInstrument_RaumId",
table: "RaumInstrument",
column: "RaumId");
migrationBuilder.CreateIndex(
name: "IX_Unterrichte_KursId",
table: "Unterrichte",
column: "KursId");
migrationBuilder.CreateIndex(
name: "IX_Unterrichte_RaumId",
table: "Unterrichte",
column: "RaumId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "AntragInstrument");
migrationBuilder.DropTable(
name: "DozentInstrument");
migrationBuilder.DropTable(
name: "KursInstrument");
migrationBuilder.DropTable(
name: "KursSchueler");
migrationBuilder.DropTable(
name: "RaumInstrument");
migrationBuilder.DropTable(
name: "Unterrichte");
migrationBuilder.DropTable(
name: "Antraege");
migrationBuilder.DropTable(
name: "Donzenten");
migrationBuilder.DropTable(
name: "Instrumente");
migrationBuilder.DropTable(
name: "Kurse");
migrationBuilder.DropTable(
name: "Raeume");
migrationBuilder.DropTable(
name: "Schueler");
migrationBuilder.DropTable(
name: "UnterrichtTypen");
}
}
}

386
Backend/EVABackend/EVABackend/Migrations/EVA/EVAContextModelSnapshot.cs

@ -0,0 +1,386 @@
// <auto-generated />
using System;
using EVABackend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EVABackend.Migrations.EVA
{
[DbContext(typeof(EVAContext))]
partial class EVAContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.8-servicing-32085");
modelBuilder.Entity("EVABackend.Models.Antrag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("KursId");
b.Property<int?>("SchuelerId");
b.Property<int?>("UnterrichtTypId");
b.HasKey("Id");
b.HasIndex("SchuelerId");
b.HasIndex("UnterrichtTypId");
b.ToTable("Antraege");
});
modelBuilder.Entity("EVABackend.Models.AntragInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("AntragId");
b.HasKey("InstrumentId", "AntragId");
b.HasIndex("AntragId");
b.ToTable("AntragInstrument");
});
modelBuilder.Entity("EVABackend.Models.Dozent", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("BLZ")
.IsRequired();
b.Property<string>("Bankname")
.IsRequired();
b.Property<string>("EMail")
.IsRequired();
b.Property<DateTime>("Geburtsdatum");
b.Property<string>("Geburtsort")
.IsRequired();
b.Property<string>("KontoNr")
.IsRequired();
b.Property<string>("Name")
.IsRequired();
b.Property<string>("Ort")
.IsRequired();
b.Property<int>("PLZ");
b.Property<string>("Strasse")
.IsRequired();
b.Property<decimal>("Stundensatz");
b.Property<string>("Telefon")
.IsRequired();
b.Property<string>("Vorname")
.IsRequired();
b.HasKey("Id");
b.ToTable("Donzenten");
});
modelBuilder.Entity("EVABackend.Models.DozentInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("DozentId");
b.HasKey("InstrumentId", "DozentId");
b.HasIndex("DozentId");
b.ToTable("DozentInstrument");
});
modelBuilder.Entity("EVABackend.Models.Instrument", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("Instrumente");
});
modelBuilder.Entity("EVABackend.Models.Kurs", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Bestaetigt");
b.Property<int>("Kuendigungsfrist");
b.Property<int>("Laufzeit");
b.Property<string>("Name")
.IsRequired();
b.Property<int?>("UnterrichtsTypId");
b.HasKey("Id");
b.HasIndex("UnterrichtsTypId");
b.ToTable("Kurse");
});
modelBuilder.Entity("EVABackend.Models.KursInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("KursId");
b.HasKey("InstrumentId", "KursId");
b.HasIndex("KursId");
b.ToTable("KursInstrument");
});
modelBuilder.Entity("EVABackend.Models.KursSchueler", b =>
{
b.Property<int>("SchuelerId");
b.Property<int>("KursId");
b.Property<int?>("DozentId");
b.HasKey("SchuelerId", "KursId");
b.HasIndex("DozentId");
b.HasIndex("KursId");
b.ToTable("KursSchueler");
});
modelBuilder.Entity("EVABackend.Models.Raum", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<bool>("Belegt");
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("Raeume");
});
modelBuilder.Entity("EVABackend.Models.RaumInstrument", b =>
{
b.Property<int?>("InstrumentId");
b.Property<int?>("RaumId");
b.HasKey("InstrumentId", "RaumId");
b.HasIndex("RaumId");
b.ToTable("RaumInstrument");
});
modelBuilder.Entity("EVABackend.Models.Schueler", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("BLZ")
.IsRequired();
b.Property<string>("Bankname")
.IsRequired();
b.Property<string>("EMail")
.IsRequired();
b.Property<DateTime>("Geburtsdatum");
b.Property<string>("Geburtsort")
.IsRequired();
b.Property<bool>("IstErmaessigt");
b.Property<string>("KontoNr")
.IsRequired();
b.Property<string>("Name")
.IsRequired();
b.Property<string>("Ort")
.IsRequired();
b.Property<int>("PLZ");
b.Property<string>("Strasse")
.IsRequired();
b.Property<string>("Telefon")
.IsRequired();
b.Property<string>("Vorname")
.IsRequired();
b.HasKey("Id");
b.ToTable("Schueler");
});
modelBuilder.Entity("EVABackend.Models.Unterricht", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<int?>("KursId");
b.Property<string>("Notiz");
b.Property<int?>("RaumId");
b.Property<DateTime>("Startzeit");
b.HasKey("Id");
b.HasIndex("KursId");
b.HasIndex("RaumId");
b.ToTable("Unterrichte");
});
modelBuilder.Entity("EVABackend.Models.UnterrichtTyp", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("Name")
.IsRequired();
b.HasKey("Id");
b.ToTable("UnterrichtTypen");
});
modelBuilder.Entity("EVABackend.Models.Antrag", b =>
{
b.HasOne("EVABackend.Models.Schueler", "Schueler")
.WithMany()
.HasForeignKey("SchuelerId");
b.HasOne("EVABackend.Models.UnterrichtTyp", "UnterrichtTyp")
.WithMany()
.HasForeignKey("UnterrichtTypId");
});
modelBuilder.Entity("EVABackend.Models.AntragInstrument", b =>
{
b.HasOne("EVABackend.Models.Antrag", "Antrag")
.WithMany("Instrumente")
.HasForeignKey("AntragId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.DozentInstrument", b =>
{
b.HasOne("EVABackend.Models.Dozent", "Dozent")
.WithMany("Instrumente")
.HasForeignKey("DozentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.Kurs", b =>
{
b.HasOne("EVABackend.Models.UnterrichtTyp", "UnterrichtsTyp")
.WithMany()
.HasForeignKey("UnterrichtsTypId");
});
modelBuilder.Entity("EVABackend.Models.KursInstrument", b =>
{
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Kurs", "Kurs")
.WithMany("Instrumente")
.HasForeignKey("KursId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.KursSchueler", b =>
{
b.HasOne("EVABackend.Models.Dozent")
.WithMany("KursSchueler")
.HasForeignKey("DozentId");
b.HasOne("EVABackend.Models.Kurs", "Kurs")
.WithMany("KursSchueler")
.HasForeignKey("KursId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Schueler", "Schueler")
.WithMany("KursSchueler")
.HasForeignKey("SchuelerId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.RaumInstrument", b =>
{
b.HasOne("EVABackend.Models.Instrument", "Instrument")
.WithMany()
.HasForeignKey("InstrumentId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Models.Raum", "Raum")
.WithMany("Instrumente")
.HasForeignKey("RaumId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("EVABackend.Models.Unterricht", b =>
{
b.HasOne("EVABackend.Models.Kurs")
.WithMany("Unterrichte")
.HasForeignKey("KursId");
b.HasOne("EVABackend.Models.Raum", "Raum")
.WithMany()
.HasForeignKey("RaumId");
});
#pragma warning restore 612, 618
}
}
}

227
Backend/EVABackend/EVABackend/Migrations/EVABackendIdentityContextModelSnapshot.cs

@ -0,0 +1,227 @@
// <auto-generated />
using System;
using EVABackend.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace EVABackend.Migrations
{
[DbContext(typeof(EVABackendIdentityContext))]
partial class EVABackendIdentityContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.8-servicing-32085");
modelBuilder.Entity("EVABackend.Areas.Identity.Data.EVABackendUser", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<int>("AccessFailedCount");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Email")
.HasMaxLength(256);
b.Property<bool>("EmailConfirmed");
b.Property<bool>("LockoutEnabled");
b.Property<DateTimeOffset?>("LockoutEnd");
b.Property<string>("NormalizedEmail")
.HasMaxLength(256);
b.Property<string>("NormalizedUserName")
.HasMaxLength(256);
b.Property<string>("PasswordHash");
b.Property<string>("PhoneNumber");
b.Property<bool>("PhoneNumberConfirmed");
b.Property<string>("SecurityStamp");
b.Property<bool>("TwoFactorEnabled");
b.Property<string>("UserName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedEmail")
.HasName("EmailIndex");
b.HasIndex("NormalizedUserName")
.IsUnique()
.HasName("UserNameIndex");
b.ToTable("AspNetUsers");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b =>
{
b.Property<string>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken();
b.Property<string>("Name")
.HasMaxLength(256);
b.Property<string>("NormalizedName")
.HasMaxLength(256);
b.HasKey("Id");
b.HasIndex("NormalizedName")
.IsUnique()
.HasName("RoleNameIndex");
b.ToTable("AspNetRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("RoleId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("RoleId");
b.ToTable("AspNetRoleClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd();
b.Property<string>("ClaimType");
b.Property<string>("ClaimValue");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("Id");
b.HasIndex("UserId");
b.ToTable("AspNetUserClaims");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("ProviderKey")
.HasMaxLength(128);
b.Property<string>("ProviderDisplayName");
b.Property<string>("UserId")
.IsRequired();
b.HasKey("LoginProvider", "ProviderKey");
b.HasIndex("UserId");
b.ToTable("AspNetUserLogins");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("RoleId");
b.HasKey("UserId", "RoleId");
b.HasIndex("RoleId");
b.ToTable("AspNetUserRoles");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.Property<string>("UserId");
b.Property<string>("LoginProvider")
.HasMaxLength(128);
b.Property<string>("Name")
.HasMaxLength(128);
b.Property<string>("Value");
b.HasKey("UserId", "LoginProvider", "Name");
b.ToTable("AspNetUserTokens");
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole<string>", b =>
{
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole")
.WithMany()
.HasForeignKey("RoleId")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken<string>", b =>
{
b.HasOne("EVABackend.Areas.Identity.Data.EVABackendUser")
.WithMany()
.HasForeignKey("UserId")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

42
Backend/EVABackend/EVABackend/Models/Aufnahmeantrag.cs

@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EVABackend.Models
{
public class Aufnahmeantrag
{
[Required]
public string Name { get; set; }
[Required]
public string Vonname { get; set; }
public bool IstErmaessigt { get; set; }
public DateTime Geburtsdatum { get; set; }
[Required]
public string Geburtsort { get; set; }
[Range(1, 100000)]
public int PLZ { get; set; }
[Required]
public string Ort { get; set; }
[Required]
public string StrasseHNR { get; set; }
[Required]
public string Bankname { get; set; }
[Required]
public string BLZ { get; set; }
[Required]
public string KontoNr { get; set; }
[Required]
public UnterrichtTyp Typ { get; set; }
[Required]
public List<int> Instrumente { get; set; }
[Required]
public string Laufzeit { get; set; }
[Required]
public string KursId { get; set; }
[Required]
public string Telefon { get; set; }
[Required]
public string EMail { get; set; }
}
}

13
Backend/EVABackend/EVABackend/Models/CreateRooms.cs

@ -0,0 +1,13 @@
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace EVABackend.Models
{
public class CreateRooms
{
[Required]
public string Name { get; set; }
[Required]
public List<string> InstrumentIDs { get; set; }
}
}

227
Backend/EVABackend/EVABackend/Models/EVAContext.cs

@ -0,0 +1,227 @@
using System.Reflection.Emit;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EVABackend.Models
{
public class EVAContext : DbContext
{
public DbSet<Schueler> Schueler { get; set; }
public DbSet<Dozent> Donzenten { get; set; }
public DbSet<Kurs> Kurse { get; set; }
public DbSet<KursSchueler> KursSchueler { get; set; }
public DbSet<Unterricht> Unterrichte { get; set; }
public DbSet<Instrument> Instrumente { get; set; }
public DbSet<Raum> Raeume { get; set; }
public DbSet<Antrag> Antraege { get; set; }
public DbSet<UnterrichtTyp> UnterrichtTypen { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite("Data Source=eva_ls.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<KursSchueler>()
.HasKey(c => new { c.SchuelerId, c.KursId });
modelBuilder.Entity<RaumInstrument>()
.HasKey(c => new { c.InstrumentId, c.RaumId });
modelBuilder.Entity<KursInstrument>()
.HasKey(c => new { c.InstrumentId, c.KursId });
modelBuilder.Entity<DozentInstrument>()
.HasKey(c => new { c.InstrumentId, c.DozentId });
modelBuilder.Entity<AntragInstrument>()
.HasKey(c => new { c.InstrumentId, c.AntragId });
modelBuilder.Entity<KursSchueler>()
.HasOne(c => c.Schueler)
.WithMany(c => c.KursSchueler)
.HasForeignKey(c => c.SchuelerId);
modelBuilder.Entity<KursSchueler>()
.HasOne(c => c.Kurs)
.WithMany(c => c.KursSchueler)
.HasForeignKey(c => c.KursId);
modelBuilder.Entity<Kurs>()
.HasMany(c => c.Instrumente)
.WithOne(c => c.Kurs)
.HasForeignKey(c => c.KursId);
modelBuilder.Entity<Dozent>()
.HasMany(c => c.Instrumente)
.WithOne(c => c.Dozent)
.HasForeignKey(c => c.DozentId);
modelBuilder.Entity<Raum>()
.HasMany(c => c.Instrumente)
.WithOne(c => c.Raum)
.HasForeignKey(c => c.RaumId);
modelBuilder.Entity<Antrag>()
.HasMany(c => c.Instrumente)
.WithOne(c => c.Antrag)
.HasForeignKey(c => c.AntragId);
}
}
public abstract class Person
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public string Vorname { get; set; }
public DateTime Geburtsdatum { get; set; }
[Required]
public string Geburtsort { get; set; }
public int PLZ { get; set; }
[Required]
public string Ort { get; set; }
[Required]
public string Strasse { get; set; }
[Required]
public string Telefon { get; set; }
[Required]
public string EMail { get; set; }
[Required]
public string Bankname { get; set; }
[Required]
public string BLZ { get; set; }
[Required]
public string KontoNr { get; set; }
public virtual ICollection<KursSchueler> KursSchueler { get; set; }
}
public class Schueler : Person
{
public bool IstErmaessigt { get; set; }
}
public class Dozent : Person
{
public decimal Stundensatz { get; set; }
public virtual ICollection<DozentInstrument> Instrumente { get; set; }
}
public class Kurs
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public int Laufzeit { get; set; }
public int Kuendigungsfrist { get; set; }
public bool Bestaetigt { get; set; }
public UnterrichtTyp UnterrichtsTyp { get; set; }
public virtual ICollection<KursInstrument> Instrumente { get; set; }
public virtual ICollection<Unterricht> Unterrichte { get; set; }
public virtual ICollection<KursSchueler> KursSchueler { get; set; }
}
public class KursSchueler
{
public int SchuelerId { get; set; }
public int KursId { get; set; }
public virtual Schueler Schueler { get; set; }
public virtual Kurs Kurs { get; set; }
}
public class Unterricht
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public DateTime Startzeit { get; set; }
public string Notiz { get; set; }
public Raum Raum { get; set; }
}
public class Raum
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
public bool Belegt { get; set; }
public virtual ICollection<RaumInstrument> Instrumente { get; set; }
}
public class Antrag
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public Schueler Schueler { get; set; }
public UnterrichtTyp UnterrichtTyp { get; set; }
public int KursId { get; set; }
public virtual ICollection<AntragInstrument> Instrumente { get; set; }
}
public class UnterrichtTyp
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class Instrument
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
[Required]
public string Name { get; set; }
}
public class KursInstrument
{
public int? InstrumentId { get; set; }
public Instrument Instrument { get; set; }
public int? KursId { get; set; }
public Kurs Kurs { get; set; }
}
public class RaumInstrument
{
public int? InstrumentId { get; set; }
public Instrument Instrument { get; set; }
public int? RaumId { get; set; }
public Raum Raum { get; set; }
}
public class DozentInstrument
{
public int? InstrumentId { get; set; }
public Instrument Instrument { get; set; }
public int? DozentId { get; set; }
public Dozent Dozent { get; set; }
}
public class AntragInstrument
{
public int? InstrumentId { get; set; }
public Instrument Instrument { get; set; }
public int? AntragId { get; set; }
public Antrag Antrag { get; set; }
}
//public enum InstrumentTyp
//{
// Klavier, Schlagzeug, Geige, Gitarre, Band
//}
}

6
Backend/EVABackend/EVABackend/Properties/launchSettings.json

@ -12,7 +12,7 @@
"IIS Express": { "IIS Express": {
"commandName": "IISExpress", "commandName": "IISExpress",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "api/values", "launchUrl": "login",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
} }
@ -20,7 +20,7 @@
"EVABackend": { "EVABackend": {
"commandName": "Project", "commandName": "Project",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "api/values", "launchUrl": "login",
"environmentVariables": { "environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development" "ASPNETCORE_ENVIRONMENT": "Development"
}, },
@ -29,7 +29,7 @@
"Docker": { "Docker": {
"commandName": "Docker", "commandName": "Docker",
"launchBrowser": true, "launchBrowser": true,
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/api/values", "launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}/login",
"httpPort": 50571, "httpPort": 50571,
"useSSL": true, "useSSL": true,
"sslPort": 44375 "sslPort": 44375

26
Backend/EVABackend/EVABackend/ScaffoldingReadme.txt

@ -0,0 +1,26 @@
Support for ASP.NET Core Identity was added to your project
- The code for adding Identity to your project was generated under Areas/Identity.
Configuration of the Identity related services can be found in the Areas/Identity/IdentityHostingStartup.cs file.
If your app was previously configured to use Identity, then you should remove the call to the AddIdentity method from your ConfigureServices method.
The generated UI requires support for static files. To add static files to your app:
1. Call app.UseStaticFiles() from your Configure method
To use ASP.NET Core Identity you also need to enable authentication. To authentication to your app:
1. Call app.UseAuthentication() from your Configure method (after static files)
The generated UI requires MVC. To add MVC to your app:
1. Call services.AddMvc() from your ConfigureServices method
2. Call app.UseMvc() from your Configure method (after authentication)
The generated database code requires Entity Framework Core Migrations. Run the following commands:
1. dotnet ef migrations add CreateIdentitySchema
2. dotnet ef database update
Or from the Visual Studio Package Manager Console:
1. Add-Migration CreateIdentitySchema
2. Update-Database
Apps that use ASP.NET Core Identity should also use HTTPS. To enable HTTPS see https://go.microsoft.com/fwlink/?linkid=848054.

11
Backend/EVABackend/EVABackend/Startup.cs

@ -1,15 +1,10 @@
using System; using EVABackend.Areas.Identity.Data;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace EVABackend namespace EVABackend
{ {
@ -40,6 +35,8 @@ namespace EVABackend
app.UseHsts(); app.UseHsts();
} }
app.UseStaticFiles();
app.UseAuthentication();
app.UseHttpsRedirection(); app.UseHttpsRedirection();
app.UseMvc(); app.UseMvc();
} }

7
Backend/EVABackend/EVABackend/appsettings.json

@ -4,5 +4,8 @@
"Default": "Warning" "Default": "Warning"
} }
}, },
"AllowedHosts": "*" "AllowedHosts": "*",
} "ConnectionStrings": {
"EVABackendIdentityContextConnection": "DataSource=EVABackend.db"
}
}

BIN
Backend/EVABackend/EVABackend/eva_ls.db

Binary file not shown.

BIN
Backend/EVABackend/EVABackend/eva_users.db

Binary file not shown.

15
Frontend/src/components/App.js

@ -5,12 +5,23 @@ import Login from "./Login.js";
import { Box } from "@material-ui/core"; import { Box } from "@material-ui/core";
import Aufnahmeantrag from "./Aufnahmeantrag.js"; import Aufnahmeantrag from "./Aufnahmeantrag.js";
import {RoomOverview} from "./RoomOverview"; import {RoomOverview} from "./RoomOverview";
import { createMuiTheme, MuiThemeProvider } from "@material-ui/core";
const theme = createMuiTheme({
palette: {
primary: { main: "#2e294e" },
grey: { main: "#595959" },
danger: { main: "#d90368" },
secondary: { main: "#eadeda" },
text: { main: "#ffffff" }
}
});
class App extends Component { class App extends Component {
state = {}; state = {};
render() { render() {
return ( return (
<> <MuiThemeProvider theme={theme}>
<CssBaseline /> <CssBaseline />
<Router> <Router>
<Box flexDirection="column" width="100%"> <Box flexDirection="column" width="100%">
@ -19,7 +30,7 @@ class App extends Component {
<Route path="/raumübersicht" component={RoomOverview} /> <Route path="/raumübersicht" component={RoomOverview} />
</Box> </Box>
</Router> </Router>
</> </MuiThemeProvider>
); );
} }
} }

4
Frontend/src/components/Aufnahmeantrag.js

@ -25,7 +25,7 @@ const useStyles = createStyles(theme => ({
margin: theme.spacing(1) margin: theme.spacing(1)
}, },
form: { form: {
backgroundColor: "#f5f5f5", backgroundColor: "rgba(255, 255, 255, 1)",
borderRadius: "5px", borderRadius: "5px",
margin: "20px", margin: "20px",
padding: "20px", padding: "20px",
@ -39,7 +39,7 @@ const useStyles = createStyles(theme => ({
marginLeft: "7px" marginLeft: "7px"
}, },
instruments: { instruments: {
border: "1px solid lightgrey", border: "1px solid #bbb",
borderRadius: "5px", borderRadius: "5px",
display: "flex", display: "flex",
flexWrap: "wrap", flexWrap: "wrap",

98
Frontend/src/components/Login.js

@ -1,36 +1,80 @@
import React, { Component } from "react"; import React, { Component } from "react";
import TextField from "@material-ui/core/TextField"; import { TextField, Typography, Grid, Fab, Container } from "@material-ui/core";
import SendIcon from "@material-ui/icons/Send";
import { withStyles, createStyles } from "@material-ui/styles";
const useStyles = createStyles(theme => ({
textField: {
margingLeft: theme.spacing(1),
marginRight: theme.spacing(1)
},
fab: {
margin: theme.spacing(1)
},
form: {
backgroundColor: "#f5f5f5",
borderRadius: "5px",
margin: "20px",
padding: "20px",
boxShadow: "0px 0px 5px 0px lightgrey",
border: "1px solid lightgrey"
}
}));
class Login extends Component { class Login extends Component {
state = {}; state = { username: "", password: "" };
handleChange = name => event => {
this.setState({ [name]: event.target.value });
};
render() { render() {
const classes = this.props.classes;
return ( return (
<form> <Container maxWidth="md">
<TextField <div className={classes.form}>
variant="outlined" <Grid container direction="row" justify="center" alignItems="center">
margin="normal" <Grid container spacing={1}>
required <Grid item xs={12}>
fullWidth <Typography align="center" variant="h4">
id="email" Login
label="Email Address" </Typography>
name="email" </Grid>
autoComplete="email" <Grid item xs={12}>
autoFocus <TextField
/> fullWidth={true}
<TextField id="outlined-name"
type="password" label="Username"
variant="outlined" className={classes.textField}
margin="normal" value={this.state.username}
required onChange={this.handleChange("username")}
fullWidth margin="normal"
id="password" variant="outlined"
label="Password" />
name="password" </Grid>
autoComplete="password" <Grid item xs={12}>
/> <TextField
</form> fullWidth={true}
id="outlined-name"
label="Password"
className={classes.textField}
value={this.state.password}
onChange={this.handleChange("password")}
margin="normal"
variant="outlined"
type="password"
/>
</Grid>
</Grid>
<Fab color="primary" aria-label="Send" className={classes.fab}>
<SendIcon />
</Fab>
</Grid>
</div>
</Container>
); );
} }
} }
export default Login; export default withStyles(useStyles)(Login);

5
Frontend/src/style/index.css

@ -4,6 +4,7 @@ body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
"Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
sans-serif; sans-serif;
background-color: rgba(234, 222, 218, 1) !important;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
@ -12,3 +13,7 @@ code {
font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New",
monospace; monospace;
} }
html {
background-color: rgba(234, 222, 218, 1);
}

22
_Dokumente/Ausgearbeitete Dokumente/Endpoints.md

@ -85,6 +85,7 @@ Zusäzlich ist angegeben, für welche Benutzerrollen die jeweiligen Funktionen z
- Liefert Array - Liefert Array
- RaumID string - RaumID string
- RaumName string - RaumName string
- Belegt bool
- Instrumente Array - Instrumente Array
- InstrumentID string - InstrumentID string
- InstrumentName string - InstrumentName string
@ -101,19 +102,24 @@ Zusäzlich ist angegeben, für welche Benutzerrollen die jeweiligen Funktionen z
- RaumID string - RaumID string
- Liefert object - Liefert object
- Belegt bool - Belegt bool
- GET room_instruments - GET room_details
- Liefert alle Instrumente zu einem Raum - Liefert Daten zu einem Raum
- Parameter - Paramter
- RaumID string - RaumID string
- Liefert Array - Liefert
- InstrumentID string - RaumID string
- InstrumentName string - RaumName string
- Vorhanden bool - Belegt true
- Instrumente Array
- InstrumentID string
- InstrumentName string
- Vorhanden bool
- GET lessons - GET lessons
- Liefert alle Unterrichtszeiten in einem Raum - Liefert alle Unterrichtszeiten in einem Raum
- Parameter - Parameter
- RaumID string - RaumID string
- Liefert Array - Liefert Array
- KursName string
- StartZeit DateTime - StartZeit DateTime
### Kurs Erstellen [Person + Kurs] (Verwaltung) ### Kurs Erstellen [Person + Kurs] (Verwaltung)

BIN
_Dokumente/Ausgearbeitete Dokumente/LS Musikschule. PROJEKTSTRUKTURPLAN.xlsx

Binary file not shown.

216
_Dokumente/Ausgearbeitete Dokumente/Pflichtenheft.md

@ -1,114 +1,118 @@
# Pflichtenheft # Pflichtenheft
## Inhalt ## Inhalt
- [Pflichtenheft](#pflichtenheft) - [Pflichtenheft](#Pflichtenheft)
- [Inhalt](#inhalt) - [Inhalt](#Inhalt)
- [Zielbestimmungsss](#zielbestimmungsss) - [Zielbestimmung](#Zielbestimmung)
- [Musskriterien](#musskriterien) - [Musskriterien](#Musskriterien)
- [Wunschkriterien](#wunschkriterien) - [Wunschkriterien](#Wunschkriterien)
- [Abgrenzungungskriterien](#abgrenzungungskriterien) - [Abgrenzungungskriterien](#Abgrenzungungskriterien)
- [Produktübersicht](#produkt%C3%BCbersicht) - [Produktübersicht](#Produkt%C3%BCbersicht)
- [Produktdaten](#produktdaten) - [Produktdaten](#Produktdaten)
- [Speichernutzung](#speichernutzung) - [Speichernutzung](#Speichernutzung)
- [Produktleistungen](#produktleistungen) - [Produktleistungen](#Produktleistungen)
- [Benutzeroberfläche **/L01/**](#benutzeroberfl%C3%A4che-l01) - [Benutzeroberfläche **/L01/**](#Benutzeroberfl%C3%A4che-L01)
- [Datenschutz **/L02/**](#datenschutz-l02) - [Datenschutz **/L02/**](#Datenschutz-L02)
- [Loggin und Nachvollziehbarkeit **/L03/**](#loggin-und-nachvollziehbarkeit-l03) - [Loggin und Nachvollziehbarkeit **/L03/**](#Loggin-und-Nachvollziehbarkeit-L03)
- [Produkteinsatz](#produkteinsatz) - [Produkteinsatz](#Produkteinsatz)
- [Anwendungsbereiche](#anwendungsbereiche) - [Anwendungsbereiche](#Anwendungsbereiche)
- [Zielgruppe](#zielgruppe) - [Zielgruppe](#Zielgruppe)
- [Betriebsbedingungen](#betriebsbedingungen) - [Betriebsbedingungen](#Betriebsbedingungen)
- [Produktumgebung](#produktumgebung) - [Produktumgebung](#Produktumgebung)
- [Software](#software) - [Software](#Software)
- [Hardware](#hardware) - [Hardware](#Hardware)
- [Entwicklungsumgebung](#entwicklungsumgebung) - [Entwicklungsumgebung](#Entwicklungsumgebung)
- [Software](#software-1) - [Software](#Software-1)
- [Backend](#backend) - [Backend](#Backend)
- [Frontend](#frontend) - [Frontend](#Frontend)
- [Hardware](#hardware-1) - [Hardware](#Hardware-1)
- [Backend und Frontend](#backend-und-frontend) - [Backend und Frontend](#Backend-und-Frontend)
- [Orgware](#orgware) - [Orgware](#Orgware)
- [Backend und Frontend](#backend-und-frontend-1) - [Backend und Frontend](#Backend-und-Frontend-1)
- [Produktfunktionen](#produktfunktionen) - [Produktfunktionen](#Produktfunktionen)
- [Annahmen und Definitionen zu Produktfunktionen](#annahmen-und-definitionen-zu-produktfunktionen) - [Annahmen und Definitionen zu Produktfunktionen](#Annahmen-und-Definitionen-zu-Produktfunktionen)
- [Dozentenfunktionen](#dozentenfunktionen) - [Dozentenfunktionen](#Dozentenfunktionen)
- [Wochenübersicht **/FD01/**](#wochen%C3%BCbersicht-fd01) - [Wochenübersicht **/FD01/**](#Wochen%C3%BCbersicht-FD01)
- [Kursdetails **/FD02/**](#kursdetails-fd02) - [Kursdetails **/FD02/**](#Kursdetails-FD02)
- [Verwaltungsfunktionen](#verwaltungsfunktionen) - [Verwaltungsfunktionen](#Verwaltungsfunktionen)
- [Offene Anträge **/FV01/**](#offene-antr%C3%A4ge-fv01) - [Offene Anträge **/FV01/**](#Offene-Antr%C3%A4ge-FV01)
- [Kurs Erstellen **/FV02/**](#kurs-erstellen-fv02) - [Kurs Erstellen **/FV02/**](#Kurs-Erstellen-FV02)
- [Kursübersicht **/FV03/**](#kurs%C3%BCbersicht-fv03) - [Kursübersicht **/FV03/**](#Kurs%C3%BCbersicht-FV03)
- [Schülerübersicht **/FV04/**](#sch%C3%BCler%C3%BCbersicht-fv04) - [Schülerübersicht **/FV04/**](#Sch%C3%BCler%C3%BCbersicht-FV04)
- [Schüler eines Dozenten **/FV05/**](#sch%C3%BCler-eines-dozenten-fv05) - [Schüler eines Dozenten **/FV05/**](#Sch%C3%BCler-eines-Dozenten-FV05)
- [Raumübersicht **/FV06/**](#raum%C3%BCbersicht-fv06) - [Raumübersicht **/FV06/**](#Raum%C3%BCbersicht-FV06)
- [Raumdetails **/FV07/**](#raumdetails-fv07) - [Raumdetails **/FV07/**](#Raumdetails-FV07)
- [Finanzübersicht **/FV09/**](#finanz%C3%BCbersicht-fv09) - [Finanzübersicht **/FV09/**](#Finanz%C3%BCbersicht-FV09)
- [Sonstige Funktionen](#sonstige-funktionen) - [Sonstige Funktionen](#Sonstige-Funktionen)
- [Login **/F01/**](#login-f01) - [Login **/F01/**](#Login-F01)
- [Mitglied zu Kurs hinzufügen **/F02/**](#mitglied-zu-kurs-hinzuf%C3%BCgen-f02) - [Mitglied zu Kurs hinzufügen **/F02/**](#Mitglied-zu-Kurs-hinzuf%C3%BCgen-F02)
- [Antrag Stellen **/F03/**](#antrag-stellen-f03) - [Antrag Stellen **/F03/**](#Antrag-Stellen-F03)
- [Benutzeroberfläche](#benutzeroberfl%C3%A4che) - [Benutzeroberfläche](#Benutzeroberfl%C3%A4che)
- [Dialogstruktur](#dialogstruktur) - [Dialogstruktur](#Dialogstruktur)
- [Startseite](#startseite) - [Startseite](#Startseite)
- [Übersichtsseite Dozenten](#%C3%BCbersichtsseite-dozenten) - [Übersichtsseite Dozenten](#%C3%9Cbersichtsseite-Dozenten)
- [Übersichtsseite Verwaltung](#%C3%BCbersichtsseite-verwaltung) - [Übersichtsseite Verwaltung](#%C3%9Cbersichtsseite-Verwaltung)
- [Bildschirmlayout](#bildschirmlayout) - [Bildschirmlayout](#Bildschirmlayout)
- [Testfälle](#testf%C3%A4lle) - [Testfälle](#Testf%C3%A4lle)
## Zielbestimmungsss <div class="page"/>
## Zielbestimmung
> Das Ziel von Parsec Iron Puffin (*PIP*) ist es, eine Anwendung zu bieten welche die Organisation der Musikschule erlaubt. Hierzu werden für Dozenten und Verwaltung verschiedene administrative Funktionen bereitgestellt. Die aktuellen Betriebsprozesse sollen vereinfacht und beschleunigt werden. > Das Ziel von Parsec Iron Puffin (*PIP*) ist es, eine Anwendung zu bieten welche die Organisation der Musikschule erlaubt. Hierzu werden für Dozenten und Verwaltung verschiedene administrative Funktionen bereitgestellt. Die aktuellen Betriebsprozesse sollen vereinfacht und beschleunigt werden.
Die Anwendung bietet der Verwaltung Übersichten über die Schüler, Dozenten, Kurse und Finanzen. Es können Schüler der Kurse und Dozenten der Schüler angezeigt werden. Die Anwendung bietet der Verwaltung Übersichten über die Schüler, Dozenten, Kurse und Finanzen. Es können Schüler der Kurse und Dozenten der Schüler angezeigt werden.
Der Dozent erhält eine Übersicht über die Stunden, welche er in der Woch zu unterrichten hat. Außerdem kann er eine Detailansicht eines Kurses aufrufen, welche ihm Informationen über die Schüler in diesem Kurs und die Unterrichtsinhalte der vergangenen Stunden bietet. Der Dozent erhält eine Übersicht über die Stunden, welche er in der Woche zu unterrichten hat. Außerdem kann er eine Detailansicht eines Kurses aufrufen, welche ihm Informationen über die Schüler in diesem Kurs und die Unterrichtsinhalte der vergangenen Stunden bietet.
Nutzer können mithilfe der Anwendung Kurse beantragen und "Band"-Kursen beitreten. Nutzer können mithilfe der Anwendung Kurse beantragen und "Band"-Kursen beitreten.
### Musskriterien ### Musskriterien
* Es besteht ein Authentifizierung um den Zugriff auf alle Funktionen auf die jeweils berechtigten Personen zu beschränken. * Es besteht eine Authentifizierung um den Zugriff auf alle Funktionen auf die jeweils berechtigten Personen zu beschränken.
* Der Dozent * Der Dozent
* Kann seine Stunden in der kommenden Woche sehen können. * Kann seine Stunden in der kommenden Woche sehen.
* Kann den Inhalt seiner Kurs für jede Unterrichtseinheit (*UE*) pflegen. * Kann den Inhalt seiner Kurse für jede Unterrichtseinheit (*UE*) pflegen.
* Kann die Schüler eines Kurses sehen. * Kann die Schüler eines Kurses sehen.
* Die Verwaltung * Die Verwaltung
* Kann sehen, welcher Lehrer welchen Kurs leitet. * Kann sehen, welcher Dozent welchen Kurs leitet.
* Kann sehen, welcher Schüler an welchem Kurs teilnimmt. * Kann sehen, welcher Schüler an welchem Kurs teilnimmt.
* Kann sehen, welche Schüler von einem gegebenen Lehrer unterrichtet werden. * Kann sehen, welche Schüler von einem gegebenen Dozent unterrichtet werden.
* Kann Räume anlegen. * Kann Räume anlegen.
* Kann bearbeiten, welche Instrumente in einem Raum zu verfügung stehen. * Kann bearbeiten, welche Instrumente in einem Raum zur Verfügung stehen.
* Kann die aktuelle Verfügbarkeit und die nächsten Termine eines Raumes sehen. * Kann die aktuelle Verfügbarkeit und die nächsten Termine eines Raumes sehen.
* Kann offene Anträge sehen. * Kann offene Anträge sehen.
* Kann aus eingehenden Anträgen neue Kurs erstellen und UE planen. * Kann aus eingehenden Anträgen neue Kurse erstellen und UE planen.
* Kann in einer Übersicht die Einnahmen der Musikschule und den Betrag, welcher an jeden Dozent gezahlt wird sehen. * Kann in einer Übersicht die Einnahmen der Musikschule und den Betrag, welcher an jeden Dozent gezahlt wird, sehen.
* Der Administrative Nutzer * Der Administrative Nutzer
* Konfiguriert die Betriebsparameter des Systems * Konfiguriert die Betriebsparameter des Systems.
* Sichert die Datenbank * Sichert die Datenbank.
* Der Schüler * Der Schüler
* kann einen Aufnahmeantrag über ein Webformular abschicken * Kann einen Aufnahmeantrag über ein Webformular abschicken
* erhält, nachdem die Verwaltung einen Kurs aus dem Antrag erstellt hat, eine Bestätigung (Kursbestätigung) mit den Zeiten Seiner Unterrichtseinheiten * Erhält, nachdem die Verwaltung einen Kurs aus dem Antrag erstellt hat, eine Bestätigung (Kursbestätigung) mit den Zeiten seiner Unterrichtseinheiten.
* hat bis zum ersten Unterrichtstermin Zeit, um den Unterricht zu bestätigen * Hat bis zum ersten Unterrichtstermin Zeit, um den Unterricht zu bestätigen.
* Sonstiges * Sonstiges
* Deutsch ist Verkehrssprache * Deutsch ist Verkehrssprache.
* Alle Funktionen sind über das Internet erreichbar * Alle Funktionen sind über das Internet erreichbar.
* Die Anwendung ist für Mobilgeräte optimiert * Die Anwendung ist für Mobilgeräte optimiert.
### Wunschkriterien ### Wunschkriterien
* Der Administrative Nutzer * Der Administrative Nutzer
* Möchte bei der Erstellung eines Kurses durch einen Vorschlag zu passendem Raum, Dozenten und Zeitpunkt unterstützt werden. * Möchte bei der Erstellung eines Kurses durch einen Vorschlag zu passendem Raum, Dozenten und Zeitpunkt unterstützt werden.
* Der Schüler * Der Schüler
* Möchte sich einloggen können um die eigenen Unterrichtszeiten und Inhalte einzusehen * Möchte sich einloggen können um die eigenen Unterrichtszeiten und Inhalte einzusehen.
* Sonstiges * Sonstiges
* Daten sollen soweit sinnvoll möglich auf dem Endgerät zwischengespeichert werden, damit auch ohne Internetverbindung Grundlegende funktionalität geleistet werden kann. * Daten sollen soweit sinnvoll möglich auf dem Endgerät zwischengespeichert werden, damit auch ohne Internetverbindung grundlegende Funktionalität geleistet werden kann.
### Abgrenzungungskriterien ### Abgrenzungungskriterien
* Das *PIP* * Das *PIP*
* soll keine Abrechnung erstellen oder verschicken. * Soll keine Abrechnung erstellen oder verschicken.
## Produktübersicht ## Produktübersicht
* Das System wird von den Rollen Verwaltung, Dozent und Anonym bedient. * Das System wird von den Rollen Verwaltung, Dozent und Anonym bedient.
* Die Rollen Verwaltung und Dozent werden über einen Login authentizifiert, ihnen stehen abhängig von ihrer Rolle verschiedene Funktionen zur verfügung, diese werden unter [Produktfunktionen](#produktfunktionen) spezifiziert. Sonstige Funktionen stehen _allen_ Rollen zur verfügung. * Die Rollen Verwaltung und Dozent werden über einen Login authentizifiert, ihnen stehen abhängig von ihrer Rolle verschiedene Funktionen zur verfügung, diese werden unter [Produktfunktionen](#produktfunktionen) spezifiziert. Sonstige Funktionen stehen _allen_ Rollen zur verfügung.
<div class="page"/>
## Produktdaten ## Produktdaten
* Datenstrukturen der Anwendung: * Datenstrukturen der Anwendung:
![ERD](EVA&#32;ERD&#32;Umletino.png) ![ERD](EVA&#32;ERD&#32;Umletino.png)
@ -124,6 +128,8 @@ Nutzer können mithilfe der Anwendung Kurse beantragen und "Band"-Kursen beitret
* Ein Kursdatensatzen kann bis zu 55 Byte groß sein. * Ein Kursdatensatzen kann bis zu 55 Byte groß sein.
* Ein Unterrichtseinheitendatensatz kann bis zu 2056 Byte groß sein. * Ein Unterrichtseinheitendatensatz kann bis zu 2056 Byte groß sein.
<div class="page"/>
## Produktleistungen ## Produktleistungen
### Benutzeroberfläche **/L01/** ### Benutzeroberfläche **/L01/**
* Die Anwendung bietet eine deutschsprachige Benutzeroberfläche * Die Anwendung bietet eine deutschsprachige Benutzeroberfläche
@ -132,7 +138,9 @@ Nutzer können mithilfe der Anwendung Kurse beantragen und "Band"-Kursen beitret
### Loggin und Nachvollziehbarkeit **/L03/** ### Loggin und Nachvollziehbarkeit **/L03/**
* Zugriffe wie das Schreiben von Daten (anlegen und modifizieren von Datensätzen) werden in einem Log dokumentiert und können so nachvollzogen werden. * Zugriffe wie das Schreiben von Daten (anlegen und modifizieren von Datensätzen) werden in einem Log dokumentiert und können so nachvollzogen werden.
## Produkteinsatz <div class="page"/>
## Produkteinsatz
### Anwendungsbereiche ### Anwendungsbereiche
Die Anwendung wird von den Dozenten und der Verwaltung zur Planung und Organisation der Musikschule genutzt. Die Anwendung wird von den Dozenten und der Verwaltung zur Planung und Organisation der Musikschule genutzt.
@ -146,6 +154,8 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
* Die Anwendung ist global über das Internet erreichbar * Die Anwendung ist global über das Internet erreichbar
* Der Betrieb wird vom Auftragnehmer überwacht * Der Betrieb wird vom Auftragnehmer überwacht
<div class="page"/>
## Produktumgebung ## Produktumgebung
### Software ### Software
* Client * Client
@ -160,11 +170,13 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
* Internetfähiger Server * Internetfähiger Server
* Ausreichende Rechen- und Festplattenkapazität * Ausreichende Rechen- und Festplattenkapazität
<div class="page"/>
## Entwicklungsumgebung ## Entwicklungsumgebung
### Software ### Software
#### Backend #### Backend
* Entwickler nutzen die IDE Visual Studio 2019 von Microsoft * Entwickler nutzen die IDE Visual Studio 2019 von Microsoft
* Zum Untersuchen der Datenbank wird der DB Browser genutzt * Zum Untersuchen der Datenbank wird ein DB Browser genutzt
* Code wird mithilfe des .NET Komplierers kompiliert * Code wird mithilfe des .NET Komplierers kompiliert
* Als Betriebssystem wird Microsoft Windows genutzt * Als Betriebssystem wird Microsoft Windows genutzt
* Als Codeverwaltung wird Gitlab CE genutzt * Als Codeverwaltung wird Gitlab CE genutzt
@ -188,20 +200,22 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
* Als Codeverwaltung wird Gitlab CE genutzt * Als Codeverwaltung wird Gitlab CE genutzt
* Als CI/CD Tool wird Gitlab CI/CD genutzt * Als CI/CD Tool wird Gitlab CI/CD genutzt
<div class="page"/>
## Produktfunktionen ## Produktfunktionen
#### Annahmen und Definitionen zu Produktfunktionen #### Annahmen und Definitionen zu Produktfunktionen
> Getroffene Annahmen und Definitionen zu unterliegenen Produktfunktionen und Geschäftsprozessen, mit denen die Nutzer nicht direkt in Kontakt kommen und daher nicht einer speziellen Funktion zugeordnet werden können. > Getroffene Annahmen und Definitionen zu unterliegenen Produktfunktionen und Geschäftsprozessen, mit denen die Nutzer nicht direkt in Kontakt kommen und daher nicht einer speziellen Funktion zugeordnet werden können.
* Aus einem eingegangenen Antrag wird wird von der Verwaltung mithilfe der gebotenen Funktion ein Kurs erstellt. Hierfür wählt diese einene passenden Dozenten, Raum, und Zeitpunkt(e) aus. Diese werden dem Antragsteller auf geeignetem Weg, zusammen mit einem ausgefertigtem Vertrag zustellt. Der Antragsteller hat bis zum ersten Unterrichtszeitpunkt Zeit, um diesen Vertrag unterschrieben vorzulegen, ansonsten verfällt der Kurs und Dozent und Raum werden zu dem Zeitpunkt(en) freigegeben. * Aus einem eingegangenen Antrag wird von der Verwaltung mithilfe der gebotenen Funktion ein Kurs erstellt. Hierfür wählt diese einen passenden Dozenten, Raum, und UEs aus. Diese werden dem Antragsteller auf geeignetem Weg, zusammen mit einem ausgefertigtem Vertrag, zustellt. Der Antragsteller hat bis zum ersten Unterrichtszeitpunkt Zeit, um diesen Vertrag unterschrieben vorzulegen. Ansonsten verfällt der Kurs und Dozent und Raum werden zu den Zeitpunkten der geplanten UEs freigegeben.
* Im Falle eines "Band"-Kurses wird dem Antragsteller zusammen mit dem Vertrag ein Einzigartiger Link zugestellt. Über diesen Link können sich weiter Mitglieder durch angeben ihrer personenbezogenen Daten zu diesem bereits erstellten Kurs anmelden. Die Anmeldung ist bis zum ersten Unterrichtszeitpunkt möglich. * Im Falle eines "Band"-Kurses wird dem Antragsteller zusammen mit dem Vertrag ein einzigartiger Link zugestellt. Über diesen Link können sich weitere Mitglieder durch angeben ihrer personenbezogenen Daten zu diesem bereits erstellten Kurs anmelden. Die Anmeldung ist bis zum ersten Unterrichtszeitpunkt möglich.
* Die Laufzeit des Vertrags startet zum ersten Unterrichtstermin. * Die Laufzeit des Vertrags startet zum ersten Unterrichtstermin.
* Unterrichtszeiten werden in 15min (1/4 Stunden) blöcken gegeben und geplant. * Unterrichtszeiten werden in 15min (1/4 Stunden) Blöcken gegeben und geplant.
### Dozentenfunktionen ### Dozentenfunktionen
#### Wochenübersicht **/FD01/** #### Wochenübersicht **/FD01/**
* Der Nutzer sieht eine Übersicht mit von Ihm gegebenen Kursen in den kommenden 7 Tagen, gruppiert nach Wochentag * Der Nutzer sieht eine Übersicht mit von ihm gegebenen Kursen in den kommenden 7 Tagen, gruppiert nach Wochentag
* Mit einem Klick auf einen Kurs gelangt man zu den entsprechenden Kursdetails * Mit einem Klick auf einen Kurs gelangt man zu den entsprechenden Kursdetails
#### Kursdetails **/FD02/** #### Kursdetails **/FD02/**
@ -230,8 +244,8 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
* Ein Klick auf einen Dozenten führt zu [Schüler eines Dozenten](#sch%C3%BCler-eines-dozenten-fv05) * Ein Klick auf einen Dozenten führt zu [Schüler eines Dozenten](#sch%C3%BCler-eines-dozenten-fv05)
#### Schülerübersicht **/FV04/** #### Schülerübersicht **/FV04/**
* Es werden in Tabellenform alle Schüler mit Ihren Kursen angezeigt, ein Kurs pro Zeile * Es werden in Tabellenform alle Schüler mit ihren Kursen angezeigt; ein Kurs pro Zeile
* Ein Schüler kann also mehrere Zeilen umfassen * Ein Schüler kann also mehrere Zeilen umfassen.
* Die Tabelle kann spaltenweise sortiert und nach Schüler- und Kursname gefiltert werden. * Die Tabelle kann spaltenweise sortiert und nach Schüler- und Kursname gefiltert werden.
#### Schüler eines Dozenten **/FV05/** #### Schüler eines Dozenten **/FV05/**
@ -239,40 +253,40 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
#### Raumübersicht **/FV06/** #### Raumübersicht **/FV06/**
* Es werden alle Räume mit Grundlegenden Informationen angezeigt. * Es werden alle Räume mit Grundlegenden Informationen angezeigt.
* aktuelle Belegung * Aktuelle Belegung
* Instrumente * Instrumente
* Es wird ein Button zum erstellen von neuen Räumen angzeigt * Es wird ein Button zum erstellen von neuen Räumen angezeigt
#### Raumdetails **/FV07/** #### Raumdetails **/FV07/**
* Es werden alle Informationen zu einem Raum Angzeigt. * Es werden alle Informationen zu einem Raum Angzeigt.
* Name (bearbeitbar) * Name (bearbeitbar)
* aktuelle Belegung * Aktuelle Belegung
* Instrumente (bearbeitbar) * Instrumente (bearbeitbar)
* Nächste 5 Unterrichtseinheiten in diesem Raum * Nächste 5 Unterrichtseinheiten in diesem Raum
#### Finanzübersicht **/FV09/** #### Finanzübersicht **/FV09/**
* Es werden die gesamten monatlichen Einnahmen der Musikschule angzeigt. * Es werden die gesamten monatlichen Einnahmen der Musikschule angzeigt.
* Es werden die Zahlungen an die Dozenten, aufgeschlüsselt nacht Dozent angezeigt. * Es werden die Zahlungen an die Dozenten, aufgeschlüsselt nach Dozent angezeigt.
### Sonstige Funktionen ### Sonstige Funktionen
#### Login **/F01/** #### Login **/F01/**
* Der Nutzer kann sich mit Benutzername und Passwort anmelden. * Ein Nutzer kann sich mit Benutzername und Passwort anmelden.
* Benutzername und Passwort können von dem Administrativen Nutzer mithilfe von Direktzugriff auf das System angelegt werden * Benutzername und Passwort können von dem Administrativen Nutzer mithilfe von Direktzugriff auf das System angelegt werden.
#### Mitglied zu Kurs hinzufügen **/F02/** #### Mitglied zu Kurs hinzufügen **/F02/**
* Wenn ein Schüler einen Gruppenkurs erstellt hat, erhält dieser mit seiner Kursbestätigung einen Einladungslink, welcher auf eine "Antrag-Lite" Seite führt. * Wenn ein Schüler einen Gruppenkurs ("Band"-Kurs) erstellt hat, erhält dieser mit seiner Kursbestätigung einen Einladungslink, welcher auf eine "Antrag-Lite" Seite führt.
* Hier können sich weiter Mitglieder der Gruppe/Band in diesen Kurs eintragen. * Hier können sich weitere Mitglieder der Gruppe/Band in diesen Kurs eintragen.
* Dafür müssen diese nur Ihre Personenbezogenen Daten angeben, Sie werden in der über den Link identifizierten Kurs eingeschrieben. * Dafür müssen diese nur Ihre personenbezogenen Daten angeben; Sie werden in der über den Link identifizierten Kurs eingeschrieben.
* Dies muss vor dem ersten Unterrichtstermin geschehen. * Dies muss vor dem ersten Unterrichtstermin geschehen.
#### Antrag Stellen **/F03/** #### Antrag Stellen **/F03/**
* Der Nutzer gibt personenbezogene- und kursbezogenen Daten an, aus diesen wird beim Absenden ein Antrag in der Datenbank erstellt, welche von der Verwaltung mithilfe der Funktion [Offene Anträge](#offene-antr%C3%A4ge-fv01) eingesehen und weiter verarbeitet werden können. * Der Nutzer gibt personenbezogene- und kursbezogenen Daten an. Aus diesen wird beim Absenden ein Antrag in der Datenbank erstellt, welche von der Verwaltung mithilfe der Funktion [Offene Anträge](#offene-antr%C3%A4ge-fv01) eingesehen und weiter verarbeitet werden können.
* Personenbezogene Daten: * Personenbezogene Daten:
* Vorname * Vorname
* Nachname * Nachname
* Geb. Datum * Geburtsdatum
* Geb. Ort * Geburtsort
* PLZ * PLZ
* Ort * Ort
* Straße * Straße
@ -287,14 +301,16 @@ Die Zielgruppe besteht aus der Verwaltung und allen aktuellen und zukünftigen D
* Laufzeit * Laufzeit
* Unterrichtstyp * Unterrichtstyp
<div class="page"/>
## Benutzeroberfläche ## Benutzeroberfläche
> Was sind die grundlegenden Anforderungen an die Benutzeroberfläche (Bildschirmlayout, Dialogstruktur, ...)? > Was sind die grundlegenden Anforderungen an die Benutzeroberfläche (Bildschirmlayout, Dialogstruktur, ...)?
### Dialogstruktur ### Dialogstruktur
Im Folgenden wird die grobe Dialogstruktur einer fehlerfreien bzw. konfliktfreien Benutzung des Systems gezeigt wird. Im Folgenden wird die grobe Dialogstruktur einer fehlerfreien bzw. konfliktfreien Benutzung des Systems gezeigt.
Fehlereingaben haben eine akkumulierte Fehlermeldung zur Folge. Fehleingaben haben eine akkumulierte Fehlermeldung zur Folge.
#### Startseite #### Startseite
@ -314,13 +330,15 @@ Die Übersichtsseite Verwaltung ist die Startseite der Verwaltung, die die Verwa
### Bildschirmlayout ### Bildschirmlayout
Das Frontend wird mithilfe der JavaScript Bibliothek React erstellt, das Design wird mithilfe der MIT-lizensierten Designbibliothek Material-UI realisiert. Die Anwendung ist für Mobilegeräte optimiert und wird nach den Prinzipien des Responsiven Desings entwickelt. Das Frontend wird mithilfe der JavaScript Bibliothek React erstellt und das Design wird mithilfe der MIT-lizensierten Designbibliothek Material-UI realisiert. Die Anwendung ist für Mobilegeräte optimiert und wird nach den Prinzipien des responsiven Designs entwickelt.
> Ausnahme sind die Administrationsfunktionen > Ausnahme sind die Administrationsfunktionen
<div class="page"/>
## Testfälle ## Testfälle
1. Der Login funktioniert und erlaubt nur Zugriff auf authorisierte Bereiche / Ansichten. 1. Der Login funktioniert und erlaubt nur Zugriff auf autorisierte Bereiche und Ansichten.
2. Anonyme Nutzer können Anträge stellen, diese gehen in der Datenbank ein. 2. Anonyme Nutzer können Anträge stellen, diese gehen in der Datenbank ein.
3. Die Verwaltung kann Anträge verarbeiten und daraus Kurse erstellen. 3. Die Verwaltung kann Anträge verarbeiten und daraus Kurse erstellen.
* Der Antragsteller wird über die Verarbeitung informiert. * Der Antragsteller wird über die Verarbeitung informiert.

BIN
_Dokumente/Ausgearbeitete Dokumente/Pflichtenheft.pdf

Binary file not shown.

BIN
_Dokumente/Ausgearbeitete Dokumente/Zeitplan.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 535 KiB

2
_Dokumente/Protokolle/2019-05-15_Protokoll.md

@ -41,4 +41,4 @@ _Ort: Schule_
|-|-|-| |-|-|-|
|Papierprototyp erstellen und im nächsten Metting weiter besprechen|Kai, Levin|X| |Papierprototyp erstellen und im nächsten Metting weiter besprechen|Kai, Levin|X|
|Erstellung ER-Diagram und im nächsten Meeting weiter besprechen|Alexej, Tobias|X| |Erstellung ER-Diagram und im nächsten Meeting weiter besprechen|Alexej, Tobias|X|
|Erstellung Pflichtenheft und Definition der Endpoints nach Besprechung von Papierprototyp und ER-Diagram|Alle|| |Erstellung Pflichtenheft und Definition der Endpoints nach Besprechung von Papierprototyp und ER-Diagram|Alle|X|

3
_Dokumente/Protokolle/2019-05-22_Protokoll.md

@ -15,5 +15,4 @@ _Ort: Schule_
* Laufzettel: Abnahme von Kommunikationsplan und Papierprototyp * Laufzettel: Abnahme von Kommunikationsplan und Papierprototyp
## Resultierende Aufgaben ## Resultierende Aufgaben
|Aufgabe|Verantwortlicher|Erledigt| Keine
|-|-|-|

6
_Dokumente/Protokolle/2019-05-29_Protokoll.md

@ -16,6 +16,6 @@ _Ort: Schule_
## Resultierende Aufgaben ## Resultierende Aufgaben
|Aufgabe|Verantwortlicher|Erledigt| |Aufgabe|Verantwortlicher|Erledigt|
|-|-|-| |-|-|-|
|Erstellung Pflichtenheft|Kai, Levin|| |Erstellung Pflichtenheft|Kai, Levin|X|
|Erstellung Projektstrukturplan inkl. Zeitplan|Alexej, Tobi| |Erstellung Projektstrukturplan inkl. Zeitplan|Alexej, Tobi|X|
|Erstellung div. Diagramme|Alexej, Tobi| |Erstellung div. Diagramme|Alexej, Tobi|X|

2
_Dokumente/Protokolle/2019-06-05_Protokoll.md

@ -20,5 +20,5 @@ _Ort: Schule_
## Resultierende Aufgaben ## Resultierende Aufgaben
|Aufgabe|Verantwortlicher|Erledigt| |Aufgabe|Verantwortlicher|Erledigt|
|-|-|-| |-|-|-|
|Erstellung Datenbankschema|Tobi|| |Erstellung Datenbankschema|Tobi|X|
|Vorbereitung Präsensation (Basislayout und Inhaltsgliederung)|Kai|| |Vorbereitung Präsensation (Basislayout und Inhaltsgliederung)|Kai||

8
_Dokumente/Protokolle/2019-06-12_Protokoll.md

@ -13,14 +13,16 @@ _Ort: Schule_
## Ergebnisse ## Ergebnisse
* Pflichtenheft ist abgegeben * Pflichtenheft ist abgegeben
* Pflichenheft initial vollständig * PSP vervollständigt und abgenommen
* PSP vervollständigt
* Prototyp (enthaltene Funktionen) * Prototyp (enthaltene Funktionen)
* Login * Login
* Antragsgformular * Antragsgformular
* Wochenübersicht für Dozenten (Dozenten) * Wochenübersicht für Dozenten (Dozenten)
* Kurse erstellen/bestätigen (Verwaltung) * Kurse erstellen/bestätigen (Verwaltung)
* Endpoints kontrolliert
* Use-Case-Diagramm abgegeben
## Resultierende Aufgaben ## Resultierende Aufgaben
|Aufgabe|Verantwortlicher|Erledigt| |Aufgabe|Verantwortlicher|Erledigt|
|Pflichtenheft|Levin|Ja| |Pflichtenheft|Levin|Ja|
|Zeitplan|Alexej|X|

17
_Dokumente/Protokolle/2019-06-19_Protokoll.md

@ -0,0 +1,17 @@
# 2019-06-19 Protokoll
_Teilnehmer: Levin Faber, Alexej Komnik, Tobias Schiffarth, Kai Senkowski_
_Ort: Schule_
## Agenda
* Prototyp vorantreiben
* Zeitplan
* Präsentation
## Ergebnisse
* Abschließende Vorgangsliste für Zeitplan
* Weitere Implementation Prototyp (Authentifizierung)
## Resultierende Aufgaben
Keine
Loading…
Cancel
Save