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); } } }