Exemplo n.º 1
0
    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);
    }
Exemplo n.º 2
0
        /// <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));
        }
Exemplo n.º 3
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}."));
        }
Exemplo n.º 4
0
        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));
        }
Exemplo n.º 5
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}."));
        }
Exemplo n.º 6
0
        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);
            }));
        }
Exemplo n.º 7
0
        /// <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"));
        }
Exemplo n.º 8
0
        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());
        }
Exemplo n.º 9
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}"));
        }
Exemplo n.º 10
0
 public void NotifyClientsChange()
 {
     PlanetHub.NotifyCategoryChange(this);
 }
Exemplo n.º 11
0
        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;
            }
            }
        }