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); }
/// <summary> /// Tries to delete this role /// </summary> public async Task <TaskResult <int> > TryDeleteAsync(ServerPlanetMember member, ValourDB db) { if (member == null) { return(new TaskResult <int>(false, "Member not found", 404)); } if (member.Planet_Id != Planet_Id) { return(new TaskResult <int>(false, "Member is of another planet", 403)); } if (!await member.HasPermissionAsync(PlanetPermissions.ManageRoles, db)) { return(new TaskResult <int>(false, "Member lacks PlanetPermissions.ManageRoles", 403)); } if (await member.GetAuthorityAsync() <= GetAuthority()) { return(new TaskResult <int>(false, "Member authority is lower than role authority", 403)); } Planet ??= await db.Planets.FindAsync(Planet_Id); if (Id == Planet.Default_Role_Id) { return(new TaskResult <int>(false, "Cannot remove default role", 400)); } // Remove all members var members = db.PlanetRoleMembers.Where(x => x.Role_Id == Id); db.PlanetRoleMembers.RemoveRange(members); // Remove role nodes var channelNodes = db.ChatChannelPermissionsNodes.Where(x => x.Role_Id == Id); var categoryNodes = db.CategoryPermissionsNodes.Where(x => x.Role_Id == Id); db.ChatChannelPermissionsNodes.RemoveRange(channelNodes); db.CategoryPermissionsNodes.RemoveRange(categoryNodes); // Remove self db.PlanetRoles.Remove(this); await db.SaveChangesAsync(); // Notify clients PlanetHub.NotifyRoleDeletion(this); return(new TaskResult <int>(true, "Removed role", 200)); }
/// <summary> /// Creates the requested role /// </summary> public async Task <TaskResult> EditRole([FromBody] ServerPlanetRole role, string token) { AuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult(false, "Failed to authorize user.")); } if (!Permission.HasPermission(authToken.Scope, UserPermissions.PlanetManagement)) { return(new TaskResult(false, "You don't have planet management scope.")); } if (!(await Context.PlanetRoles.AnyAsync(x => x.Id == role.Id))) { return(new TaskResult(false, $"The role {role.Id} does not exist.")); } ServerPlanetMember member = await Context.PlanetMembers.Include(x => x.User) .Include(x => x.Planet) .FirstOrDefaultAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == role.Planet_Id); if (member == null) { return(new TaskResult(false, "You're not in the planet!")); } if (!(await member.HasPermissionAsync(PlanetPermissions.ManageRoles))) { return(new TaskResult(false, "You don't have role management permissions!")); } // Do not allow modifying roles with a lower position than your own (lower is more powerful) if (member.User_Id != member.Planet.Owner_Id) { if (((await member.GetPrimaryRoleAsync()).Position > role.Position)) { return(new TaskResult(false, "You can't edit a role above your own!")); } } Context.PlanetRoles.Update(role); await Context.SaveChangesAsync(); await PlanetHub.NotifyRoleChange(role); return(new TaskResult(true, $"Successfully edited role {role.Id}.")); }
public async Task <TaskResult <int> > TryUpdateAsync(ServerPlanetMember member, ServerPlanetRole newRole, ValourDB db) { if (member == null) { return(new TaskResult <int>(false, "Member not found", 403)); } if (member.Planet_Id != Planet_Id) { return(new TaskResult <int>(false, "Member is of another planet", 403)); } if (!await member.HasPermissionAsync(PlanetPermissions.ManageRoles, db)) { return(new TaskResult <int>(false, "Member lacks PlanetPermissions.ManageRoles", 403)); } if (await member.GetAuthorityAsync() <= GetAuthority()) { return(new TaskResult <int>(false, "Member authority is lower than role authority", 403)); } if (newRole.Id != Id) { return(new TaskResult <int>(false, "Given role does not match id", 400)); } this.Name = newRole.Name; this.Position = newRole.Position; this.Permissions = newRole.Permissions; this.Color_Red = newRole.Color_Red; this.Color_Green = newRole.Color_Green; this.Color_Blue = newRole.Color_Blue; this.Bold = newRole.Bold; this.Italics = newRole.Italics; db.PlanetRoles.Update(this); await db.SaveChangesAsync(); PlanetHub.NotifyRoleChange(this); return(new TaskResult <int>(true, "Success", 200)); }
/// <summary> /// Creates the requested role /// </summary> public async Task <TaskResult> CreateRole([FromBody] ServerPlanetRole role, string token) { AuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult(false, "Failed to authorize user.")); } if (!Permission.HasPermission(authToken.Scope, UserPermissions.PlanetManagement)) { return(new TaskResult(false, "You don't have planet management scope.")); } ServerPlanetMember member = await Context.PlanetMembers.Include(x => x.User) .FirstOrDefaultAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == role.Planet_Id); if (member == null) { return(new TaskResult(false, "You're not in the planet!")); } if (!(await member.HasPermissionAsync(PlanetPermissions.ManageRoles))) { return(new TaskResult(false, "You don't have role management permissions!")); } // Set role id role.Id = IdManager.Generate(); // Set to next open position role.Position = (uint)await Context.PlanetRoles.Where(x => x.Planet_Id == role.Planet_Id).CountAsync(); await Context.PlanetRoles.AddAsync(role); await Context.SaveChangesAsync(); await PlanetHub.NotifyRoleChange(role); return(new TaskResult(true, $"Role {role.Id} successfully added to position {role.Position}.")); }
public IHttpActionResult Create(AnnouncementDto announcement) { return(CreateResponse(() => { if (!ModelState.IsValid) { return BadRequest(ModelState); } announcement.DateCreated = DateTime.Now; var model = Mapper.Map <Announcement>(announcement); _announcementService.Add(model); UnitOfWork.Commit(); announcement.Id = model.Id; PlanetHub.PushToAllUsers(announcement, null); return Created(new Uri(Request.RequestUri + "/" + announcement.Id), announcement); })); }
/// <summary> /// Tries to delete the category while respecting constraints /// </summary> public async Task <TaskResult> TryDeleteAsync(ValourDB db) { var planet = await GetPlanetAsync(); if (await db.PlanetCategories.CountAsync(x => x.Planet_Id == Planet_Id) < 2) { return(new TaskResult(false, "Last category cannot be deleted")); } var childCategoryCount = await db.PlanetCategories.CountAsync(x => x.Parent_Id == Id); var childChannelCount = await db.PlanetChatChannels.CountAsync(x => x.Parent_Id == Id); if (childCategoryCount != 0 || childChannelCount != 0) { return(new TaskResult(false, "Category must be empty")); } // Remove permission nodes db.CategoryPermissionsNodes.RemoveRange( db.CategoryPermissionsNodes.Where(x => x.Category_Id == Id) ); // Remove category db.PlanetCategories.Remove( await db.PlanetCategories.FindAsync(Id) ); // Save changes await db.SaveChangesAsync(); // Notify of update await PlanetHub.NotifyCategoryDeletion(this); return(new TaskResult(true, "Success")); }
private static async Task CreateCategory(HttpContext ctx, ValourDB db, [FromHeader] string authorization) { ServerPlanetCategory category_data = await JsonSerializer.DeserializeAsync <ServerPlanetCategory>(ctx.Request.Body); if (category_data == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Please include category in body"); return; } if (string.IsNullOrWhiteSpace(category_data.Name)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Please include a category name"); return; } // Request parameter validation // TaskResult name_valid = ServerPlanetCategory.ValidateName(category_data.Name); if (!name_valid.Success) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Name is not valid [name: {category_data.Name}]"); return; } // Request authorization // AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Token lacks UserPermissions.PlanetManagement scope"); return; } ServerPlanet planet = await db.Planets.Include(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == category_data.Planet_Id); var member = planet.Members.FirstOrDefault(); if (!await planet.HasPermissionAsync(member, PlanetPermissions.ManageChannels, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks PlanetPermissions.ManageChannels node"); return; } // Ensure parent category exists ulong?parent_id = null; ServerPlanetCategory parent = await db.PlanetCategories.FindAsync(category_data.Parent_Id); ushort child_count = 0; if (parent != null) { parent_id = parent.Id; if (parent.Planet_Id != planet.Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Parent id does not match planet"); return; } child_count += (ushort)await db.PlanetChatChannels.CountAsync(x => x.Parent_Id == parent_id); child_count += (ushort)await db.PlanetCategories.CountAsync(x => x.Parent_Id == parent_id); } // Request action // // Creates the category ServerPlanetCategory category = new ServerPlanetCategory() { Id = IdManager.Generate(), Name = category_data.Name, Planet_Id = category_data.Planet_Id, Parent_Id = category_data.Parent_Id, Description = category_data.Description, Position = child_count }; // Add channel to database await db.PlanetCategories.AddAsync(category); // Save changes to DB await db.SaveChangesAsync(); // Send channel refresh PlanetHub.NotifyCategoryChange(category); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsync(category.Id.ToString()); }
/// <summary> /// Sets whether or not a member is in a role /// </summary> public async Task <TaskResult> SetMemberRoleMembership(ulong role_id, ulong member_id, bool value, string token) { ServerAuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult(false, "Failed to authorize user.")); } // Oauth protection if (!Permission.HasPermission(authToken.Scope, UserPermissions.PlanetManagement)) { return(new TaskResult(false, "You don't have planet management scope.")); } // Retrieve role ServerPlanetRole role = await Context.PlanetRoles.Include(x => x.Planet) .FirstOrDefaultAsync(x => x.Id == role_id); if (role == null) { return(new TaskResult(false, $"Role {role_id} could not be found.")); } ServerPlanetMember authMember = await Context.PlanetMembers.Include(x => x.RoleMembership) .ThenInclude(x => x.Role) .FirstOrDefaultAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == role.Planet_Id); // If the authorizor is not in the planet if (authMember == null) { return(new TaskResult(false, $"You are not in the target planet!")); } // Get target member var targetMember = await Context.PlanetMembers.FindAsync(member_id); if (targetMember == null) { return(new TaskResult(false, $"Could not find member with id {member_id}")); } // Get auth primary role var primaryAuthRole = authMember.RoleMembership.OrderBy(x => x.Role.Position).FirstOrDefault(); if (authMember.Planet_Id != authMember.Planet.Owner_Id && primaryAuthRole == null) { return(new TaskResult(false, $"Error: Issue retrieving primary role for authorizor")); } if (!(await authMember.HasPermissionAsync(PlanetPermissions.ManageRoles, Context))) { return(new TaskResult(false, $"You don't have permission to manage roles")); } // Ensure that the role being set is *lower* than their own role if (role.Planet.Owner_Id != authMember.User_Id && role.Position <= primaryAuthRole.Role.Position) { return(new TaskResult(false, $"You cannot set roles that aren't below your own")); } // At this point, authorization should be complete // Add the role if (value) { // Ensure it isn't already there if (await Context.PlanetRoleMembers.AnyAsync(x => x.Member_Id == targetMember.Id && x.Role_Id == role.Id)) { return(new TaskResult(true, $"The user already has the role.")); } ServerPlanetRoleMember roleMember = new ServerPlanetRoleMember() { Id = IdManager.Generate(), Member_Id = targetMember.Id, Role_Id = role.Id, User_Id = targetMember.User_Id, Planet_Id = targetMember.Planet_Id }; await Context.PlanetRoleMembers.AddAsync(roleMember); } // Remove the role else { if (role.Id == authMember.Planet.Default_Role_Id) { return(new TaskResult(false, $"Cannot remove the default role!")); } var currentRoleMember = await Context.PlanetRoleMembers.FirstOrDefaultAsync(x => x.Member_Id == targetMember.Id && x.Role_Id == role.Id); // Ensure the user actually has the role if (currentRoleMember == null) { return(new TaskResult(true, $"The user doesn't have the role.")); } Context.PlanetRoleMembers.Remove(currentRoleMember); } // Save changes await Context.SaveChangesAsync(); // Send ping that the member was modified (new role) await PlanetHub.NotifyMemberChange(targetMember); return(new TaskResult(true, $"Successfully set role membership to {value}")); }
public void NotifyClientsChange() { PlanetHub.NotifyCategoryChange(this); }
private static async Task Channel(HttpContext ctx, ValourDB db, ulong channel_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { await TokenInvalid(ctx); return; } switch (ctx.Request.Method) { case "GET": { ServerPlanetChatChannel channel = await db.PlanetChatChannels.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == channel_id); if (channel == null) { await NotFound("Channel not found", ctx); return; } var member = channel.Planet.Members.FirstOrDefault(); if (member == null) { await Unauthorized("Member not found", ctx); return; } if (!await channel.HasPermission(member, ChatChannelPermissions.View, db)) { await Unauthorized("Member lacks ChatChannelPermissions.View", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync((PlanetChatChannel)channel); return; } case "DELETE": { ServerPlanetChatChannel channel = await db.PlanetChatChannels.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == channel_id); if (channel == null) { await NotFound("Channel not found", ctx); return; } var member = channel.Planet.Members.FirstOrDefault(); if (!auth.HasScope(UserPermissions.PlanetManagement)) { await Unauthorized("Token lacks UserPermissions.PlanetManagement", ctx); return; } TaskResult <int> result = await channel.TryDeleteAsync(member, db); ctx.Response.StatusCode = result.Data; await ctx.Response.WriteAsync(result.Message); return; } case "POST": { ServerPlanetChatChannel channel_data = JsonSerializer.Deserialize <ServerPlanetChatChannel>(ctx.Request.Body); if (channel_data == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Please include channel in body"); return; } if (string.IsNullOrWhiteSpace(channel_data.Name)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Please include a channel name"); return; } // Request parameter validation // TaskResult name_valid = ServerPlanetChatChannel.ValidateName(channel_data.Name); if (!name_valid.Success) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Name is not valid [name: {channel_data.Name}]"); return; } // Request authorization // if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Token lacks UserPermissions.PlanetManagement scope"); return; } ServerPlanetMember member = await db.PlanetMembers .Include(x => x.Planet) .FirstOrDefaultAsync(x => x.Planet_Id == channel_data.Planet_Id && x.User_Id == auth.User_Id); if (!await member.HasPermissionAsync(PlanetPermissions.ManageChannels, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks PlanetPermissions.ManageChannels node"); return; } // Ensure parent category exists ServerPlanetCategory parent = await db.PlanetCategories.FindAsync(channel_data.Parent_Id); if (parent == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Could not find parent"); return; } if (parent.Planet_Id != member.Planet.Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Parent id does not match planet"); return; } // Request action // // Creates the channel ushort child_count = 0; child_count += (ushort)await db.PlanetChatChannels.CountAsync(x => x.Parent_Id == channel_data.Parent_Id); child_count += (ushort)await db.PlanetCategories.CountAsync(x => x.Parent_Id == channel_data.Parent_Id); ServerPlanetChatChannel channel = new ServerPlanetChatChannel() { Id = IdManager.Generate(), Name = channel_data.Name, Planet_Id = channel_data.Planet_Id, Parent_Id = channel_data.Parent_Id, Message_Count = 0, Description = channel_data.Description, Position = child_count }; // Add channel to database await db.PlanetChatChannels.AddAsync(channel); // Save changes to DB await db.SaveChangesAsync(); // Send channel refresh PlanetHub.NotifyChatChannelChange(channel); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsync(channel.Id.ToString()); return; } } }