/// <summary> /// Returns the primary role for a given member /// </summary> public async Task <TaskResult <ServerPlanetRole> > GetMemberPrimaryRole(ulong member_id, string token) { ServerAuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult <ServerPlanetRole>(false, "Failed to authorize user.", null)); } ServerPlanetMember member = await Context.PlanetMembers.Include(x => x.Planet) .FirstOrDefaultAsync(x => x.Id == member_id); if (member == null) { return(new TaskResult <ServerPlanetRole>(false, "Member does not exist.", null)); } if (!(await member.Planet.IsMemberAsync(authToken.User_Id, Context))) { return(new TaskResult <ServerPlanetRole>(false, "You are not in the planet.", null)); } var role = await member.GetPrimaryRoleAsync(Context); return(new TaskResult <ServerPlanetRole>(true, $"Found primary role.", role)); }
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; } } }
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); }
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); }
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); }
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; }
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 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; }
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); }
private static async Task GetMemberInfo(HttpContext ctx, ValourDB db, [FromHeader] string authorization, [Required] ulong planet_id) { ServerAuthToken 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).ThenInclude(x => x.User) .Include(x => x.Members).ThenInclude(x => x.RoleMembership.OrderBy(x => x.Role.Position)) .ThenInclude(x => x.Role) .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; } if (!planet.Members.Any(x => x.User_Id == auth.User_Id)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Member not found"); return; } List <PlanetMemberInfo> info = new List <PlanetMemberInfo>(); foreach (var member in planet.Members) { PlanetMemberInfo planetInfo = new PlanetMemberInfo() { Member = member, User = member.User, RoleIds = member.RoleMembership.Select(x => x.Role_Id), State = "Currently browsing" }; info.Add(planetInfo); } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(info); }
/// <summary> /// Revokes the token and effectively logs the user out /// </summary> public async Task <TaskResult> Logout(string token) { ServerAuthToken authToken = await Context.AuthTokens.FindAsync(token); if (authToken == null) { return(new TaskResult(false, "Could not find token.")); } Context.AuthTokens.Remove(authToken); await Context.SaveChangesAsync(); return(new TaskResult(true, "Logged out successfully.")); }
private static async Task PrimaryRole(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) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsync("Target member not found"); return; } // Ensure auth user is member of planet ServerPlanetMember member = await db.PlanetMembers.FirstOrDefaultAsync(x => x.Planet_Id == target_member.Planet_Id && x.User_Id == auth.User_Id); if (member is null) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsync("Auth member not found"); return; } if (member.Planet_Id != target_member.Planet_Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Planet id mismatch"); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(target_member.RoleMembership.First().Role); return; }
private static async Task LogOut(HttpContext ctx, ValourDB db, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await Unauthorized("Include token", ctx); return; } db.AuthTokens.Remove(authToken); await db.SaveChangesAsync(); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync("Success"); }
private static async Task GetChannelIds(HttpContext ctx, ValourDB db, [FromHeader] string authorization, [Required] ulong planet_id) { ServerAuthToken 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)) .Include(x => x.ChatChannels) .FirstOrDefaultAsync(x => x.Id == planet_id); if (planet == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Planet not found [id: {planet_id}]"); return; } var member = planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Member not found"); return; } List <ulong> result = new List <ulong>(); foreach (var channel in planet.ChatChannels) { if (await channel.HasPermission(member, ChatChannelPermissions.View, db)) { result.Add(channel.Id); } } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(result); }
private static async Task GetRoles(HttpContext ctx, ValourDB db, ulong planet_id, [FromHeader] string authorization) { ServerAuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token is invalid"); return; } ServerPlanet planet = await db.Planets .Include(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .Include(x => x.Roles) .FirstOrDefaultAsync(x => x.Id == planet_id); if (planet == null) { ctx.Response.StatusCode = 404; await ctx.Response.WriteAsync($"Planet not found [id: {planet_id.ToString()}]"); return; } var member = planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsync($"Member not found"); return; } if (!await planet.HasPermissionAsync(member, PlanetPermissions.View, db)) { ctx.Response.StatusCode = 403; await ctx.Response.WriteAsync($"Member lacks PlanetPermissions.View"); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(planet.Roles); }
private static async Task GetInvite(HttpContext ctx, ValourDB db, string invite_code, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } var invite = await db.PlanetInvites.Include(x => x.Planet).FirstOrDefaultAsync(x => x.Code == invite_code); if (invite == null) { await NotFound("Invite code not found", ctx); return; } if (!invite.IsPermanent()) { if (DateTime.UtcNow > invite.Time.AddMinutes((double)(invite.Hours * 60))) { db.PlanetInvites.Remove(invite); await db.SaveChangesAsync(); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync("Invite is expired"); return; } } var ban = await db.PlanetBans.FirstOrDefaultAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == invite.Planet_Id); if (ban is not null) { await Unauthorized("User is banned", ctx); return; } if (!invite.Planet.Public) { await Unauthorized("Planet is set to private", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(invite); }
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; }
private static async Task Join(HttpContext ctx, ValourDB db, string invite_code, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } var invite = await db.PlanetInvites.Include(x => x.Planet).FirstOrDefaultAsync(x => x.Code == invite_code); if (invite == null) { await NotFound("Invite code not found", ctx); return; } if (await db.PlanetBans.AnyAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == invite.Planet_Id)) { await BadRequest("User is banned from the planet", ctx); return; } if (await db.PlanetMembers.AnyAsync(x => x.User_Id == authToken.User_Id && x.Planet_Id == invite.Planet_Id)) { await BadRequest("User is already a member", ctx); return; } if (!invite.Planet.Public) { await Unauthorized("Planet is set to private", ctx); return; } var user = await db.Users.FindAsync(authToken.User_Id); await invite.Planet.AddMemberAsync(user, db); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync("Success"); }
private static async Task GetCategoryNode(HttpContext ctx, ValourDB db, ulong category_id, ulong role_id, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken is null) { await TokenInvalid(ctx); return; } if (!authToken.HasScope(UserPermissions.Membership)) { await Unauthorized("Token lacks UserPermissions.Membership", ctx); return; } var node = await db.CategoryPermissionsNodes.FirstOrDefaultAsync(x => x.Category_Id == category_id && x.Role_Id == role_id); if (node is null) { await NotFound("Node not found", ctx); return; } var member = await ServerPlanetMember.FindAsync(authToken.User_Id, node.Planet_Id, db); if (member is null) { await Unauthorized("Member not found", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(node); }
private static async Task GetUser(HttpContext ctx, ValourDB db, ulong user_id, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } var user = await db.Users.FindAsync(user_id); if (user == null) { await NotFound("User not found", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(user); }
private static async Task GetPlanetName(HttpContext ctx, ValourDB db, string invite_code, [FromHeader] string authorization) { var authToken = await ServerAuthToken.TryAuthorize(authorization, db); if (authToken == null) { await TokenInvalid(ctx); return; } var invite = await db.PlanetInvites.Include(x => x.Planet).FirstOrDefaultAsync(x => x.Code == invite_code); if (invite is null) { await NotFound("Invite not found", ctx); return; } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync(invite.Planet.Name); }
public async Task JoinInteractionGroup(ulong planet_id, string token) { using (ValourDB Context = new(ValourDB.DBOptions)) { // Authenticate user AuthToken authToken = await ServerAuthToken.TryAuthorize(token, Context); if (authToken == null) { return; } PlanetMember member = await Context.PlanetMembers.FirstOrDefaultAsync( x => x.User_Id == authToken.User_Id && x.Planet_Id == planet_id); // If the user is not a member, cancel if (member == null) { return; } } // Add to planet group await Groups.AddToGroupAsync(Context.ConnectionId, $"i-{planet_id}"); }
private static async Task InsertItem(HttpContext ctx, ValourDB db, ulong category_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; } ServerPlanetCategory category = await db.PlanetCategories.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == category_id); if (category == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Category not found [id: {category_id}]"); return; } var member = category.Planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member not found"); return; } if (!await category.HasPermission(member, CategoryPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.View"); return; } if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token lacks UserPermissions.PlanetManagement"); return; } if (!await category.HasPermission(member, CategoryPermissions.ManageCategory, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.ManageCategory"); return; } ChannelListItem in_item = await JsonSerializer.DeserializeAsync <ChannelListItem>(ctx.Request.Body); if (in_item == null || in_item.Planet_Id == 0) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Include item data."); return; } IServerChannelListItem item = await IServerChannelListItem.FindAsync(in_item.ItemType, in_item.Id, db); if (item == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Item not found [id: {in_item.Id}]"); return; } ServerPlanet item_planet = await db.Planets.FindAsync(item.Planet_Id); if (item_planet == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Item planet not found [id: {in_item.Planet_Id}]"); return; } if (item_planet.Id != category.Planet_Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Item belongs to different planet"); return; } if (item.Parent_Id == category.Id) { ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync($"No change"); return; } // Ensure that if this is a category, it is not going into a category that contains itself! if (item.ItemType == ItemType.Category) { ulong?parent_id = category.Parent_Id; while (parent_id != null) { // Recursion is a nono if (parent_id == item.Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Operation would result in recursion."); return; } parent_id = (await db.PlanetCategories.FindAsync(parent_id)).Parent_Id; } } item.Parent_Id = category.Id; item.Position = in_item.Position; db.Update(item); await db.SaveChangesAsync(); item.NotifyClientsChange(); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync("Success"); return; }
private static async Task SetChildOrder(HttpContext ctx, ValourDB db, ulong category_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; } ServerPlanetCategory category = await db.PlanetCategories.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == category_id); if (category == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Category not found [id: {category_id}]"); return; } var member = category.Planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member not found"); return; } if (!await category.HasPermission(member, CategoryPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.View"); return; } if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token lacks UserPermissions.PlanetManagement"); return; } if (!await category.HasPermission(member, CategoryPermissions.ManageCategory, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.ManageCategory"); return; } string body = await ctx.Request.ReadBodyStringAsync(); if (string.IsNullOrEmpty(body)) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Include order data."); return; } List <CategoryContentData> orderData = JsonSerializer.Deserialize <List <CategoryContentData> >(body); if (orderData == null || orderData.Count == 0) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Include order data."); return; } List <IServerChannelListItem> changed = new List <IServerChannelListItem>(); foreach (CategoryContentData order in orderData) { IServerChannelListItem item = await IServerChannelListItem.FindAsync(order.ItemType, order.Id, db); if (item == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Item with id {order.Id} not found"); return; } if (item.Planet_Id != category.Planet_Id) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Item with id {order.Id} belongs to wrong planet {item.Planet_Id}"); return; } // Only act if there is a difference if (item.Parent_Id != category_id || item.Position != order.Position) { // Prevent putting an item inside of itself if (item.Id != category_id) { item.Parent_Id = category_id; item.Position = order.Position; db.Update(item); changed.Add(item); } } } // If all is successful, save and send updates foreach (var item in changed) { // Send update to clients item.NotifyClientsChange(); } await db.SaveChangesAsync(); ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync("Success"); return; }
private static async Task GetChildren(HttpContext ctx, ValourDB db, ulong category_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; } ServerPlanetCategory category = await db.PlanetCategories.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .Include(x => x.Planet) .ThenInclude(x => x.ChatChannels) .Include(x => x.Planet) .ThenInclude(x => x.Categories) .FirstOrDefaultAsync(x => x.Id == category_id); if (category == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Category not found [id: {category_id}]"); return; } var member = category.Planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member not found"); return; } if (!await category.HasPermission(member, CategoryPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.View"); return; } List <ChannelListItem> children = new List <ChannelListItem>(); foreach (var channel in category.Planet.ChatChannels) { if (await channel.HasPermission(member, ChatChannelPermissions.View, db)) { children.Add(channel); } } foreach (var cat in category.Planet.Categories) { if (await cat.HasPermission(member, CategoryPermissions.View, db)) { children.Add(cat); } } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(children); return; }
private static async Task Category(HttpContext ctx, ValourDB db, ulong category_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; } ServerPlanetCategory category = await db.PlanetCategories.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == category_id); if (category == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Category not found [id: {category_id}]"); return; } var member = category.Planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member not found"); return; } if (!await category.HasPermission(member, CategoryPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.View"); return; } switch (ctx.Request.Method) { case "GET": { ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync((PlanetCategory)category); return; } case "DELETE": { if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token lacks UserPermissions.PlanetManagement"); return; } if (!await category.HasPermission(member, CategoryPermissions.ManageCategory, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.ManageCategory"); return; } TaskResult result = await category.TryDeleteAsync(db); if (!result.Success) { ctx.Response.StatusCode = 400; } else { ctx.Response.StatusCode = 200; } await ctx.Response.WriteAsync(result.Message); return; } } }
private static async Task ParentId(HttpContext ctx, ValourDB db, ulong category_id, int?position, [FromHeader] string authorization) { if (position == null) { position = -1; } AuthToken auth = await ServerAuthToken.TryAuthorize(authorization, db); if (auth == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token is invalid [token: {authorization}]"); return; } ServerPlanetCategory category = await db.PlanetCategories.Include(x => x.Planet) .ThenInclude(x => x.Members.Where(x => x.User_Id == auth.User_Id)) .FirstOrDefaultAsync(x => x.Id == category_id); if (category == null) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync($"Category not found [id: {category_id}]"); return; } var member = category.Planet.Members.FirstOrDefault(); if (member == null) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member not found"); return; } if (!await category.HasPermission(member, CategoryPermissions.View, db)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync("Member lacks CategoryPermissions.View"); return; } switch (ctx.Request.Method) { case "GET": { ctx.Response.StatusCode = 200; await ctx.Response.WriteAsJsonAsync(category.Parent_Id); return; } case "PUT": { if (!auth.HasScope(UserPermissions.PlanetManagement)) { ctx.Response.StatusCode = 401; await ctx.Response.WriteAsync($"Token lacks UserPermissions.PlanetManagement"); return; } string body = await ctx.Request.ReadBodyStringAsync(); ulong?parent_id; if (body == "null" || body == "0" || body == "none" || string.IsNullOrWhiteSpace(body)) { parent_id = null; } else { ulong parsed_ul; bool parsed = ulong.TryParse(body, out parsed_ul); parent_id = parsed_ul; if (!parsed) { ctx.Response.StatusCode = 400; await ctx.Response.WriteAsync("Given value is invalid"); return; } } TaskResult <int> result = await category.TrySetParentAsync(member, parent_id, (int)position, db); ctx.Response.StatusCode = result.Data; await ctx.Response.WriteAsync(result.Message); return; } } }
private static async Task RequestToken(HttpContext ctx, ValourDB db, UserManager userManager) { TokenRequest request = await JsonSerializer.DeserializeAsync <TokenRequest>(ctx.Request.Body); UserEmail emailObj = await db.UserEmails.Include(x => x.User).FirstOrDefaultAsync(x => x.Email == request.Email.ToLower()); if (emailObj == null) { await Unauthorized("Failed to authorize", ctx); return; } if (emailObj.User.Disabled) { await BadRequest("User is disabled.", ctx); return; } if (!emailObj.Verified) { await Unauthorized("The email associated with this account needs to be verified! Please check your email.", ctx); return; } var result = await userManager.ValidateAsync(CredentialType.PASSWORD, request.Email, request.Password); if (!result.Success) { await Unauthorized("Failed to authorize", ctx); return; } if (emailObj.User.Id != result.Data.Id) { await Unauthorized("Failed to authorize", ctx); return; } // This would be weird tbhtbh // Attempt to re-use token var token = await db.AuthTokens.FirstOrDefaultAsync(x => x.App_Id == "VALOUR" && x.User_Id == emailObj.User_Id && x.Scope == UserPermissions.FullControl.Value); if (token is null) { // We now have to create a token for the user token = new ServerAuthToken() { App_Id = "VALOUR", Id = "val-" + Guid.NewGuid().ToString(), Time = DateTime.UtcNow, Expires = DateTime.UtcNow.AddDays(7), Scope = UserPermissions.FullControl.Value, User_Id = emailObj.User_Id }; await db.AuthTokens.AddAsync(token); await db.SaveChangesAsync(); } else { token.Time = DateTime.UtcNow; token.Expires = DateTime.UtcNow.AddDays(7); db.AuthTokens.Update(token); await db.SaveChangesAsync(); } ctx.Response.StatusCode = 200; await ctx.Response.WriteAsync(token.Id); }
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()); }
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); }