Exemplo n.º 1
0
        /// <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));
        }
Exemplo 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;
            }
            }
        }
Exemplo n.º 3
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.º 4
0
        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);
        }
Exemplo n.º 5
0
        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);
        }
Exemplo n.º 6
0
        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;
        }
Exemplo n.º 7
0
        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));
        }
Exemplo n.º 8
0
        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;
        }
Exemplo n.º 9
0
    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);
    }
Exemplo n.º 10
0
        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);
        }
Exemplo n.º 11
0
        /// <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."));
        }
Exemplo n.º 12
0
        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;
        }
Exemplo n.º 13
0
        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");
        }
Exemplo n.º 14
0
        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);
        }
Exemplo n.º 15
0
        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);
        }
Exemplo n.º 16
0
    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);
    }
Exemplo n.º 17
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;
        }
Exemplo n.º 18
0
    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");
    }
Exemplo n.º 19
0
    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);
    }
Exemplo n.º 20
0
        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);
        }
Exemplo n.º 21
0
    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);
    }
Exemplo n.º 22
0
        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}");
        }
Exemplo n.º 23
0
        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;
        }
Exemplo n.º 24
0
        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;
        }
Exemplo n.º 25
0
        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;
        }
Exemplo n.º 26
0
        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;
            }
            }
        }
Exemplo n.º 27
0
        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;
            }
            }
        }
Exemplo n.º 28
0
        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);
        }
Exemplo n.º 29
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.º 30
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);
        }