Bulk-Commit: Darft: Anmeldetool.

Interface Definition: done
Server-Side-Implementation: partly done (CR missing, potential Refactor, ...)
Client-Side-Implementation: started: (UI: done, Service: started, but works with SSR)
Missing: Permissions / Roles to restrict access to an event.
Missing: Fields on Event.
Missing: Good Styling
Time-Took: about 12 Hours.
Learning: Commit in smaller packets, rest will be discussed at CR
This commit is contained in:
Konstantin Hintermayer 2025-05-14 20:40:10 +02:00
parent e45fce2e65
commit 38c5bef225
17 changed files with 508 additions and 92 deletions

View File

@ -8,22 +8,38 @@
@inject NavigationManager NavigationManager
@inject IStringLocalizer<Edit> Localizer
<div class="container">
<div class="row mb-1 align-items-center">
<Label Class="col-sm-3" For="name" HelpText="Enter a name" ResourceKey="Name">Name: </Label>
<div class="col-sm-9">
<input id="name" class="form-control" @bind="@_name" required />
</div>
<h3>Anmeldung zum Event</h3>
<p>Willst du am Event (@_name) teilnehmen?</p>
@if (PageState.User != null) {
@if (Status != null)
{
<p class="mt-3"><strong>Status:</strong>
@if (Status == true)
{
@Localizer["Zusage"]
<button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button>
} else
{
@Localizer["Absage"]
<button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button>
}
</p>
} else {
<div class="buttons">
<button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button>
<button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button>
</div>
</div>
<button type="button" class="btn btn-success" @onclick="Save">@Localizer["Save"]</button>
<NavLink class="btn btn-secondary" href="@NavigateUrl()">@Localizer["Cancel"]</NavLink>
<br /><br />
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
}
} else
{
<p class="mt-3">Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.</p> <Login />
}
@code {
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.Edit;
public override SecurityAccessLevel SecurityAccessLevel => SecurityAccessLevel.View;
public override string Actions => "Details";
@ -44,19 +60,59 @@
private string _modifiedby;
private DateTime _modifiedon;
private Response _response;
private bool? Status;
private async Task SendResponse(bool response)
{
if(_response == null)
{
_response = new Response();
_response.EventRegistrationId = _id;
_response.OwnerId = PageState.User.UserId;
_response.ModuleId = ModuleState.ModuleId;
_response.ResponseType = response;
_response = await EventRegistrationService.AddResponseAsync(_response);
} else
{
_response.ResponseType = response;
_response = await EventRegistrationService.UpdateResponseAsync(_response);
}
if(_response != null) Status = _response.ResponseType;
}
private async void Zusage()
{
await SendResponse(true);
}
private async void Absage()
{
await SendResponse(false);
}
protected override async Task OnInitializedAsync()
{
try
{
_id = Int32.Parse(PageState.QueryString["id"]);
Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId);
if (EventRegistration != null)
Event currentEvent;
Response rsvp;
(currentEvent, rsvp) = await EventRegistrationService.GetEventDetails(_id, ModuleState.ModuleId);
if (currentEvent != null)
{
_name = EventRegistration.Name;
_createdby = EventRegistration.CreatedBy;
_createdon = EventRegistration.CreatedOn;
_modifiedby = EventRegistration.ModifiedBy;
_modifiedon = EventRegistration.ModifiedOn;
_name = currentEvent.Name;
_createdby = currentEvent.CreatedBy;
_createdon = currentEvent.CreatedOn;
_modifiedby = currentEvent.ModifiedBy;
_modifiedon = currentEvent.ModifiedOn;
}
if(rsvp != null)
{
_response = rsvp;
Status = rsvp.ResponseType;
}
}
catch (Exception ex)
@ -79,14 +135,14 @@
Event EventRegistration = new Event();
EventRegistration.ModuleId = ModuleState.ModuleId;
EventRegistration.Name = _name;
EventRegistration = await EventRegistrationService.AddEventRegistrationAsync(EventRegistration);
EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration);
}
else
{
Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId);
Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId);
EventRegistration.Name = _name;
await EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration);
await EventRegistrationService.UpdateEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration);
}
NavigationManager.NavigateTo(NavigateUrl());

View File

@ -55,7 +55,7 @@
if (PageState.Action == "Edit")
{
_id = Int32.Parse(PageState.QueryString["id"]);
Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId);
Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId);
if (EventRegistration != null)
{
_name = EventRegistration.Name;
@ -86,14 +86,14 @@
Event EventRegistration = new Event();
EventRegistration.ModuleId = ModuleState.ModuleId;
EventRegistration.Name = _name;
EventRegistration = await EventRegistrationService.AddEventRegistrationAsync(EventRegistration);
EventRegistration = await EventRegistrationService.AddEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Added {EventRegistration}", EventRegistration);
}
else
{
Event EventRegistration = await EventRegistrationService.GetEventRegistrationAsync(_id, ModuleState.ModuleId);
Event EventRegistration = await EventRegistrationService.GetEventAsync(_id, ModuleState.ModuleId);
EventRegistration.Name = _name;
await EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration);
await EventRegistrationService.UpdateEventAsync(EventRegistration);
await logger.LogInformation("EventRegistration Updated {EventRegistration}", EventRegistration);
}
NavigationManager.NavigateTo(NavigateUrl());

View File

@ -27,13 +27,11 @@ else
<th style="width: 1px;">&nbsp;</th>
</Header>
<Row>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.EventRegistrationId.ToString())" ResourceKey="Edit" /></td>
<td><ActionDialog Header="Delete EventRegistration" Message="Are You Sure You Wish To Delete This EventRegistration?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" Id="@context.EventRegistrationId.ToString()" /></td>
<td><ActionLink Action="Edit" Parameters="@($"id=" + context.EventId.ToString())" ResourceKey="Edit" /></td>
<td><ActionDialog Header="Delete EventRegistration" Message="Are You Sure You Wish To Delete This EventRegistration?" Action="Delete" Security="SecurityAccessLevel.Edit" Class="btn btn-danger" OnClick="@(async () => await Delete(context))" ResourceKey="Delete" Id="@context.EventId.ToString()" /></td>
<td>@context.Name</td>
@* @if(UserSecurity.IsAuthorized(PageState.User, PermissionNames.Utilize)) { *@
<td><ActionLink Action="Details" Parameters="@($"id=" + context.EventRegistrationId.ToString())" ResourceKey="Details"/></td>
@* } *@
<td><ActionLink Action="Details" Parameters="@($"id=" + context.EventId.ToString())" ResourceKey="Details"/></td>
</Row>
</Pager>
}
@ -58,7 +56,7 @@ else
{
try
{
_EventRegistrations = await EventRegistrationService.GetEventRegistrationsAsync(ModuleState.ModuleId);
_EventRegistrations = await EventRegistrationService.GetEventsAsync(ModuleState.ModuleId);
}
catch (Exception ex)
{
@ -71,9 +69,9 @@ else
{
try
{
await EventRegistrationService.DeleteEventRegistrationAsync(EventRegistration.EventRegistrationId, ModuleState.ModuleId);
await EventRegistrationService.DeleteEventAsync(EventRegistration.EventId, ModuleState.ModuleId);
await logger.LogInformation("EventRegistration Deleted {EventRegistration}", EventRegistration);
_EventRegistrations = await EventRegistrationService.GetEventRegistrationsAsync(ModuleState.ModuleId);
_EventRegistrations = await EventRegistrationService.GetEventsAsync(ModuleState.ModuleId);
StateHasChanged();
}
catch (Exception ex)

View File

@ -0,0 +1,132 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="Absage" xml:space="preserve">
<value>Du hast abgesagt. Schade, vielleicht nächstes Mal!</value>
</data>
<data name="Absagen" xml:space="preserve">
<value>Absagen</value>
</data>
<data name="Zusage" xml:space="preserve">
<value>Du hast zugesagt. Wir freuen uns auf dich!</value>
</data>
<data name="Zusagen" xml:space="preserve">
<value>Zusagen</value>
</data>
</root>

View File

@ -2,8 +2,10 @@ using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Oqtane.Services;
using Oqtane.Shared;
using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
@ -13,7 +15,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
private string Apiurl => CreateApiUrl("EventRegistration");
public async Task<List<Models.Event>> GetEventRegistrationsAsync(int ModuleId)
/*public async Task<List<Models.Event>> GetEventRegistrationsAsync(int ModuleId)
{
List<Models.Event> EventRegistrations = await GetJsonAsync<List<Models.Event>>(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Models.Event>().ToList());
return EventRegistrations.OrderBy(item => item.Name).ToList();
@ -32,11 +34,51 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
public async Task<Models.Event> UpdateEventRegistrationAsync(Models.Event EventRegistration)
{
return await PutJsonAsync<Models.Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistration.EventRegistrationId}", EntityNames.Module, EventRegistration.ModuleId), EventRegistration);
}*/
public async Task<List<Event>> GetEventsAsync(int ModuleId)
{
List<Event> EventRegistrations = await GetJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}?moduleid={ModuleId}", EntityNames.Module, ModuleId), Enumerable.Empty<Event>().ToList());
return EventRegistrations.OrderBy(item => item.Name).ToList();
}
public async Task<Event> GetEventAsync(int EventId, int ModuleId)
{
return await GetJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
}
public async Task DeleteEventRegistrationAsync(int EventRegistrationId, int ModuleId)
public async Task<Event> AddEventAsync(Event NewEvent)
{
await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventRegistrationId}/{ModuleId}", EntityNames.Module, ModuleId));
return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent);
}
public async Task<Event> UpdateEventAsync(Event NewEvent)
{
return await PutJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{NewEvent.EventId}", EntityNames.Module, NewEvent.ModuleId), NewEvent);
}
public async Task DeleteEventAsync(int EventId, int ModuleId)
{
await DeleteAsync(CreateAuthorizationPolicyUrl($"{Apiurl}/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
}
public async Task<Response> AddResponseAsync(Response response)
{
return await PostJsonAsync<Response>(CreateAuthorizationPolicyUrl($"{Apiurl}/response/{response.EventRegistrationId}/{response.ModuleId}", EntityNames.Module, response.ModuleId), response);
}
public async Task<Response> UpdateResponseAsync(Response response)
{
return await PutJsonAsync<Response>(CreateAuthorizationPolicyUrl($"{Apiurl}/response/{response.EventRegistrationId}/{response.ModuleId}", EntityNames.Module, response.ModuleId), response);
}
public async Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId)
{
return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
}
public Task<List<Response>> GetEventResponses(int EventId, int ModuleId)
{
throw new System.NotImplementedException();
}
}
}

View File

@ -30,7 +30,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
int ModuleId;
if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId))
{
return await _EventRegistrationService.GetEventRegistrationsAsync(ModuleId);
return await _EventRegistrationService.GetEventsAsync(ModuleId);
}
else
{
@ -45,7 +45,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<Models.Event> Get(int id, int moduleid)
{
Models.Event EventRegistration = await _EventRegistrationService.GetEventRegistrationAsync(id, moduleid);
Models.Event EventRegistration = await _EventRegistrationService.GetEventAsync(id, moduleid);
if (EventRegistration != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
{
return EventRegistration;
@ -65,7 +65,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
{
if (ModelState.IsValid && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
{
EventRegistration = await _EventRegistrationService.AddEventRegistrationAsync(EventRegistration);
EventRegistration = await _EventRegistrationService.AddEventAsync(EventRegistration);
}
else
{
@ -81,9 +81,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
[Authorize(Policy = PolicyNames.EditModule)]
public async Task<Models.Event> Put(int id, [FromBody] Models.Event EventRegistration)
{
if (ModelState.IsValid && EventRegistration.EventRegistrationId == id && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
if (ModelState.IsValid && EventRegistration.EventId == id && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
{
EventRegistration = await _EventRegistrationService.UpdateEventRegistrationAsync(EventRegistration);
EventRegistration = await _EventRegistrationService.UpdateEventAsync(EventRegistration);
}
else
{
@ -99,10 +99,10 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
[Authorize(Policy = PolicyNames.EditModule)]
public async Task Delete(int id, int moduleid)
{
Models.Event EventRegistration = await _EventRegistrationService.GetEventRegistrationAsync(id, moduleid);
Models.Event EventRegistration = await _EventRegistrationService.GetEventAsync(id, moduleid);
if (EventRegistration != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
{
await _EventRegistrationService.DeleteEventRegistrationAsync(id, EventRegistration.ModuleId);
await _EventRegistrationService.DeleteEventAsync(id, EventRegistration.ModuleId);
}
else
{
@ -110,5 +110,27 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
}
}
// GET api/<controller>/5
[HttpGet("details/{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<(Models.Event, Models.Response)> GetDetails(int id, int moduleid)
{
Models.Event EventRegistration;
Models.Response EventResponse;
(EventRegistration, EventResponse) = await _EventRegistrationService.GetEventDetails(id, moduleid);
if (EventRegistration != null && EventResponse != null && IsAuthorizedEntityId(EntityNames.Module, EventRegistration.ModuleId))
{
return (EventRegistration, EventResponse);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {EventRegistrationId} {ModuleId}", id, moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return (null, null);
}
}
// TODO: Add Event Response Endpoints.
}
}

View File

@ -15,12 +15,14 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
{
public class EventRegistrationManager : MigratableModuleBase, IInstallable, IPortable, ISearchable
{
private readonly IEventRepository _EventRegistrationRepository;
private readonly IEventRepository _EventRepository;
private readonly IResponseRepository _ResponseRepository;
private readonly IDBContextDependencies _DBContextDependencies;
public EventRegistrationManager(IEventRepository EventRegistrationRepository, IDBContextDependencies DBContextDependencies)
public EventRegistrationManager(IEventRepository EventRegistrationRepository, IResponseRepository ResponseRepository, IDBContextDependencies DBContextDependencies)
{
_EventRegistrationRepository = EventRegistrationRepository;
_EventRepository = EventRegistrationRepository;
_ResponseRepository = ResponseRepository;
_DBContextDependencies = DBContextDependencies;
}
@ -36,8 +38,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
public string ExportModule(Oqtane.Models.Module module)
{
// TODO: Export event Responses as well.
string content = "";
List<Models.Event> EventRegistrations = _EventRegistrationRepository.GetEvents(module.ModuleId).ToList();
List<Models.Event> EventRegistrations = _EventRepository.GetEvents(module.ModuleId).ToList();
if (EventRegistrations != null)
{
content = JsonSerializer.Serialize(EventRegistrations);
@ -47,6 +50,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
public void ImportModule(Oqtane.Models.Module module, string content, string version)
{
// TODO: Import event Responses as well.
List<Models.Event> EventRegistrations = null;
if (!string.IsNullOrEmpty(content))
{
@ -56,7 +60,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
{
foreach(var EventRegistration in EventRegistrations)
{
_EventRegistrationRepository.AddEvent(new Models.Event { ModuleId = module.ModuleId, Name = EventRegistration.Name });
_EventRepository.AddEvent(new Models.Event { ModuleId = module.ModuleId, Name = EventRegistration.Name });
}
}
}
@ -65,14 +69,14 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Manager
{
var searchContentList = new List<SearchContent>();
foreach (var EventRegistration in _EventRegistrationRepository.GetEvents(pageModule.ModuleId))
foreach (var EventRegistration in _EventRepository.GetEvents(pageModule.ModuleId))
{
if (EventRegistration.ModifiedOn >= lastIndexedOn)
{
searchContentList.Add(new SearchContent
{
EntityName = "SZUAbsolventenvereinEventRegistration",
EntityId = EventRegistration.EventRegistrationId.ToString(),
EntityId = EventRegistration.EventId.ToString(),
Title = EventRegistration.Name,
Body = EventRegistration.Name,
ContentModifiedBy = EventRegistration.ModifiedBy,

View File

@ -17,7 +17,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations
protected override void Up(MigrationBuilder migrationBuilder)
{
var entityBuilder = new EventRegistrationEntityBuilder(migrationBuilder, ActiveDatabase);
var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase);
entityBuilder.Create();
var entityBuilder2 = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase);
@ -26,7 +26,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations
protected override void Down(MigrationBuilder migrationBuilder)
{
var entityBuilder = new EventRegistrationEntityBuilder(migrationBuilder, ActiveDatabase);
var entityBuilder = new EventEntityBuilder(migrationBuilder, ActiveDatabase);
entityBuilder.Drop();
var entityBuilder2 = new EventResponseEntityBuilder(migrationBuilder, ActiveDatabase);
entityBuilder2.Drop();

View File

@ -7,29 +7,29 @@ using Oqtane.Migrations.EntityBuilders;
namespace SZUAbsolventenverein.Module.EventRegistration.Migrations.EntityBuilders
{
public class EventRegistrationEntityBuilder : AuditableBaseEntityBuilder<EventRegistrationEntityBuilder>
public class EventEntityBuilder : AuditableBaseEntityBuilder<EventEntityBuilder>
{
private const string _entityTableName = "SZUAbsolventenvereinEvent";
private readonly PrimaryKey<EventRegistrationEntityBuilder> _primaryKey = new("PK_SZUAbsolventenvereinEvent", x => x.EventRegistrationId);
private readonly ForeignKey<EventRegistrationEntityBuilder> _moduleForeignKey = new("FK_SZUAbsolventenvereinEvent_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade);
private readonly PrimaryKey<EventEntityBuilder> _primaryKey = new("PK_SZUAbsolventenvereinEvent", x => x.EventId);
private readonly ForeignKey<EventEntityBuilder> _moduleForeignKey = new("FK_SZUAbsolventenvereinEvent_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade);
public EventRegistrationEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
public EventEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)
{
EntityTableName = _entityTableName;
PrimaryKey = _primaryKey;
ForeignKeys.Add(_moduleForeignKey);
}
protected override EventRegistrationEntityBuilder BuildTable(ColumnsBuilder table)
protected override EventEntityBuilder BuildTable(ColumnsBuilder table)
{
EventRegistrationId = AddAutoIncrementColumn(table,"EventRegistrationId");
EventId = AddAutoIncrementColumn(table,"EventId");
ModuleId = AddIntegerColumn(table,"ModuleId");
Name = AddMaxStringColumn(table,"Name");
AddAuditableColumns(table);
return this;
}
public OperationBuilder<AddColumnOperation> EventRegistrationId { get; set; }
public OperationBuilder<AddColumnOperation> EventId { get; set; }
public OperationBuilder<AddColumnOperation> ModuleId { get; set; }
public OperationBuilder<AddColumnOperation> Name { get; set; }
}

View File

@ -13,7 +13,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Migrations.EntityBuilder
private const string _entityTableName = "SZUAbsolventenvereinEventResponse";
private readonly PrimaryKey<EventResponseEntityBuilder> _primaryKey = new("PK_SZUAbsolventenvereinEventResponse", x => x.EventResponseId);
private readonly ForeignKey<EventResponseEntityBuilder> _moduleForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Module", x => x.ModuleId, "Module", "ModuleId", ReferentialAction.Cascade);
private readonly ForeignKey<EventResponseEntityBuilder> _eventForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Event", x => x.EventRegistrationId, "SZUAbsolventenvereinEvent", "EventRegistrationId", ReferentialAction.Cascade);
private readonly ForeignKey<EventResponseEntityBuilder> _eventForeignKey = new("FK_SZUAbsolventenvereinEventResponse_Event", x => x.EventRegistrationId, "SZUAbsolventenvereinEvent", "EventId", ReferentialAction.Cascade);
private readonly ForeignKey<EventResponseEntityBuilder> _ownerForeignKey = new("FK_SZUAbsolventenvereinEventResponse_User_Owner", x => x.OwnerId, "User", "UserId", ReferentialAction.Cascade);
public EventResponseEntityBuilder(MigrationBuilder migrationBuilder, IDatabase database) : base(migrationBuilder, database)

View File

@ -34,7 +34,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Repository
}
else
{
return db.Event.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventRegistrationId);
return db.Event.AsNoTracking().FirstOrDefault(item => item.EventId == EventRegistrationId);
}
}

View File

@ -1,15 +1,19 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Repository
{
public interface IResponseRepository
{
IEnumerable<Models.Response> GetResponses(int ModuleId);
Models.Response GetResponse(int EventRegistrationId);
Models.Response GetResponse(int EventRegistrationId, bool tracking);
Models.Response AddResponse(Models.Event EventRegistration);
Models.Response UpdateResponse(Models.Event EventRegistration);
void DeleteResponse(int EventRegistrationId);
IEnumerable<Response> GetResponses(int ModuleId);
IEnumerable<Response> GetResponses(int EventId, int ModuleId);
Response GetResponse(int EventRegistrationId);
Response GetResponse(int EventRegistrationId, bool tracking);
Response GetResponse(int EventId, int OwnerId);
Response GetResponse(int EventId, int OwnerId, bool tracking);
Response AddResponse(Response EventResponse);
Response UpdateResponse(Response EventResponse);
void DeleteResponse(int EventResponseId);
}
}

View File

@ -0,0 +1,89 @@
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using Oqtane.Modules;
using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Repository
{
public class ResponseRepository : IResponseRepository, ITransientService
{
private readonly IDbContextFactory<EventRegistrationContext> _factory;
public ResponseRepository(IDbContextFactory<EventRegistrationContext> factory)
{
_factory = factory;
}
public IEnumerable<Response> GetResponses(int ModuleId)
{
using var db = _factory.CreateDbContext();
return db.Response.Where(item => item.ModuleId == ModuleId).ToList();
}
public IEnumerable<Response> GetResponses(int EventId, int ModuleId)
{
using var db = _factory.CreateDbContext();
return db.Response.Where(item => item.ModuleId == ModuleId && item.EventRegistrationId == EventId).ToList();
}
public Response GetResponse(int EventRegistrationId)
{
return GetResponse(EventRegistrationId, true);
}
public Response GetResponse(int EventRegistrationId, bool tracking)
{
using var db = _factory.CreateDbContext();
if (tracking)
{
return db.Response.Find(EventRegistrationId);
}
else
{
return db.Response.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventRegistrationId);
}
}
public Response GetResponse(int EventId, int OwnerId)
{
return GetResponse(EventId, OwnerId, true);
}
public Response GetResponse(int EventId, int OwnerId, bool tracking)
{
using var db = _factory.CreateDbContext();
if (tracking)
{
return db.Response.FirstOrDefault(item => item.EventRegistrationId == EventId && item.OwnerId == OwnerId);
}
else
{
return db.Response.AsNoTracking().FirstOrDefault(item => item.EventRegistrationId == EventId && item.OwnerId == OwnerId);
}
}
public Response AddResponse(Response EventResponse)
{
using var db = _factory.CreateDbContext();
db.Response.Add(EventResponse);
db.SaveChanges();
return EventResponse;
}
public Response UpdateResponse(Response EventResponse)
{
using var db = _factory.CreateDbContext();
db.Entry(EventResponse).State = EntityState.Modified;
db.SaveChanges();
return EventResponse;
}
public void DeleteResponse(int EventRegistrationId)
{
using var db = _factory.CreateDbContext();
Response EventResponse = db.Response.Find(EventRegistrationId);
db.Response.Remove(EventResponse);
db.SaveChanges();
}
}
}

View File

@ -3,6 +3,7 @@ using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Oqtane.Enums;
using Oqtane.Extensions;
using Oqtane.Infrastructure;
using Oqtane.Models;
using Oqtane.Security;
@ -14,15 +15,17 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
public class ServerEventRegistrationService : IEventRegistrationService
{
private readonly IEventRepository _EventRegistrationRepository;
private readonly IEventRepository _EventRepository;
private readonly IResponseRepository _ResponseRepository;
private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger;
private readonly IHttpContextAccessor _accessor;
private readonly Alias _alias;
public ServerEventRegistrationService(IEventRepository EventRegistrationRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
{
_EventRegistrationRepository = EventRegistrationRepository;
_EventRepository = EventRepository;
_ResponseRepository = ResponseRepository;
_userPermissions = userPermissions;
_logger = logger;
_accessor = accessor;
@ -33,7 +36,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, NewEvent.ModuleId, PermissionNames.Edit))
{
NewEvent = _EventRegistrationRepository.AddEvent(NewEvent);
NewEvent = _EventRepository.AddEvent(NewEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", NewEvent);
}
else
@ -44,32 +47,90 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
return Task.FromResult(NewEvent);
}
public Task<Response> AddOrUpdateResponseAsync(int EventId, int ModuleId, bool ResponseType)
public Task<Response> AddResponseAsync(Response Response)
{
throw new System.NotImplementedException();
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View))
{
Response = _ResponseRepository.AddResponse(Response);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {NewEvent}", Response);
Response = null;
}
return Task.FromResult(Response);
}
public Task<Response> UpdateResponseAsync(Response Response)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, Response.ModuleId, PermissionNames.View))
{
Response = _ResponseRepository.UpdateResponse(Response);
_logger.Log(LogLevel.Information, this, LogFunction.Create, "EventRegistration Added {NewEvent}", Response);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Add Attempt {NewEvent}", Response);
Response = null;
}
return Task.FromResult(Response);
}
public Task DeleteEventAsync(int EventId, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit))
{
_EventRegistrationRepository.DeleteEvent(EventId);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "EventRegistration Deleted {EventId}", EventId);
_EventRepository.DeleteEvent(EventId);
_logger.Log(LogLevel.Information, this, LogFunction.Delete, "Event Deleted {EventId}", EventId);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Delete Attempt {EventId} {ModuleId}", EventId, ModuleId);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Delete Attempt {EventId} {ModuleId}", EventId, ModuleId);
}
return Task.CompletedTask;
}
public Task<Event> GetEventAsync(int EventId, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_EventRepository.GetEvent(EventId, true));
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Get Attempt {ModuleId}", ModuleId);
return null;
}
}
public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId)
{
throw new System.NotImplementedException();
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
Event currentEvent = _EventRepository.GetEvent(EventId);
Response rsvp = _ResponseRepository.GetResponse(EventId, _accessor.HttpContext.User.UserId());
return Task.FromResult((currentEvent, rsvp));
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Get Attempt {ModuleId}", ModuleId);
return null;
}
}
public Task<List<Response>> GetEventResponses(int EventId, int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.Edit))
{
return Task.FromResult(_ResponseRepository.GetResponses(EventId, ModuleId).ToList());
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Response Get Attempt {ModuleId}", ModuleId);
return null;
}
throw new System.NotImplementedException();
}
@ -77,11 +138,11 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_EventRegistrationRepository.GetEvents(ModuleId).ToList());
return Task.FromResult(_EventRepository.GetEvents(ModuleId).ToList());
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {ModuleId}", ModuleId);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Events Get Attempt {ModuleId}", ModuleId);
return null;
}
}
@ -90,17 +151,19 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, NewEvent.ModuleId, PermissionNames.Edit))
{
NewEvent = _EventRegistrationRepository.UpdateEvent(NewEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "EventRegistration Updated {NewEvent}", NewEvent);
NewEvent = _EventRepository.UpdateEvent(NewEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Event Updated {NewEvent}", NewEvent);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Update Attempt {NewEvent}", NewEvent);
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Update Attempt {NewEvent}", NewEvent);
NewEvent = null;
}
return Task.FromResult(NewEvent);
}
// TODO: Implement the methods for EventResponses
/*
public Task<Models.Event> GetEventRegistrationAsync(int EventRegistrationId, int ModuleId)
@ -147,5 +210,8 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
}
}*/
}
}

View File

@ -1,26 +1,30 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Services
{
public interface IEventRegistrationService
{
/* Reine Events */
Task<List<Models.Event>> GetEventsAsync(int ModuleId);
Task<List<Event>> GetEventsAsync(int ModuleId);
Task<Event> GetEventAsync(int EventId, int ModuleId);
Task<Models.Event> AddEventAsync(Models.Event NewEvent);
Task<Event> AddEventAsync(Event NewEvent);
Task<Models.Event> UpdateEventAsync(Models.Event NewEvent);
Task<Event> UpdateEventAsync(Event NewEvent);
Task DeleteEventAsync(int EventId, int ModuleId);
/* Events & Responses */
Task<Models.Response> AddOrUpdateResponseAsync(int EventId, int ModuleId, bool ResponseType);
Task<Response> AddResponseAsync(Response Response);
Task<Response> UpdateResponseAsync(Response Response);
Task<(Models.Event, Models.Response)> GetEventDetails(int EventId, int ModuleId);
Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId);
Task<List<Models.Response>> GetEventResponses(int EventId, int ModuleId);
Task<List<Response>> GetEventResponses(int EventId, int ModuleId);
}
}

View File

@ -9,7 +9,7 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Models
public class Event : IAuditable
{
[Key]
public int EventRegistrationId { get; set; }
public int EventId { get; set; }
public int ModuleId { get; set; }
public string Name { get; set; }

View File

@ -14,7 +14,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Models
public int OwnerId { get; set; }
public int EventRegistrationId { get; set; }
public int ModuleId { get; set; }
public string Name { get; set; }
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }