using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using SimpleHashing.Net;
namespace Nibriboard.Userspace
{
///
/// Creates new class instances for Newtonsoft.json.
///
public class UserCreationConverter : CustomCreationConverter
{
private UserManager userManager;
public UserCreationConverter(UserManager inUserManager)
{
userManager = inUserManager;
}
public override User Create(Type objectType)
{
return new User(userManager);
}
}
///
/// Represents a single Nibriboard user.
///
[JsonObject(MemberSerialization.OptIn)]
public class User
{
private static ISimpleHash passwordHasher = new SimpleHash();
private UserManager userManager;
[JsonProperty]
public DateTime CreationTime { get; set; }
[JsonProperty]
public string Username { get; set; }
[JsonProperty]
public string HashedPassword { get; set; }
[JsonIgnore]
public List Roles { get; set; } = new List();
[JsonProperty]
public List RawRoles = new List();
public List RolesText {
get {
return new List(Roles.Select((RbacRole role) => role.Name));
}
set {
RawRoles = value;
}
}
public User(UserManager inUserManager)
{
userManager = inUserManager;
}
///
/// Updates this user's password.
///
/// The new (unhashed) password.
public void SetPassword(string newPassword)
{
HashedPassword = passwordHasher.Compute(newPassword);
}
///
/// Checks whether a specified (unhashed) password matches
///
/// The password to check.
/// Whether the specified password matches the stored password or not.
public bool CheckPassword(string providedPassword)
{
return passwordHasher.Verify(providedPassword, HashedPassword);
}
///
/// Recursively works out whether this user has the specified permission.
///
/// The permission to search for.
/// Whether this user has the specified permission through one of their roles or not.
public bool HasPermission(RbacPermission permission)
{
return Roles.Any((RbacRole role) => role.HasPermission(permission));
}
public bool HasRole(RbacRole targetRole)
{
return Roles.Any((RbacRole role) => role.HasRole(targetRole));
}
[OnSerializing]
internal void OnSerializing(StreamingContext context)
{
// Update the textual list of roles just before serialisation
RawRoles = RolesText;
}
[OnDeserialized]
internal void OnDeserialized(StreamingContext context)
{
// Resolve the list of text roles to a list of RbacRole objects after deserialisation
Roles = new List(userManager.ResolveRoles(RawRoles));
}
}
}