Skip to content
Snippets Groups Projects
Commit 454ee175 authored by Marcel Nellesen's avatar Marcel Nellesen
Browse files

Merge branch 'Sprint/2021-04' into 'master'

Sprint/2021 04

See merge request !121
parents 8a5e6086 2673b0d0
Branches
Tags
2 merge requests!124Update product with master,!121Sprint/2021 04
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<RootNamespace>Coscine.Database</RootNamespace>
......
using Coscine.Database.DataModel;
using Coscine.Database.ReturnObjects;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
namespace Coscine.Database.Models
{
// ------------------------------------------------------------------------------------
// This Class makes use of "GetAllWhere(...Id)" method rather than "GetById(...Id)"
// to make it future proof in case on a later stage more than a single entry
// is allowed inside the ContactChange table (e.g. history of contact change requests).
// To achieve that, remove usage of "DeleteAllDbEntries(...Id)" method.
// The line in quesiton is marked with an appropiate comment.
// ------------------------------------------------------------------------------------
public class ContactChangeModel : DatabaseModel<ContactChange>
{
public bool UserHasEmailsToConfirm(Guid userId)
{
// Perform deletion of all expired entries (older than 24 Hours).
DeleteExpiredDbEntries(userId);
IEnumerable<ContactChange> emailData = GetAllWhere((contactChange) => contactChange.UserId == userId);
// Return True if entries for a user exist inside the database table ContactChange. Else return False.
if (emailData.Count() > 0)
{
return true;
}
else
{
return false;
}
}
public ContactChangeObject NewEmailChangeRequest(Guid userId, string email)
{
if (UserHasEmailsToConfirm(userId))
{
DeleteAllDbEntries(userId); // <--- REMOVE THIS LINE IF YOU WANT TO KEEP HISTORY OF EMAIL CHANGES.
}
ContactChangeObject contactChangeObject = AddDbEntry(userId, email);
// Sending a confirmation email after an addition to the database is handled by the Controller.
return contactChangeObject;
}
public List<ContactChangeObject> GetEmailsForConfirmation(Guid userId)
{
List<ContactChangeObject> contactChangeObjects = new List<ContactChangeObject>();
IEnumerable<ContactChange> emailData = GetAllWhere((contactChange) => contactChange.UserId == userId);
foreach (var entry in emailData)
{
contactChangeObjects.Add(ToObject(entry));
}
return contactChangeObjects;
}
public UserObject ExecuteConfirmation(Guid token)
{
ContactChange emailData = GetWhere((contactChange) => contactChange.ConfirmationToken == token);
if (emailData != null)
{
if (emailData.EditDate != null)
{
// Add 23 Hours, 59 Minutes and 59 Seconds to EditDate, see when the token has to expire and compare with Now.
DateTime expirationDateTime = emailData.EditDate.Value.AddHours(23).AddMinutes(59).AddSeconds(59);
var compareDateTime = DateTime.Compare(expirationDateTime, DateTime.Now);
// Token EXPIRED when expirationDateTime = -1 (Expiration is BEFORE Now)
// Token VALID when expirationDateTime = 0 OR = 1 (Expiration IS Now or AFTER Now)
if (compareDateTime >= 0)
{
// VALID
UserModel userModel = new UserModel();
User user = userModel.GetById(emailData.UserId);
user.EmailAddress = emailData.NewEmail; // Overwrite old Email with New.
userModel.Update(user); // Update Database (User Table).
Delete(emailData); // Delete Entry from Database (ContactChange Table).
UserObject userObject = userModel.CreateReturnObjectFromDatabaseObject(userModel.GetWhere((usr) => usr.Id == emailData.UserId));
return userObject;
}
else
{
throw new Exception("EXPIRED: Token " + token.ToString() + " has expired.");
}
}
else
{
throw new ArgumentNullException("INVALID: Value EditDate is NULL for Token " + token.ToString() + ".");
}
}
else
{
throw new MissingFieldException("INVALID: The Token " + token.ToString() + " is not valid. No entry inside the Database.");
}
}
private void DeleteExpiredDbEntries(Guid userId)
{
IEnumerable<ContactChange> emailData = GetAllWhere((contactChange) => contactChange.UserId == userId);
foreach (var entry in emailData)
{
// Add 23 Hours, 59 Minutes and 59 Seconds to EditDate, see when the token has to expire and compare with Now.
DateTime expirationDateTime = entry.EditDate.Value.AddHours(23).AddMinutes(59).AddSeconds(59);
var compareDateTime = DateTime.Compare(expirationDateTime, DateTime.Now);
// Token EXPIRED when expirationDateTime = -1 (Expiration is BEFORE Now)
// Token VALID when expirationDateTime = 0 OR = 1 (Expiration IS Now or AFTER Now)
if (compareDateTime < 0)
{
Delete(entry);
}
}
}
private void DeleteAllDbEntries(Guid userId)
{
IEnumerable<ContactChange> emailData = GetAllWhere((contactChange) => contactChange.UserId == userId);
foreach (var entry in emailData)
{
Delete(entry);
}
}
private ContactChangeObject AddDbEntry(Guid userId, string email)
{
// Create new entry inside the Database for an Email Change Request for the specific User with an Id.
ContactChange contactChange = new ContactChange()
{
RelationId = Guid.NewGuid(),
UserId = userId,
NewEmail = email,
EditDate = DateTime.Now,
ConfirmationToken = Guid.NewGuid()
};
Insert(contactChange);
return ToObject(contactChange);
}
public static ContactChangeObject ToObject(ContactChange contactChange)
{
return new ContactChangeObject(
contactChange.RelationId,
contactChange.UserId,
contactChange.NewEmail,
contactChange.EditDate,
contactChange.ConfirmationToken
);
}
public static ContactChange FromObject(ContactChangeObject contactChangeObject)
{
return new ContactChange()
{
RelationId = contactChangeObject.RelationId,
UserId = contactChangeObject.UserId,
NewEmail = contactChangeObject.NewEmail,
EditDate = contactChangeObject.EditDate,
ConfirmationToken = contactChangeObject.ConfirmationToken
};
}
public override Expression<Func<ContactChange, Guid>> GetIdFromObject()
{
return (contactChange) => contactChange.RelationId;
}
public override Microsoft.EntityFrameworkCore.DbSet<ContactChange> GetITableFromDatabase(CoscineDB db)
{
return db.ContactChanges;
}
public override void SetObjectId(ContactChange databaseObject, Guid id)
{
databaseObject.RelationId = id;
}
}
}
using System;
namespace Coscine.Database.ReturnObjects
{
public class ContactChangeObject : IReturnObject
{
public Guid RelationId { get; set; }
public Guid UserId { get; set; }
public string NewEmail { get; set; }
public DateTime? EditDate { get; set; }
public Guid ConfirmationToken { get; set; }
public ContactChangeObject(Guid relationId, Guid userId, string newEmail, DateTime? editDate, Guid confirmationToken)
{
RelationId = relationId;
UserId = userId;
NewEmail = newEmail;
EditDate = editDate;
ConfirmationToken = confirmationToken;
}
}
}
using System;
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
......@@ -21,6 +21,7 @@ namespace Coscine.Database.DataModel
public virtual DbSet<ActivatedFeature> ActivatedFeatures { get; set; }
public virtual DbSet<ApiToken> ApiTokens { get; set; }
public virtual DbSet<ContactChange> ContactChanges { get; set; }
public virtual DbSet<Discipline> Disciplines { get; set; }
public virtual DbSet<ExternalAuthenticator> ExternalAuthenticators { get; set; }
public virtual DbSet<ExternalId> ExternalIds { get; set; }
......@@ -98,6 +99,29 @@ namespace Coscine.Database.DataModel
.HasConstraintName("FK_ApiTokens_UserId_Users_Id");
});
modelBuilder.Entity<ContactChange>(entity =>
{
entity.HasKey(e => e.RelationId);
entity.ToTable("ContactChange");
entity.Property(e => e.RelationId).HasDefaultValueSql("(newid())");
entity.Property(e => e.ConfirmationToken).HasDefaultValueSql("(newid())");
entity.Property(e => e.EditDate).HasColumnType("datetime");
entity.Property(e => e.NewEmail)
.IsRequired()
.HasMaxLength(200);
entity.HasOne(d => d.User)
.WithMany(p => p.ContactChanges)
.HasForeignKey(d => d.UserId)
.OnDelete(DeleteBehavior.ClientSetNull)
.HasConstraintName("FK_ContactChange_UserId_Users_Id");
});
modelBuilder.Entity<Discipline>(entity =>
{
entity.Property(e => e.Id).HasDefaultValueSql("(newid())");
......
......@@ -12,6 +12,7 @@ namespace Coscine.Database.DataModel
public User()
{
ApiTokens = new HashSet<ApiToken>();
ContactChanges = new HashSet<ContactChange>();
ExternalIds = new HashSet<ExternalId>();
GroupMemberships = new HashSet<GroupMembership>();
ProjectRoles = new HashSet<ProjectRole>();
......@@ -33,6 +34,7 @@ namespace Coscine.Database.DataModel
public virtual Language Language { get; set; }
public virtual Title Title { get; set; }
public virtual ICollection<ApiToken> ApiTokens { get; set; }
public virtual ICollection<ContactChange> ContactChanges { get; set; }
public virtual ICollection<ExternalId> ExternalIds { get; set; }
public virtual ICollection<GroupMembership> GroupMemberships { get; set; }
public virtual ICollection<ProjectRole> ProjectRoles { get; set; }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment