Customizable FS network url

This commit is contained in:
Andre Beging
2022-05-31 12:25:11 +02:00
parent bba0a377b5
commit cd22c2f215
10 changed files with 388 additions and 24 deletions

View File

@@ -1,3 +1,5 @@
using FoodsharingSiegen.Contracts.Model;
namespace FoodsharingSiegen.Contracts.Entity namespace FoodsharingSiegen.Contracts.Entity
{ {
/// <summary> /// <summary>
@@ -118,6 +120,42 @@ namespace FoodsharingSiegen.Contracts.Entity
Ambassador = 400 Ambassador = 400
} }
/// <summary>
/// The fs network type enum
/// </summary>
public enum FsNetworkType
{
/// <summary>
/// The germany fs network type
/// </summary>
[CustomValue("https://foodsharing.de")]
Germany = 0,
/// <summary>
/// The germany beta fs network type
/// </summary>
[CustomValue("https://beta.foodsharing.de")]
GermanyBeta = 10,
/// <summary>
/// The austria fs network type
/// </summary>
[CustomValue("https://foodsharing.at")]
Austria = 20,
/// <summary>
/// The austria beta fs network type
/// </summary>
[CustomValue("https://beta.foodsharing.at")]
AustriaBeta = 30,
/// <summary>
/// The switzerland fs network type
/// </summary>
[CustomValue("https://foodsharing.network")]
Switzerland = 40
}
/// <summary> /// <summary>
/// The interaction type enum /// The interaction type enum
/// </summary> /// </summary>

View File

@@ -4,36 +4,35 @@ using FoodsharingSiegen.Contracts.Helper;
namespace FoodsharingSiegen.Contracts.Entity namespace FoodsharingSiegen.Contracts.Entity
{ {
/// <summary> /// <summary>
/// The user class (a. beging, 06.04.2022) /// The user class (a. beging, 06.04.2022)
/// </summary> /// </summary>
public class User public class User
{ {
#region Public Properties #region Public Properties
/// <summary> /// <summary>
/// Gets or sets the value of the created (ab) /// Gets or sets the value of the created (ab)
/// </summary> /// </summary>
public DateTime Created { get; set; } public DateTime Created { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the encrypted password (ab) /// Gets or sets the value of the encrypted password (ab)
/// </summary> /// </summary>
public string EncryptedPassword { get; set; } public string EncryptedPassword { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the force logout (ab) /// Gets or sets the value of the force logout (ab)
/// </summary> /// </summary>
public bool ForceLogout { get; set; } public bool ForceLogout { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the groups (ab) /// Gets or sets the value of the groups (ab)
/// </summary> /// </summary>
public string Groups { get; set; } public string Groups { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the groups list (ab) /// Gets or sets the value of the groups list (ab)
/// </summary> /// </summary>
[NotMapped] [NotMapped]
public List<UserGroup> GroupsList public List<UserGroup> GroupsList
@@ -49,32 +48,44 @@ namespace FoodsharingSiegen.Contracts.Entity
} }
/// <summary> /// <summary>
/// Gets or sets the value of the id (ab) /// Gets or sets the value of the id (ab)
/// </summary> /// </summary>
[Key] public Guid Id { get; set; } [Key]
public Guid Id { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the interactions (ab) /// Gets or sets the value of the interactions (ab)
/// </summary> /// </summary>
public IList<Interaction> Interactions { get; set; } public IList<Interaction> Interactions { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the mail (ab) /// Gets or sets the value of the mail (ab)
/// </summary> /// </summary>
public string Mail { get; set; } public string Mail { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the memo (ab) /// Gets or sets the value of the memo (ab)
/// </summary> /// </summary>
public string? Memo { get; set; } public string? Memo { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the name (ab) /// Gets or sets the value of the name (ab)
/// </summary> /// </summary>
public string Name { get; set; } public string Name { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the password (ab) /// Gets or sets the value of the network (ab)
/// </summary>
public FsNetworkType Network { get; set; }
/// <summary>
/// Gets the value of the network link (ab)
/// </summary>
[NotMapped]
public string NetworkLink => Network.GetCustomValue();
/// <summary>
/// Gets or sets the value of the password (ab)
/// </summary> /// </summary>
[NotMapped] [NotMapped]
public string Password public string Password
@@ -84,12 +95,12 @@ namespace FoodsharingSiegen.Contracts.Entity
} }
/// <summary> /// <summary>
/// Gets or sets the value of the type (ab) /// Gets or sets the value of the type (ab)
/// </summary> /// </summary>
public UserType Type { get; set; } public UserType Type { get; set; }
/// <summary> /// <summary>
/// Gets or sets the value of the verified (ab) /// Gets or sets the value of the verified (ab)
/// </summary> /// </summary>
public bool Verified { get; set; } public bool Verified { get; set; }
@@ -98,10 +109,10 @@ namespace FoodsharingSiegen.Contracts.Entity
#region Public Method Clone #region Public Method Clone
/// <summary> /// <summary>
/// Clones this instance (a. beging, 11.04.2022) /// Clones this instance (a. beging, 11.04.2022)
/// </summary> /// </summary>
/// <returns>The user</returns> /// <returns>The user</returns>
public User Clone() => (User) MemberwiseClone(); public User Clone() => (User)MemberwiseClone();
#endregion #endregion
} }

View File

@@ -0,0 +1,43 @@
using FoodsharingSiegen.Contracts.Model;
namespace FoodsharingSiegen.Contracts.Helper
{
/// <summary>
/// The attribute extensions class (a. beging, 31.05.2022)
/// </summary>
public static class AttributeExtensions
{
#region Public Method GetCustomValue
/// <summary>
/// Gets the custom value using the specified enum val (a. beging, 31.05.2022)
/// </summary>
/// <param name="enumVal">The enum val</param>
/// <returns>The string</returns>
public static string GetCustomValue(this Enum enumVal)
{
var attribute = enumVal.GetAttributeOfType<CustomValueAttribute>();
return attribute?.Value ?? string.Empty;
}
#endregion
#region Private Method GetAttributeOfType
/// <summary>
/// Gets the attribute of type using the specified enum val (a. beging, 31.05.2022)
/// </summary>
/// <typeparam name="T">The </typeparam>
/// <param name="enumVal">The enum val</param>
/// <returns>The</returns>
private static T? GetAttributeOfType<T>(this Enum enumVal) where T : Attribute
{
var type = enumVal.GetType();
var memInfo = type.GetMember(enumVal.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(T), false);
return attributes.Length > 0 ? (T)attributes[0] : null;
}
#endregion
}
}

View File

@@ -0,0 +1,28 @@
namespace FoodsharingSiegen.Contracts.Model
{
/// <summary>
/// The custom value attribute class (a. beging, 31.05.2022)
/// </summary>
/// <seealso cref="Attribute" />
public sealed class CustomValueAttribute : Attribute
{
#region Public Properties
/// <summary>
/// Gets the value of the value (ab)
/// </summary>
public string Value { get; }
#endregion
#region Setup/Teardown
/// <summary>
/// Initializes a new instance of the <see cref="CustomValueAttribute" /> class
/// </summary>
/// <param name="value">The value (ab)</param>
public CustomValueAttribute(string value) => Value = value;
#endregion
}
}

View File

@@ -17,7 +17,7 @@
@Prospect.Name @Prospect.Name
<small style="font-size: .9rem; opacity: .7;"> <small style="font-size: .9rem; opacity: .7;">
<a class="invert" href="https://foodsharing.de/profile/@Prospect.FsId" target="_blank">Profil öffnen</a> <a class="invert" href="@(CurrentUser.NetworkLink)/profile/@Prospect.FsId" target="_blank">Profil öffnen</a>
</small> </small>
</h5> </h5>
<div>@Prospect.Memo</div> <div>@Prospect.Memo</div>

View File

@@ -138,6 +138,7 @@ namespace FoodsharingSiegen.Server.Data.Service
entityUser.Type = user.Type; entityUser.Type = user.Type;
entityUser.Verified = user.Verified; entityUser.Verified = user.Verified;
entityUser.Groups = user.Groups; entityUser.Groups = user.Groups;
entityUser.Network = user.Network;
if (!Context.HasChanges()) if (!Context.HasChanges())
return new OperationResult(new Exception("Nichts zum Speichern gefunden")); return new OperationResult(new Exception("Nichts zum Speichern gefunden"));

View File

@@ -0,0 +1,198 @@
// <auto-generated />
using System;
using FoodsharingSiegen.Server.Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
#nullable disable
namespace FoodsharingSiegen.Server.Migrations
{
[DbContext(typeof(FsContext))]
[Migration("20220531100143_User-Network")]
partial class UserNetwork
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder.HasAnnotation("ProductVersion", "6.0.1");
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<string>("Data1")
.HasColumnType("TEXT");
b.Property<string>("Data2")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid?>("UserID")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("UserID");
b.ToTable("Audits");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<bool>("Alert")
.HasColumnType("INTEGER");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<DateTime>("Date")
.HasColumnType("TEXT");
b.Property<string>("Info")
.HasColumnType("TEXT");
b.Property<bool>("NotNeeded")
.HasColumnType("INTEGER");
b.Property<Guid>("ProspectID")
.HasColumnType("TEXT");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<Guid>("UserID")
.HasColumnType("TEXT");
b.HasKey("Id");
b.HasIndex("ProspectID");
b.HasIndex("UserID");
b.ToTable("Interactions");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<int>("FsId")
.HasColumnType("INTEGER");
b.Property<string>("Memo")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.HasKey("Id");
b.ToTable("Prospects");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("TEXT");
b.Property<DateTime>("Created")
.HasColumnType("TEXT");
b.Property<string>("EncryptedPassword")
.IsRequired()
.HasColumnType("TEXT");
b.Property<bool>("ForceLogout")
.HasColumnType("INTEGER");
b.Property<string>("Groups")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Mail")
.IsRequired()
.HasColumnType("TEXT");
b.Property<string>("Memo")
.HasColumnType("TEXT");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("TEXT");
b.Property<int>("Network")
.HasColumnType("INTEGER");
b.Property<int>("Type")
.HasColumnType("INTEGER");
b.Property<bool>("Verified")
.HasColumnType("INTEGER");
b.HasKey("Id");
b.ToTable("Users");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Audit", b =>
{
b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
.WithMany()
.HasForeignKey("UserID");
b.Navigation("User");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Interaction", b =>
{
b.HasOne("FoodsharingSiegen.Contracts.Entity.Prospect", "Prospect")
.WithMany("Interactions")
.HasForeignKey("ProspectID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("FoodsharingSiegen.Contracts.Entity.User", "User")
.WithMany("Interactions")
.HasForeignKey("UserID")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Prospect");
b.Navigation("User");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.Prospect", b =>
{
b.Navigation("Interactions");
});
modelBuilder.Entity("FoodsharingSiegen.Contracts.Entity.User", b =>
{
b.Navigation("Interactions");
});
#pragma warning restore 612, 618
}
}
}

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace FoodsharingSiegen.Server.Migrations
{
public partial class UserNetwork : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<int>(
name: "Network",
table: "Users",
type: "INTEGER",
nullable: false,
defaultValue: 0);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Network",
table: "Users");
}
}
}

View File

@@ -139,6 +139,9 @@ namespace FoodsharingSiegen.Server.Migrations
.IsRequired() .IsRequired()
.HasColumnType("TEXT"); .HasColumnType("TEXT");
b.Property<int>("Network")
.HasColumnType("INTEGER");
b.Property<int>("Type") b.Property<int>("Type")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");

View File

@@ -2,6 +2,8 @@
@using FoodsharingSiegen.Server.Dialogs @using FoodsharingSiegen.Server.Dialogs
@using FoodsharingSiegen.Server.BaseClasses @using FoodsharingSiegen.Server.BaseClasses
@using FoodsharingSiegen.Contracts.Entity
@using FoodsharingSiegen.Contracts.Helper
@inherits FsBase @inherits FsBase
@@ -33,9 +35,23 @@
</Validations> </Validations>
</Fields> </Fields>
<hr /> <hr/>
<h3>Allgemeines</h3>
<p class="mt-4 mb-1">
Die ausgewählte URL wird zum Beispiel verwendet, um die Profile der Neulinge zu verlinken
<Select TValue="FsNetworkType" @bind-SelectedValue="User.Network">
@foreach (var networkType in Enum.GetValues<FsNetworkType>())
{
<SelectItem Value="networkType">@networkType (@networkType.GetCustomValue())</SelectItem>
}
</Select>
</p>
<hr/>
<h3>Sicherheit</h3> <h3>Sicherheit</h3>
<p class="mt-4 mb-1"> <p class="mt-4 mb-1">
Die Änderung deines Passworts ist sofort aktiv. Im Anschluss wirst du ausgeloggt und kannst dich neu einloggen. Die Änderung deines Passworts ist sofort aktiv. Im Anschluss wirst du ausgeloggt und kannst dich neu einloggen.
<Button Color="Color.Primary" Class="d-block" Clicked="() => PasswordModal?.Show(User)!"><i class="fa-solid fa-key"></i>&nbsp;Passwort ändern</Button> <Button Color="Color.Primary" Class="d-block" Clicked="() => PasswordModal?.Show(User)!"><i class="fa-solid fa-key"></i>&nbsp;Passwort ändern</Button>