Esempio n. 1
0
        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);
        }
Esempio n. 2
0
        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;
            }
            }
        }
Esempio n. 3
0
        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);
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
        /// <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}."));
        }
Esempio n. 6
0
        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;
        }
Esempio n. 7
0
        /// <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}."));
        }
Esempio n. 8
0
        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);
        }
Esempio n. 9
0
        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;
        }
Esempio n. 10
0
        /// <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}"));
        }
Esempio n. 11
0
        /// <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));
        }
Esempio n. 12
0
        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);
        }