public static async void NotifyRoleDeletion(ServerPlanetRole role) { string json = JsonSerializer.Serialize(role); // Send update to members await Current.Clients.Group($"p-{role.Planet_Id}").SendAsync("RoleDeletion", json); }
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; } } }
public static async Task NotifyRoleChange(ServerPlanetRole role) { string json = JsonConvert.SerializeObject(role); // Send update to members await Current.Clients.Group($"p-{role.Planet_Id}").SendAsync("RoleUpdate", json); }
public async Task <bool> HasPermission(ServerPlanetMember member, ChannelPermission permission) { var roles = await member.GetRolesAsync(); // Starting from the most important role, we stop once we hit the first clear "TRUE/FALSE". // If we get an undecided, we continue to the next role down foreach (var role in roles) { var node = await ServerPlanetRole.FromBase(role).GetChannelNodeAsync(this); PermissionState state = node.GetPermissionState(permission); if (state == PermissionState.Undefined) { continue; } else if (state == PermissionState.True) { return(true); } else { return(false); } } // No roles ever defined behavior: resort to false. return(false); }
/// <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}.")); }
private static async Task AddRole(HttpContext ctx, ValourDB db, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth is null) { await TokenInvalid(ctx); return; } ServerPlanetRole in_role = await JsonSerializer.DeserializeAsync <ServerPlanetRole>(ctx.Response.Body); ServerPlanetMember member = await db.PlanetMembers.FirstOrDefaultAsync(x => x.User_Id == auth.User_Id && x.Planet_Id == in_role.Planet_Id); if (member is null) { await Unauthorized("Member not found", ctx); return; } if (!auth.HasScope(UserPermissions.PlanetManagement)) { await Unauthorized("Auth token lacks UserPermissions.PlanetManagement", ctx); return; } if (!await member.HasPermissionAsync(PlanetPermissions.ManageRoles, db)) { await Unauthorized("Member lacks PlanetPermissions.ManageRoles", ctx); return; } // Ensure fields are correct in_role.Planet_Id = member.Planet_Id; in_role.Position = (uint)await db.PlanetRoles.CountAsync(x => x.Planet_Id == in_role.Planet_Id); // Generate ID in_role.Id = IdManager.Generate(); await db.PlanetRoles.AddAsync(in_role); await db.SaveChangesAsync(); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsJsonAsync(in_role.Id); return; }
/// <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}.")); }
private static async Task Create(HttpContext ctx, ValourDB db, [FromHeader] string authorization, [Required] string name, [Required] string image_url) { ServerAuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token is invalid [token: {authorization}]"); return; } TaskResult nameValid = ServerPlanet.ValidateName(name); if (!nameValid.Success) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync(nameValid.Message); return; } ServerUser user = await db.Users.FindAsync(auth.User_Id); if (!user.Valour_Staff) { var owned_planets = await db.Planets.CountAsync(x => x.Owner_Id == user.Id); if (owned_planets > MAX_OWNED_PLANETS) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Max owned planets reached"); return; } } // Image handling via proxy ProxyResponse proxyResponse = await MPSManager.GetProxy(image_url); bool is_media = MPSManager.Media_Types.Contains(proxyResponse.Item.Mime_Type); if (proxyResponse.Item == null || !is_media) { image_url = "https://valour.gg/image.png"; } else { image_url = proxyResponse.Item.Url; } ulong planet_id = IdManager.Generate(); // Create general category ServerPlanetCategory category = new ServerPlanetCategory() { Id = IdManager.Generate(), Name = "General", Parent_Id = null, Planet_Id = planet_id, Description = "General category", Position = 0 }; // Create general channel ServerPlanetChatChannel channel = new ServerPlanetChatChannel() { Id = IdManager.Generate(), Planet_Id = planet_id, Name = "General", Message_Count = 0, Description = "General chat channel", Parent_Id = category.Id }; // Create default role ServerPlanetRole defaultRole = new ServerPlanetRole() { Id = IdManager.Generate(), Planet_Id = planet_id, Position = uint.MaxValue, Color_Blue = 255, Color_Green = 255, Color_Red = 255, Name = "@everyone" }; ServerPlanet planet = new ServerPlanet() { Id = planet_id, Name = name, Member_Count = 1, Description = "A Valour server.", Image_Url = image_url, Public = true, Owner_Id = user.Id, Default_Role_Id = defaultRole.Id, Main_Channel_Id = channel.Id }; // Add planet to database await db.Planets.AddAsync(planet); await db.SaveChangesAsync(); // We must do this first to prevent foreign key errors // Add category to database await db.PlanetCategories.AddAsync(category); // Add channel to database await db.PlanetChatChannels.AddAsync(channel); // Add default role to database await db.PlanetRoles.AddAsync(defaultRole); // Save changes await db.SaveChangesAsync(); // Add owner to planet await planet.AddMemberAsync(user, db); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(planet.Id); }
private static async Task AddRole(HttpContext ctx, ValourDB db, ulong planet_id, [FromHeader] string authorization) { AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth is null) { Results.Unauthorized(); return; } ServerPlanetMember member = await db.PlanetMembers.FirstOrDefaultAsync(x => x.Planet_Id == planet_id && x.User_Id == auth.User_Id); if (member == null) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsync($"Member not found"); return; } if (!await member.HasPermissionAsync(PlanetPermissions.ManageRoles, db)) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsync($"Member lacks PlanetPermissions.ManageRoles"); return; } //string egg = await ctx.Request.ReadBodyStringAsync(); ServerPlanetRole in_role = await JsonSerializer.DeserializeAsync <ServerPlanetRole>(ctx.Request.Body); if (in_role is null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Include new role"); return; } if (in_role.Planet_Id != planet_id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Member planet does not match role planet"); return; } // Set ID in_role.Id = IdManager.Generate(); // Set planet id in_role.Planet_Id = planet_id; // Set position in_role.Position = (uint)await db.PlanetRoles.CountAsync(x => x.Planet_Id == planet_id); await db.PlanetRoles.AddAsync(in_role); await db.SaveChangesAsync(); ctx.Response.StatusCode = 201; await ctx.Response.WriteAsJsonAsync(in_role.Id); return; }
/// <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}")); }
/// <summary> /// Creates a server and if successful returns a task result with the created /// planet's id /// </summary> public async Task <TaskResult <ulong> > CreatePlanet(string name, string image_url, string token) { TaskResult nameValid = ValidateName(name); if (!nameValid.Success) { return(new TaskResult <ulong>(false, nameValid.Message, 0)); } AuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult <ulong>(false, "Failed to authorize user.", 0)); } User user = await Context.Users.FindAsync(authToken.User_Id); if (await Context.Planets.CountAsync(x => x.Owner_Id == user.Id) > MAX_OWNED_PLANETS - 1) { return(new TaskResult <ulong>(false, "You have hit your maximum planets!", 0)); } // User is verified and given planet info is valid by this point // We don't actually need the user object which is cool // Use MSP for proxying image MSPResponse proxyResponse = await MSPManager.GetProxy(image_url); if (string.IsNullOrWhiteSpace(proxyResponse.Url) || !proxyResponse.Is_Media) { image_url = "https://valour.gg/image.png"; } else { image_url = proxyResponse.Url; } ulong planet_id = IdManager.Generate(); // Create general category PlanetCategory category = new PlanetCategory() { Id = IdManager.Generate(), Name = "General", Parent_Id = null, Planet_Id = planet_id, Position = 0 }; // Create general channel PlanetChatChannel channel = new PlanetChatChannel() { Id = IdManager.Generate(), Planet_Id = planet_id, Name = "General", Message_Count = 0, Description = "General chat channel", Parent_Id = category.Id }; // Create default role ServerPlanetRole defaultRole = new ServerPlanetRole() { Id = IdManager.Generate(), Planet_Id = planet_id, Position = uint.MaxValue, Color_Blue = 255, Color_Green = 255, Color_Red = 255, Name = "@everyone" }; ServerPlanet planet = new ServerPlanet() { Id = planet_id, Name = name, Member_Count = 1, Description = "A Valour server.", Image_Url = image_url, Public = true, Owner_Id = user.Id, Default_Role_Id = defaultRole.Id, Main_Channel_Id = channel.Id }; // Add planet to database await Context.Planets.AddAsync(planet); await Context.SaveChangesAsync(); // We must do this first to prevent foreign key errors // Add category to database await Context.PlanetCategories.AddAsync(category); // Add channel to database await Context.PlanetChatChannels.AddAsync(channel); // Add default role to database await Context.PlanetRoles.AddAsync(defaultRole); // Save changes await Context.SaveChangesAsync(); // Add owner to planet await planet.AddMemberAsync(user); // Return success return(new TaskResult <ulong>(true, "Successfully created planet.", planet.Id)); }
public async Task <bool> HasPermission(ServerPlanetMember member, Permission permission, ValourDB db = null) { Planet planet = await GetPlanetAsync(db); if (planet.Owner_Id == member.User_Id) { return(true); } var roles = await member.GetRolesAsync(db); CategoryPermission catPerm = null; ChatChannelPermission chatPerm = null; catPerm = permission as CategoryPermission; chatPerm = permission as ChatChannelPermission; // Starting from the most important role, we stop once we hit the first clear "TRUE/FALSE". // If we get an undecided, we continue to the next role down foreach (var role in roles) { var node = await ServerPlanetRole.FromBase(role).GetCategoryNodeAsync(this); // If we are dealing with the default role and the behavior is undefined, we fall back to the default permissions if (node == null) { if (role.Id == planet.Default_Role_Id) { if (catPerm != null) { return(Permission.HasPermission(CategoryPermissions.Default, permission)); } else if (chatPerm != null) { return(Permission.HasPermission(ChatChannelPermissions.Default, permission)); } } continue; } PermissionState state = PermissionState.Undefined; if (catPerm != null) { state = node.GetPermissionState(permission); } else if (chatPerm != null) { state = node.GetChatChannelPermissionState(permission); } if (state == PermissionState.Undefined) { continue; } else if (state == PermissionState.True) { return(true); } else { return(false); } } // No roles ever defined behavior: resort to false. return(false); }