using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Newtonsoft.Json;
namespace Nibriboard.Userspace
{
public class UserManager
{
///
/// The list of users that this is managing.
///
public List Users { get; private set; } = new List();
///
/// A list of the permissions that this is aware of.
///
public List Permissions { get; private set; } = new List();
///
/// A list of the roles that this is aware of.
///
public List Roles { get; private set; } = new List();
public UserManager()
{
Permissions.AddRange(new RbacPermission[] {
new RbacPermission("view-public-plane", "View public planes"),
new RbacPermission("view-own-plane", "View your own planes."),
new RbacPermission("view-any-plane", "View anyone's planes."),
new RbacPermission("create-plane", "Create a new plane."),
new RbacPermission("delete-own-plane", "Delete a plane."),
new RbacPermission("delete-any-plane", "Delete a plane."),
new RbacPermission("manage-own-plane-members", "Manage the users allowed to access one of your planes."),
new RbacPermission("manage-any-plane-members", "Manage the users allowed to access one any plane.")
});
Roles.Add(new RbacRole("Guest", new List() {
ResolvePermission("view-public-plane")
}));
Roles.Add(new RbacRole("Member", new List() {
ResolvePermission("view-own-plane"),
ResolvePermission("create-plane"),
ResolvePermission("delete-own-plane"),
ResolvePermission("manage-own-plane-members")
}, new List() {
ResolveRole("Guest")
}));
Roles.Add(new RbacRole("Root", new List() {
ResolvePermission("view-any-plane"),
ResolvePermission("delete-any-plane"),
ResolvePermission("manage-any-plane-members")
}, new List() {
ResolveRole("Member")
}));
}
///
/// Loads the user data stored in the specified file.
///
/// The filename to load the user data from.
public async Task LoadUserDataFile(string filename)
{
StreamReader sourceStream = new StreamReader(filename);
await LoadUserData(sourceStream);
}
///
/// Loads the user data from the specified stream.
///
/// The stream to load the user data from.
public async Task LoadUserData(StreamReader userDataStream)
{
LoadUserData(await userDataStream.ReadToEndAsync());
}
///
/// Loads the user data from the specified JSON string.
///
/// The JSON-serialised user data to load.
public void LoadUserData(string userData)
{
Users = JsonConvert.DeserializeObject>(userData, new UserCreationConverter(this));
}
///
/// Saves the user data to the specified file.
///
/// The filename to save the user data to.
public async Task SaveUserDataFile(string filename)
{
StreamWriter destination = new StreamWriter(filename);
await SaveUserData(destination);
destination.Close();
}
///
/// Saves the user data to specified destination.
///
/// The destination to save to.
public async Task SaveUserData(StreamWriter destination)
{
string json = JsonConvert.SerializeObject(Users);
await destination.WriteLineAsync(json);
}
///
/// Resolves a permission name to it's associated object.
///
/// The permission name to resolve.
/// The resolved permission object.
public RbacPermission ResolvePermission(string permissionName)
{
return Permissions.Find((RbacPermission permission) => permission.Name == permissionName);
}
///
/// Resolves a role name to it's associated object.
///
/// The role name to resolve.
/// The resolved role object.
public RbacRole ResolveRole(string roleName)
{
return Roles.Find((RbacRole role) => role.Name == roleName);
}
///
/// Resolves a list of role names to their associated objects.
///
/// The role names to resolve.
/// The resolved role objects.
public IEnumerable ResolveRoles(IEnumerable roleNames)
{
foreach (RbacRole role in Roles)
{
if(roleNames.Contains(role.Name))
yield return role;
}
}
///
/// Works out whether a user exists with the specified username.
///
/// The target username to search for.
/// Whether a user exists with the specified username or not.
public bool UserExists(string username)
{
return Users.Any((User user) => user.Username == username);
}
///
/// Finds the user with the specified name.
///
/// The username to search for.
/// The user with the specified name.
public User GetByName(string username)
{
return Users.Find((User user) => user.Username == username);
}
///
/// Creates a new user with the specified username and password, and adds them to the system.
///
/// The username for the new user.
/// The new user's password.
public void AddUser(string username, string password)
{
if (UserExists(username))
throw new Exception($"Error: A user with the name {username} already exists, so it can't be created.");
User newUser = new User(this) {
Username = username,
CreationTime = DateTime.Now
};
newUser.SetPassword(password);
Users.Add(newUser);
}
}
}