/// <summary> /// Adds a member to the server /// </summary> public async Task AddMemberAsync(User user, ValourDB db) { // Already a member if (await db.PlanetMembers.AnyAsync(x => x.User_Id == user.Id && x.Planet_Id == Id)) { return; } ServerPlanetMember member = new ServerPlanetMember() { Id = IdManager.Generate(), Nickname = user.Username, Planet_Id = Id, User_Id = user.Id }; // Add to default planet role ServerPlanetRoleMember rolemember = new ServerPlanetRoleMember() { Id = IdManager.Generate(), Planet_Id = Id, User_Id = user.Id, Role_Id = Default_Role_Id, Member_Id = member.Id }; await db.PlanetMembers.AddAsync(member); await db.PlanetRoleMembers.AddAsync(rolemember); await db.SaveChangesAsync(); Console.WriteLine($"User {user.Username} ({user.Id}) has joined {Name} ({Id})"); }
private static async Task GetAuthority(HttpContext ctx, ValourDB db, ulong member_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth is null) { await TokenInvalid(ctx); return; } ServerPlanetMember target_member = await db.PlanetMembers .Include(x => x.RoleMembership.OrderBy(x => x.Role.Position)) .ThenInclude(x => x.Role) .FirstOrDefaultAsync(x => x.Id == member_id); if (target_member is null) { await NotFound("Target member not found", ctx); return; } // Ensure auth user is member of planet ServerPlanetMember auth_member = await db.PlanetMembers.FirstOrDefaultAsync(x => x.Planet_Id == target_member.Planet_Id && x.User_Id == auth.User_Id); if (auth_member is null) { await Unauthorized("Auth member not found", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(await target_member.GetAuthorityAsync()); return; }
/// <summary> /// Returns the default role for the planet /// </summary> public async Task <PlanetRole> GetDefaultRole() { using (ValourDB Context = new ValourDB(ValourDB.DBOptions)) { return(await Context.PlanetRoles.FindAsync(Default_Role_Id)); } }
/// <summary> /// Validates and returns a User using credentials (async) /// </summary> public async Task <TaskResult <User> > ValidateAsync(string credential_type, string identifier, string secret) { using (ValourDB context = new ValourDB(ValourDB.DBOptions)) { // Find the credential that matches the identifier and type Credential credential = await context.Credentials.FirstOrDefaultAsync( x => string.Equals(credential_type, x.Credential_Type, StringComparison.OrdinalIgnoreCase) && string.Equals(identifier, x.Identifier, StringComparison.OrdinalIgnoreCase)); if (credential == null || string.IsNullOrWhiteSpace(secret)) { return(new TaskResult <User>(false, "The credentials were incorrect.", null)); } // Use salt to validate secret hash byte[] hash = PasswordManager.GetHashForPassword(secret, credential.Salt); // Spike needs to remember how reference types work if (!hash.SequenceEqual(credential.Secret)) { return(new TaskResult <User>(false, "The credentials were incorrect.", null)); } User user = await context.Users.FindAsync(credential.User_Id); if (user.Disabled) { return(new TaskResult <User>(false, "This account has been disabled", null)); } return(new TaskResult <User>(true, "Succeeded", user)); } }
private static async Task Interaction(HttpContext ctx, ValourDB db, [FromHeader] string authorization) { InteractionEvent e = await JsonSerializer.DeserializeAsync <InteractionEvent>(ctx.Request.Body); var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } var member = await db.PlanetMembers.Include(x => x.Planet).FirstOrDefaultAsync(x => x.Id == e.Member_Id); if (member == null) { await NotFound("Member not found", ctx); return; } if (authToken.User_Id != member.User_Id) { await BadRequest("Member id mismatch", ctx); return; } var channel = await db.PlanetChatChannels.FindAsync(e.Channel_Id); if (!await channel.HasPermission(member, ChatChannelPermissions.View, db)) { await Unauthorized("Member lacks ChatChannelPermissions.View", ctx); return; } PlanetHub.NotifyInteractionEvent(e); }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { Task task = Task.Run(async() => { //try //{ Context = new ValourDB(ValourDB.DBOptions); if (Context != null && System.Diagnostics.Debugger.IsAttached == false) { stats.Time = DateTime.UtcNow; stats.userCount = Context.Users.Count(); stats.planetCount = Context.Planets.Count(); stats.planetmemberCount = Context.PlanetMembers.Count(); stats.channelCount = Context.PlanetChatChannels.Count(); stats.categoryCount = Context.PlanetCategories.Count(); await Context.Stats.AddAsync(stats); await Context.SaveChangesAsync(); stats = new StatObject(); _logger.LogInformation($"Saved successfully."); } }); while (!task.IsCompleted) { _logger.LogInformation($"Stat Worker running at: {DateTimeOffset.Now}"); await Task.Delay(60000, stoppingToken); } _logger.LogInformation("Stat Worker task stopped at: {time}", DateTimeOffset.Now); _logger.LogInformation("Restarting.", DateTimeOffset.Now); } }
/// <summary> /// Returns all members who can see this channel /// </summary> public async Task <List <ServerPlanetMember> > GetChannelMembersAsync(ValourDB db = null) { List <ServerPlanetMember> members = new List <ServerPlanetMember>(); bool createdb = false; if (db == null) { db = new ValourDB(ValourDB.DBOptions); createdb = true; } var planetMembers = db.PlanetMembers.Include(x => x.RoleMembership).Where(x => x.Planet_Id == Planet_Id); foreach (var member in planetMembers) { if (await HasPermission(member, ChatChannelPermissions.View, db)) { members.Add(member); } } if (createdb) { await db.DisposeAsync(); } return(members); }
private static async Task GetPlanets(HttpContext ctx, ValourDB db, ulong user_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { await TokenInvalid(ctx); return; } if (!auth.HasScope(UserPermissions.Membership)) { await Unauthorized("Token lacks UserPermissions.Membership", ctx); return; } if (auth.User_Id != user_id) { await Unauthorized("User id does not match token holder", ctx); return; } ServerUser user = await db.Users .Include(x => x.Membership) .ThenInclude(x => x.Planet) .FirstOrDefaultAsync(x => x.Id == user_id); if (user == null) { await NotFound("User not found", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(user.Membership.Select(x => x.Planet)); }
private static async Task GetInvites(HttpContext ctx, ValourDB db, ulong planet_id, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } ServerPlanetMember member = await db.PlanetMembers .Include(x => x.Planet) .ThenInclude(x => x.Invites) .FirstOrDefaultAsync(x => x.Planet_Id == planet_id && x.User_Id == authToken.User_Id); if (member == null) { await Unauthorized("Member not found", ctx); return; } if (!await member.HasPermissionAsync(PlanetPermissions.Invite, db)) { await Unauthorized("Member lacks PlanetPermissions.Invite", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(member.Planet.Invites); }
/// <summary> /// Creates a PlanetUser instance using a user id and planet id /// </summary> public static async Task <ServerPlanetUser> CreateAsync(ulong userid, ulong planet_id, IMapper mapper) { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { // Retrieve user User user = await db.Users.FindAsync(userid); // Retrieve planet ServerPlanet planet = ServerPlanet.FromBase(await db.Planets.FindAsync(planet_id), mapper); // TODO: Actually set roles and stuff once roles exist. // Ensure user is within planet if (!(await planet.IsMemberAsync(user))) { return(null); } // First map the user to a planetUser to copy basic fields ServerPlanetUser planetUser = mapper.Map <ServerPlanetUser>(user); // Now copy across planet info planetUser.Planet_Id = planet_id; return(planetUser); } }
public List <ChannelPermissionsNode> GetAllChannelNodes() { using (ValourDB Context = new ValourDB(ValourDB.DBOptions)) { return(Context.ChannelPermissionsNodes.Where(x => x.Planet_Id == Planet_Id).ToList()); } }
/// <summary> /// Returns all of the roles for a planet user /// </summary> public async Task <List <ServerPlanetRole> > GetRolesAsync(ValourDB db = null) { bool createdb = false; if (db == null) { db = new ValourDB(ValourDB.DBOptions); createdb = true; } List <ServerPlanetRole> roles = new List <ServerPlanetRole>(); // Add default role ServerPlanet planet = await ServerPlanet.FindAsync(Planet_Id); var membership = db.PlanetRoleMembers.Include(x => x.Role) .Where(x => x.Member_Id == Id) .OrderBy(x => x.Role.Position) .Select(x => x.Role) .ToList(); if (createdb) { await db.DisposeAsync(); } return(membership); }
private static async Task KickMember(HttpContext ctx, ValourDB db, ulong planet_id, ulong target_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth is null) { Results.Unauthorized(); return; } ServerPlanet planet = await db.Planets .Include(x => x.Members.Where(x => x.User_Id == auth.User_Id || x.Id == target_id)) .FirstOrDefaultAsync(x => x.Id == planet_id); if (planet is null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsync($"Planet not found"); return; } ServerPlanetMember member = planet.Members.FirstOrDefault(x => x.User_Id == auth.User_Id); ServerPlanetMember target = planet.Members.FirstOrDefault(x => x.Id == target_id); var result = await planet.TryKickMemberAsync(member, target, db); ctx.Response.StatusCode = result.Data; await ctx.Response.WriteAsync(result.Message); }
/// <summary> /// Returns the planet (async) /// </summary> public async Task <Planet> GetPlanetAsync() { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { return(await db.Planets.FindAsync(Planet_Id)); } }
/// <summary> /// Returns if the member has the given permission /// </summary> public async Task <bool> HasPermissionAsync(PlanetPermission permission, ValourDB db = null) { // Make sure we didn't include the planet already if (Planet == null) { bool createdb = false; if (db == null) { db = new ValourDB(ValourDB.DBOptions); createdb = true; } Planet = await db.Planets.FindAsync(Planet_Id); if (createdb) { await db.DisposeAsync(); } } // Special case for owner if (User_Id == Planet.Owner_Id) { return(true); } return((await GetPrimaryRoleAsync(db)).HasPermission(permission)); }
/// <summary> /// Returns if a given user id is a member (async) /// </summary> public async Task <bool> IsMemberAsync(ulong userid) { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { return(await db.PlanetMembers.AnyAsync(x => x.Planet_Id == this.Id && x.User_Id == userid)); } }
private static async Task Role(HttpContext ctx, ValourDB db, ulong role_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth is null) { await TokenInvalid(ctx); return; } ServerPlanetRole role = await db.PlanetRoles.FindAsync(role_id); if (role == null) { await NotFound("Role not found.", ctx); return; } ServerPlanetMember member = await db.PlanetMembers .Include(x => x.Planet) .FirstOrDefaultAsync(x => x.Planet_Id == role.Planet_Id && x.User_Id == auth.User_Id); if (member == null) { await NotFound("Member not found", ctx); return; } switch (ctx.Request.Method) { case "GET": { ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(role); return; } case "DELETE": { var result = await role.TryDeleteAsync(member, db); ctx.Response.StatusCode = result.Data; await ctx.Response.WriteAsync(result.Message); return; } case "PUT": { ServerPlanetRole in_role = await JsonSerializer.DeserializeAsync <ServerPlanetRole>(ctx.Response.Body); var result = await role.TryUpdateAsync(member, in_role, db); ctx.Response.StatusCode = result.Data; await ctx.Response.WriteAsync(result.Message); return; } } }
/// <summary> /// Returns the user (async) /// </summary> public async Task <User> GetUserAsync() { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { return(await db.Users.FindAsync(User_Id)); } }
private static async Task GetMemberRoleIds(HttpContext ctx, ValourDB db, ulong planet_id, ulong user_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token is invalid [token: {authorization}]"); return; } ServerPlanet planet = await db.Planets.Include(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == planet_id); if (planet == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Planet not found [id: {planet_id.ToString()}]"); return; } ServerPlanetMember member = planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Member not found"); return; } if (!await planet.HasPermissionAsync(member, PlanetPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks PlanetPermissions.View"); return; } ServerPlanetMember target = await db.PlanetMembers.Include(x => x.RoleMembership.OrderBy(x => x.Role.Position)) .ThenInclude(x => x.Role) .FirstOrDefaultAsync(x => x.Planet_Id == planet_id && x.User_Id == user_id); if (target == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Member not found [user_id: {user_id.ToString()}, planet_id: {planet_id.ToString()}"); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(target.RoleMembership.Select(x => x.Role_Id)); return; }
/// <summary> /// Sets the parent of this channel /// </summary> public async Task SetParentAsync(ulong parent_id, ValourDB db) { this.Parent_Id = parent_id; db.PlanetChatChannels.Update(this); await db.SaveChangesAsync(); NotifyClientsChange(); }
public static async Task <ServerPlanetMember> FindAsync(ulong user_id, ulong planet_id) { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { return(FromBase(await db.PlanetMembers.FirstOrDefaultAsync(x => x.Planet_Id == planet_id && x.User_Id == user_id))); } }
/// <summary> /// Sets the description of this channel /// </summary> public async Task SetDescriptionAsync(string desc, ValourDB db) { this.Description = desc; db.PlanetChatChannels.Update(this); await db.SaveChangesAsync(); NotifyClientsChange(); }
/// <summary> /// Sets the permissions inherit mode of this channel /// </summary> public async Task SetInheritsPermsAsync(bool inherits_perms, ValourDB db) { this.Inherits_Perms = inherits_perms; db.PlanetChatChannels.Update(this); await db.SaveChangesAsync(); NotifyClientsChange(); }
public async Task <ChannelPermissionsNode> GetChannelNodeAsync(PlanetChatChannel channel) { using (ValourDB Context = new ValourDB(ValourDB.DBOptions)) { return(await Context.ChannelPermissionsNodes.FirstOrDefaultAsync(x => x.Channel_Id == channel.Id && x.Role_Id == Id)); } }
/// <summary> /// Returns the primary channel for the planet /// </summary> public async Task <PlanetChatChannel> GetPrimaryChannelAsync() { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { // TODO: Make a way to choose a primary channel rather than just grabbing the first one return(await db.PlanetChatChannels.Where(x => x.Planet_Id == this.Id).FirstAsync()); } }
private static async Task CreateInvite(HttpContext ctx, ValourDB db, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } ServerPlanetInvite in_invite = await JsonSerializer.DeserializeAsync <ServerPlanetInvite>(ctx.Request.Body); ServerPlanetMember member = await db.PlanetMembers.Include(x => x.Planet).FirstOrDefaultAsync(x => x.Planet_Id == in_invite.Planet_Id && x.User_Id == authToken.User_Id); if (member == null) { await Unauthorized("Member not found", ctx); return; } if (!await member.HasPermissionAsync(PlanetPermissions.Invite, db)) { await Unauthorized("Member lacks PlanetPermissions.Invite", ctx); return; } // Ensure important fields are correct in_invite.Issuer_Id = authToken.User_Id; in_invite.Time = DateTime.UtcNow; in_invite.Id = IdManager.Generate(); Random random = new(); const string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; string code = ""; bool exists = false; do { code = new string(Enumerable.Repeat(chars, 8).Select(s => s[random.Next(s.Length)]).ToArray()); exists = await db.PlanetInvites.AnyAsync(x => x.Code == code); }while (!exists); in_invite.Code = code; if (in_invite.Hours < 1) { in_invite.Hours = null; } await db.PlanetInvites.AddAsync(in_invite); await db.SaveChangesAsync(); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsync(in_invite.Code); }
/// <summary> /// Retrieves a ServerPlanet for the given id /// </summary> public static async Task <ServerPlanet> FindAsync(ulong id, IMapper mapper) { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { Planet planet = await db.Planets.FindAsync(id); return(ServerPlanet.FromBase(planet, mapper)); } }
public async Task <PermissionState> GetPermissionStateAsync(Permission permission, ulong channel_id) { using (ValourDB Context = new ValourDB(ValourDB.DBOptions)) { ChannelPermissionsNode node = await Context.ChannelPermissionsNodes.FirstOrDefaultAsync(x => x.Role_Id == Id && x.Channel_Id == channel_id); return(node.GetPermissionState(permission)); } }
/// <summary> /// Retrieves a ServerPlanetChatChannel for the given id /// </summary> public static async Task <ServerPlanetChatChannel> FindAsync(ulong id) { using (ValourDB db = new ValourDB(ValourDB.DBOptions)) { PlanetChatChannel channel = await db.PlanetChatChannels.FindAsync(id); return(ServerPlanetChatChannel.FromBase(channel)); } }
/// <summary> /// Returns the member's primary role /// </summary> public async Task <ServerPlanetRole> GetPrimaryRoleAsync(ValourDB db = null) { if (RoleMembership == null) { await LoadRoleMembershipAsync(db); } return(RoleMembership.FirstOrDefault().Role); }