コード例 #1
0
ファイル: ChannelController.cs プロジェクト: ctr7029/Valour
        public async Task <TaskResult> SetDescription(string description, ulong id, ulong userid, string token)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new TaskResult(false, "Failed to authorize user."));
            }

            PlanetChatChannel channel = await Context.PlanetChatChannels.Where(x => x.Id == id).FirstOrDefaultAsync();

            ServerPlanet planet = await ServerPlanet.FindAsync(channel.Planet_Id, Mapper);

            if (!(await planet.AuthorizedAsync(authToken, PlanetPermissions.ManageChannels)))
            {
                return(new TaskResult(false, "You are not authorized to do this."));
            }

            channel.Description = description;

            await Context.SaveChangesAsync();

            return(new TaskResult(true, "Successfully set description."));
        }
コード例 #2
0
        public async Task <TaskResult> SetName(string name, ulong id, ulong user_id, string token)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != user_id)
            {
                return(new TaskResult(false, "Failed to authorize user."));
            }

            PlanetCategory category = await Context.PlanetCategories.Where(x => x.Id == id).FirstOrDefaultAsync();

            ServerPlanet planet = await ServerPlanet.FindAsync(category.Planet_Id);

            if (!(await planet.AuthorizedAsync(authToken, PlanetPermissions.ManageCategories)))
            {
                return(new TaskResult(false, "You are not authorized to do this."));
            }

            category.Name = name;

            await Context.SaveChangesAsync();

            await PlanetHub.Current.Clients.Group($"p-{category.Planet_Id}").SendAsync("RefreshChannelList", "");

            return(new TaskResult(true, "Successfully set name."));
        }
コード例 #3
0
ファイル: UserController.cs プロジェクト: ctr7029/Valour
        public async Task <TaskResult> KickUser(ulong id, ulong Planet_Id, ulong userid, string token)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new TaskResult(false, "Failed to authorize user."));
            }

            PlanetMember member = await Context.PlanetMembers.Where(x => x.User_Id == id && x.Planet_Id == Planet_Id).FirstOrDefaultAsync();

            if (member == null)
            {
                return(new TaskResult(true, $"Could not find PlanetMember {id}"));
            }

            Context.PlanetMembers.Remove(member);

            await Context.SaveChangesAsync();

            return(new TaskResult(true, $"Successfully kicked user {id}"));
        }
コード例 #4
0
        public async Task <TaskResult> Join(string code, ulong userid, string token)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new TaskResult(false, $"Incorrect token!"));
            }

            PlanetInvite invite = await Context.PlanetInvites.FindAsync(code);

            if (invite == null)
            {
                return(new TaskResult(false, $"Code is not found!"));
            }

            PlanetBan ban = await Context.PlanetBans.FirstOrDefaultAsync(x => x.User_Id == userid && x.Planet_Id == invite.Planet_Id);

            if (ban != null)
            {
                return(new TaskResult(false, $"User is banned from this planet!"));
            }

            PlanetMember mem = await Context.PlanetMembers.FirstOrDefaultAsync(x => x.User_Id == userid && x.Planet_Id == invite.Planet_Id);

            if (mem != null)
            {
                return(new TaskResult(false, $"User is already in this planet!"));
            }

            Planet planet = await Context.Planets.FirstOrDefaultAsync(x => x.Id == invite.Planet_Id);

            if (!planet.Public)
            {
                return(new TaskResult(false, $"Planet is set to private!"));
            }

            PlanetMember member = new PlanetMember()
            {
                User_Id   = userid,
                Planet_Id = invite.Planet_Id,
            };

            await Context.PlanetMembers.AddAsync(member);

            await Context.SaveChangesAsync();

            return(new TaskResult(true, $"Joined Planet"));
        }
コード例 #5
0
ファイル: UserAPI.cs プロジェクト: Coca162/Valour
        private static async Task PasswordReset(HttpContext ctx, ValourDB db, [FromBody] string email)
        {
            UserEmail userEmail = await db.UserEmails.FindAsync(email.ToLower());

            if (userEmail == null)
            {
                await NotFound("No account found for email", ctx); return;
            }

            // If a recovery already exists for this user, remove it
            var old = db.PasswordRecoveries.Where(x => x.User_Id == userEmail.User_Id);

            if (old.Count() > 0)
            {
                db.PasswordRecoveries.RemoveRange(old);
                await db.SaveChangesAsync();
            }

            string recoveryCode = Guid.NewGuid().ToString();

            PasswordRecovery recovery = new PasswordRecovery()
            {
                Code    = recoveryCode,
                User_Id = userEmail.User_Id
            };

            await db.PasswordRecoveries.AddAsync(recovery);

            await db.SaveChangesAsync();

            // Send registration email
            string emsg = $@"<body>
                              <h2 style='font-family:Helvetica;'>
                                Valour Password Recovery
                              </h2>
                              <p style='font-family:Helvetica;>
                                If you did not request this email, please ignore it.
                                To reset your password, please use the following link: 
                              </p>
                              <p style='font-family:Helvetica;'>
                                <a href='https://valour.gg/RecoverPassword/{recoveryCode}'>Click here to recover</a>
                              </p>
                            </body>";

            string rawmsg = $"To reset your password, please go to the following link:\nhttps://valour.gg/RecoverPassword/{recoveryCode}";

            await EmailManager.SendEmailAsync(email, "Valour Password Recovery", rawmsg, emsg);

            Console.WriteLine($"Sent recovery email to {email}");

            ctx.Response.StatusCode = 200;
            await ctx.Response.WriteAsync("Email sent");
        }
コード例 #6
0
ファイル: ServerPlanet.cs プロジェクト: Coca162/Valour
        /// <summary>
        /// Adds a member to the server
        /// </summary>
        public async Task AddMemberAsync(User user, ValourDB db)
        {
            // Already a member
            if (await db.PlanetMembers.AnyAsync(x => x.User_Id == user.Id && x.Planet_Id == Id))
            {
                return;
            }

            ServerPlanetMember member = new ServerPlanetMember()
            {
                Id        = IdManager.Generate(),
                Nickname  = user.Username,
                Planet_Id = Id,
                User_Id   = user.Id
            };

            // Add to default planet role
            ServerPlanetRoleMember rolemember = new ServerPlanetRoleMember()
            {
                Id        = IdManager.Generate(),
                Planet_Id = Id,
                User_Id   = user.Id,
                Role_Id   = Default_Role_Id,
                Member_Id = member.Id
            };

            await db.PlanetMembers.AddAsync(member);

            await db.PlanetRoleMembers.AddAsync(rolemember);

            await db.SaveChangesAsync();

            Console.WriteLine($"User {user.Username} ({user.Id}) has joined {Name} ({Id})");
        }
コード例 #7
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                Task task = Task.Run(async() =>
                {
                    //try
                    //{

                    Context = new ValourDB(ValourDB.DBOptions);

                    if (Context != null && System.Diagnostics.Debugger.IsAttached == false)
                    {
                        stats.Time              = DateTime.UtcNow;
                        stats.userCount         = Context.Users.Count();
                        stats.planetCount       = Context.Planets.Count();
                        stats.planetmemberCount = Context.PlanetMembers.Count();
                        stats.channelCount      = Context.PlanetChatChannels.Count();
                        stats.categoryCount     = Context.PlanetCategories.Count();
                        await Context.Stats.AddAsync(stats);
                        await Context.SaveChangesAsync();
                        stats = new StatObject();
                        _logger.LogInformation($"Saved successfully.");
                    }
                });
                while (!task.IsCompleted)
                {
                    _logger.LogInformation($"Stat Worker running at: {DateTimeOffset.Now}");
                    await Task.Delay(60000, stoppingToken);
                }

                _logger.LogInformation("Stat Worker task stopped at: {time}", DateTimeOffset.Now);
                _logger.LogInformation("Restarting.", DateTimeOffset.Now);
            }
        }
コード例 #8
0
        /// <summary>
        /// Sets the parent of this channel
        /// </summary>
        public async Task SetParentAsync(ulong parent_id, ValourDB db)
        {
            this.Parent_Id = parent_id;
            db.PlanetChatChannels.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();
        }
コード例 #9
0
        /// <summary>
        /// Sets the permissions inherit mode of this channel
        /// </summary>
        public async Task SetInheritsPermsAsync(bool inherits_perms, ValourDB db)
        {
            this.Inherits_Perms = inherits_perms;
            db.PlanetChatChannels.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();
        }
コード例 #10
0
        /// <summary>
        /// Sets the description of this channel
        /// </summary>
        public async Task SetDescriptionAsync(string desc, ValourDB db)
        {
            this.Description = desc;
            db.PlanetChatChannels.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();
        }
コード例 #11
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);
    }
コード例 #12
0
ファイル: ServerPlanet.cs プロジェクト: Coca162/Valour
        /// <summary>
        /// Tries to set the planet description
        /// </summary>
        public async Task <TaskResult> TrySetDescriptionAsync(string desc, ValourDB db)
        {
            this.Description = desc;

            db.Planets.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();

            return(new TaskResult(true, "Success"));
        }
コード例 #13
0
ファイル: ServerPlanet.cs プロジェクト: Coca162/Valour
        /// <summary>
        /// Tries to set the planet open state
        /// </summary>
        public async Task <TaskResult> TrySetPublicAsync(bool pub, ValourDB db)
        {
            this.Public = pub;

            db.Planets.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();

            return(new TaskResult(true, "Success"));
        }
コード例 #14
0
        /// <summary>
        /// Creates a server and if successful returns a task result with the created
        /// planet's id
        /// </summary>
        public async Task <TaskResult <ulong> > CreateChannel(string name, ulong userid, ulong planetid, string token)
        {
            TaskResult nameValid = ValidateName(name);

            if (!nameValid.Success)
            {
                return(new TaskResult <ulong>(false, nameValid.Message, 0));
            }

            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new TaskResult <ulong>(false, "Failed to authorize user.", 0));
            }

            // User is verified and given channel info is valid by this point

            // Creates the channel channel

            PlanetChatChannel channel = new PlanetChatChannel()
            {
                Name          = name,
                Planet_Id     = planetid,
                Message_Count = 0
            };

            // Add channel to database
            await Context.PlanetChatChannels.AddAsync(channel);

            // Save changes to DB
            await Context.SaveChangesAsync();

            // Return success
            return(new TaskResult <ulong>(true, "Successfully created channel.", channel.Id));
        }
コード例 #15
0
ファイル: UserController.cs プロジェクト: lixsady/Valour
        /// <summary>
        /// Allows a token to be requested using basic login information
        /// </summary>
        public async Task <TokenResponse> RequestStandardToken(string email, string password)
        {
            var result = await UserManager.ValidateAsync(CredentialType.PASSWORD, email, password);

            // If the verification failed, forward the failure
            if (!result.Result.Success)
            {
                return(new TokenResponse(null, result.Result));
            }

            // Otherwise, get the user we just verified
            User user = result.User;

            if (!user.Verified_Email)
            {
                EmailConfirmCode confirmCode = await Context.EmailConfirmCodes.FindAsync(password);

                // Someone using another person's verification is a little
                // worrying, and we don't want them to know it worked, so we'll
                // send the same error either way.
                if (confirmCode == null || confirmCode.User_Id != user.Id)
                {
                    return(new TokenResponse(null, new TaskResult(false, "The email associated with this account needs to be verified! Please log in using the code " +
                                                                  "that was emailed as your password.")));
                }

                // At this point the email has been confirmed
                user.Verified_Email = true;

                Context.EmailConfirmCodes.Remove(confirmCode);
                await Context.SaveChangesAsync();
            }

            // We now have to create a token for the user
            AuthToken token = new AuthToken()
            {
                App_Id  = "VALOUR",
                Id      = Guid.NewGuid().ToString(),
                Time    = DateTime.UtcNow,
                Expires = DateTime.UtcNow.AddDays(7),
                Scope   = Permission.FullControl.Value,
                User_Id = user.Id
            };

            using (ValourDB context = new ValourDB(ValourDB.DBOptions))
            {
                await context.AuthTokens.AddAsync(token);

                await context.SaveChangesAsync();
            }

            return(new TokenResponse(token.Id, new TaskResult(true, "Successfully verified and retrieved token!")));
        }
コード例 #16
0
        public async Task <LocalRedirectResult> Join(string code, ulong userid, string token)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new LocalRedirectResult("/"));
            }

            PlanetInvite invite = await Context.PlanetInvites.Where(x => x.Code == code).FirstOrDefaultAsync();

            if (invite == null)
            {
                return(new LocalRedirectResult("/"));
            }

            PlanetMember mem = await Context.PlanetMembers.Where(x => x.User_Id == userid && x.Planet_Id == invite.Planet_Id).FirstOrDefaultAsync();

            if (mem != null)
            {
                return(new LocalRedirectResult("/"));
            }

            PlanetMember member = new PlanetMember()
            {
                User_Id   = userid,
                Planet_Id = invite.Planet_Id,
            };

            await Context.PlanetMembers.AddAsync(member);

            await Context.SaveChangesAsync();

            return(new LocalRedirectResult("/"));
        }
コード例 #17
0
        public async Task <TaskResult <PlanetInvite> > GetInvite(string code, ulong user_id)
        {
            PlanetInvite invite = await Context.PlanetInvites.FirstOrDefaultAsync(x => x.Code == code);


            if (invite.IsPermanent() == false)
            {
                if (DateTime.UtcNow > invite.Time.AddMinutes((double)invite.Hours))
                {
                    Context.PlanetInvites.Remove(invite);

                    await Context.SaveChangesAsync();

                    return(new TaskResult <PlanetInvite>(false, $"Invite is expired", null));
                }
            }

            PlanetBan ban = await Context.PlanetBans.FirstOrDefaultAsync(x => x.User_Id == user_id && x.Planet_Id == invite.Planet_Id);

            if (ban != null)
            {
                return(new TaskResult <PlanetInvite>(false, $"User is banned from this planet!", null));
            }

            PlanetMember member = await Context.PlanetMembers.FirstOrDefaultAsync(x => x.User_Id == user_id && x.Planet_Id == invite.Planet_Id);

            if (member != null)
            {
                return(new TaskResult <PlanetInvite>(false, $"User is already in this planet!", null));
            }

            Planet planet = await Context.Planets.FirstOrDefaultAsync(x => x.Id == invite.Planet_Id);

            if (!planet.Public)
            {
                return(new TaskResult <PlanetInvite>(false, $"Planet is set to private!", null));
            }

            return(new TaskResult <PlanetInvite>(true, $"Successfully got invite", invite));
        }
コード例 #18
0
ファイル: ServerPlanetRole.cs プロジェクト: Coca162/Valour
        /// <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));
        }
コード例 #19
0
ファイル: UserAPI.cs プロジェクト: Coca162/Valour
        private static async Task RecoverPassword(HttpContext ctx, ValourDB db, [FromBody] PasswordRecoveryRequest request)
        {
            if (request == null)
            {
                await BadRequest("Include request data in body", ctx); return;
            }

            PasswordRecovery recovery = await db.PasswordRecoveries.FindAsync(request.Code);

            if (recovery == null)
            {
                await NotFound("Recovery request not found", ctx); return;
            }

            TaskResult passwordValid = User.TestPasswordComplexity(request.Password);

            if (!passwordValid.Success)
            {
                await BadRequest(passwordValid.Message, ctx); return;
            }

            // Get user's old credentials
            Credential credential = await db.Credentials.FirstOrDefaultAsync(x => x.User_Id == recovery.User_Id && x.Credential_Type == CredentialType.PASSWORD);

            if (credential == null)
            {
                await NotFound("No password-type credentials found. Do you log in via third party service?", ctx); return;
            }

            // Remove recovery code
            db.PasswordRecoveries.Remove(recovery);

            // Modify old credentials

            // Generate salt
            byte[] salt = new byte[32];
            PasswordManager.GenerateSalt(salt);

            // Generate password hash
            byte[] hash = PasswordManager.GetHashForPassword(request.Password, salt);

            credential.Salt   = salt;
            credential.Secret = hash;

            db.Credentials.Update(credential);
            await db.SaveChangesAsync();

            ctx.Response.StatusCode = 200;
            await ctx.Response.WriteAsync("Success");
        }
コード例 #20
0
ファイル: ServerPlanet.cs プロジェクト: Coca162/Valour
        public async Task <TaskResult <int> > TryKickMemberAsync(ServerPlanetMember member,
                                                                 ServerPlanetMember target, ValourDB db)
        {
            if (member == null)
            {
                return(new TaskResult <int>(false, "Member not found", 404));
            }

            if (!await HasPermissionAsync(member, PlanetPermissions.Kick, db))
            {
                return(new TaskResult <int>(false, "Member lacks PlanetPermissions.View", 403));
            }

            if (target == null)
            {
                return(new TaskResult <int>(false, $"Target not found", 404));
            }

            if (member.Id == target.Id)
            {
                return(new TaskResult <int>(false, "You cannot kick yourself!", 400));
            }

            if (!await HasPermissionAsync(member, PlanetPermissions.Kick, db))
            {
                return(new TaskResult <int>(false, "Member lacks PlanetPermissions.Kick", 403));
            }

            if (await member.GetAuthorityAsync() <= await target.GetAuthorityAsync())
            {
                return(new TaskResult <int>(false, "You can only kick members with lower authority!", 403));
            }

            // Remove roles
            var roles = db.PlanetRoleMembers.Where(x => x.Member_Id == target.Id);

            foreach (ServerPlanetRoleMember role in roles)
            {
                db.PlanetRoleMembers.Remove(role);
            }

            // Remove member
            db.PlanetMembers.Remove(target);

            // Save changes
            await db.SaveChangesAsync();

            return(new TaskResult <int>(true, $"Successfully kicked user", 200));
        }
コード例 #21
0
ファイル: UserAPI.cs プロジェクト: Coca162/Valour
        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");
        }
コード例 #22
0
ファイル: PlanetController.cs プロジェクト: ctr7029/Valour
        public async Task <TaskResult> BanUser(ulong id, ulong Planet_Id, string reason, ulong userid, string token, uint time)
        {
            AuthToken authToken = await Context.AuthTokens.FindAsync(token);

            // Return the same if the token is for the wrong user to prevent someone
            // from knowing if they cracked another user's token. This is basically
            // impossible to happen by chance but better safe than sorry in the case that
            // the literal impossible odds occur, more likely someone gets a stolen token
            // but is not aware of the owner but I'll shut up now - Spike
            if (authToken == null || authToken.User_Id != userid)
            {
                return(new TaskResult(false, "Failed to authorize user."));
            }

            ServerPlanet planet = await ServerPlanet.FindAsync(Planet_Id, Mapper);

            if (!(await planet.AuthorizedAsync(authToken, PlanetPermissions.Ban)))
            {
                return(new TaskResult(false, "You are not authorized to do this."));
            }

            PlanetBan ban = new PlanetBan()
            {
                Reason    = reason,
                Planet_Id = Planet_Id,
                User_Id   = id,
                Banner_Id = userid,
                Time      = DateTime.UtcNow,
                Permanent = false
            };

            if (time <= 0)
            {
                ban.Permanent = true;
            }
            else
            {
                ban.Minutes = time;
            }

            // Add channel to database
            await Context.PlanetBans.AddAsync(ban);

            PlanetMember member = await Context.PlanetMembers.Where(x => x.User_Id == id).FirstOrDefaultAsync();

            Context.PlanetMembers.Remove(member);
            await Context.SaveChangesAsync();

            return(new TaskResult(true, $"Successfully banned user {id}"));
        }
コード例 #23
0
        /// <summary>
        /// Deletes this channel
        /// </summary>
        public async Task <TaskResult <int> > TryDeleteAsync(ServerPlanetMember member, ValourDB db)
        {
            Planet ??= await GetPlanetAsync(db);

            if (Id == Planet.Main_Channel_Id)
            {
                return(new TaskResult <int>(false, $"Cannot delete main channel", 400));
            }

            if (member == null)
            {
                return(new TaskResult <int>(false, "Member not found", 403));
            }

            if (!await HasPermission(member, ChatChannelPermissions.View, db))
            {
                return(new TaskResult <int>(false, "Member lacks ChatChannelPermissions.View", 403));
            }

            if (!await HasPermission(member, ChatChannelPermissions.ManageChannel, db))
            {
                return(new TaskResult <int>(false, "Member lacks ChatChannelPermissions.ManageChannel", 403));
            }

            // Remove permission nodes
            db.ChatChannelPermissionsNodes.RemoveRange(
                db.ChatChannelPermissionsNodes.Where(x => x.Channel_Id == Id)
                );

            // Remove messages
            db.PlanetMessages.RemoveRange(
                db.PlanetMessages.Where(x => x.Channel_Id == Id)
                );

            // Remove channel
            db.PlanetChatChannels.Remove(
                await db.PlanetChatChannels.FirstOrDefaultAsync(x => x.Id == Id)
                );

            // Save changes
            await db.SaveChangesAsync();

            // Notify channel deletion
            await PlanetHub.NotifyChatChannelDeletion(this);

            return(new TaskResult <int>(true, "Success", 200));
        }
コード例 #24
0
        /// <summary>
        /// Sets the name of this channel
        /// </summary>
        public async Task <TaskResult> TrySetNameAsync(string name, ValourDB db)
        {
            TaskResult validName = ValidateName(name);

            if (!validName.Success)
            {
                return(validName);
            }

            this.Name = name;
            db.PlanetChatChannels.Update(this);
            await db.SaveChangesAsync();

            NotifyClientsChange();

            return(new TaskResult(true, "Success"));
        }
コード例 #25
0
ファイル: RoleAPI.cs プロジェクト: Coca162/Valour
        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;
        }
コード例 #26
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);
    }
コード例 #27
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                Task task = Task.Run(async() =>
                {
                    while (true)
                    {
                        try
                        {
                            using (var scope = _scopeFactory.CreateScope())
                            {
                                ValourDB context = scope.ServiceProvider.GetRequiredService <ValourDB>();
                                DateTime now     = DateTime.UtcNow;
                                foreach (Messaging.CacheMessage message in context.Messages)
                                {
                                    if (message.TimeSent.AddHours(24) < now)
                                    {
                                        context.Messages.Remove(message);
                                    }
                                    await context.SaveChangesAsync();
                                }
                            }
                            Console.WriteLine("Checked Message Cache");
                            Thread.Sleep(1000 * 60 * 60);
                        }
                        catch (System.Exception e)
                        {
                            Console.WriteLine("FATAL MESSAGE CACHE ERROR:");
                            Console.WriteLine(e.Message);
                        }
                    }
                });

                while (!task.IsCompleted)
                {
                    _logger.LogInformation("Message Cache Worker running at: {time}", DateTimeOffset.Now);
                    await Task.Delay(60000, stoppingToken);
                }

                _logger.LogInformation("Message Cache Worker task stopped at: {time}", DateTimeOffset.Now);
                _logger.LogInformation("Restarting.", DateTimeOffset.Now);
            }
        }
コード例 #28
0
ファイル: ServerAuthToken.cs プロジェクト: Coca162/Valour
        /// <summary>
        /// Will return the auth object for a valid token, including the user.
        /// This will log the access time in the user object.
        /// A null response means the token was invalid.
        /// </summary>
        public static async Task <ServerAuthToken> TryAuthorize(string token, ValourDB db)
        {
            if (token == null)
            {
                return(null);
            }

            ServerAuthToken authToken = null;

            if (QuickCache.ContainsKey(token))
            {
                authToken = QuickCache[token];
            }
            else
            {
                authToken = await db.AuthTokens.FindAsync(token);

                QuickCache.TryAdd(token, authToken);
            }

            // Spin off a task to do things we don't want to wait on
            var t = Task.Run(async() =>
            {
                using (ValourDB tdb = new ValourDB(ValourDB.DBOptions))
                {
                    if (authToken == null)
                    {
                        authToken = await tdb.AuthTokens.FindAsync(token);
                    }

                    if (authToken != null)
                    {
                        ServerUser user  = await tdb.Users.FindAsync(authToken.User_Id);
                        user.Last_Active = DateTime.UtcNow;

                        await tdb.SaveChangesAsync();
                    }
                }
            });


            return(authToken);
        }
コード例 #29
0
ファイル: ServerPlanetRole.cs プロジェクト: Coca162/Valour
        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));
        }
コード例 #30
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"));
        }