public bool Update(int idUser, EmailConfirmCode emailConfirmCode)
        {
            string[] attributes = { "code:string", "status:bool" };
            bool     result     = UpdateEntity(emailConfirmCode, "id_users", idUser.ToString(), attributes);

            Close();
            return(result);
        }
        public int Create(EmailConfirmCode emailConfirmCode)
        {
            string[] attributes = { "code:string", "id_users:int" };
            int      id         = CreateEntity(emailConfirmCode, attributes);

            Close();
            return(id);
        }
Пример #3
0
        /// <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!")));
        }
Пример #4
0
        /// <summary>
        /// Verifies the user email
        /// </summary>
        public async Task <TaskResult> VerifyEmail(string code)
        {
            EmailConfirmCode confirmCode = await Context.EmailConfirmCodes.Include(x => x.User).ThenInclude(x => x.Email).FirstOrDefaultAsync(x => x.Code == code);

            if (confirmCode == null)
            {
                return(new TaskResult(false, "Could not find a valid code!"));
            }

            var emailObj = confirmCode.User.Email;

            // At this point the email has been confirmed
            emailObj.Verified = true;

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

            return(new TaskResult(true, "Successfully verified email."));
        }
Пример #5
0
        /// <summary>
        /// Registers a new user and adds them to the database
        /// </summary>
        public async Task <TaskResult> RegisterUser(string username, string email, string password)
        {
            // Ensure unique username
            if (await Context.Users.AnyAsync(x => x.Username.ToLower() == username.ToLower()))
            {
                return(new TaskResult(false, $"Failed: There was already a user named {username}"));
            }

            // Ensure unique email
            if (await Context.Users.AnyAsync(x => x.Email.ToLower() == email.ToLower()))
            {
                return(new TaskResult(false, $"Failed: There was already a user using the email {email}"));
            }

            // Test password complexity
            TaskResult passwordResult = PasswordManager.TestComplexity(password);

            // Enforce password tests
            if (!passwordResult.Success)
            {
                return(passwordResult);
            }

            // At this point the safety checks are complete

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

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

            // Create user object
            User user = new User()
            {
                Username       = username,
                Join_DateTime  = DateTime.UtcNow,
                Email          = email,
                Verified_Email = false
            };

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await Context.Users.AddAsync(user);

                await Context.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                return(new TaskResult(false, $"A critical error occured adding the user."));
            }

            Credential cred = new Credential()
            {
                Credential_Type = CredentialType.PASSWORD,
                Identifier      = email,
                Salt            = salt,
                Secret          = hash,
                User_Id         = user.Id // We need to find what the user's assigned ID is (auto-filled by EF?)
            };

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await Context.Credentials.AddAsync(cred);

                await Context.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                return(new TaskResult(false, $"A critical error occured adding the credentials."));
            }

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

            EmailConfirmCode emailConfirm = new EmailConfirmCode()
            {
                Code    = code,
                User_Id = user.Id
            };

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await Context.EmailConfirmCodes.AddAsync(emailConfirm);

                await Context.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                return(new TaskResult(false, $"A critical error occured adding the email confirmation code."));
            }


            // Send registration email
            string emsg = $@"<body style='background-color:#040D14'>
                              <h2 style='font-family:Helvetica; color:white'>
                                Welcome to Valour!
                              </h2>
                              <p style='font-family:Helvetica; color:white'>
                                To verify your new account, please use this code as your password the first time you log in: 
                              </p>
                              <p style='font-family:Helvetica; color:#88ffff'>
                                {code}
                              </p>
                            </body>";

            string rawmsg = $"Welcome to Valour!\nTo verify your new account, please use this code as your password the first time you log in:\n{code}";

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

            return(new TaskResult(true, $"Successfully created user {username}"));
        }
Пример #6
0
        private static async Task RegisterUser(HttpContext ctx, ValourDB db, string username, string email, string password, string referrer)
        {
            if (username != null)
            {
                username = username.TrimEnd();
            }

            // Prevent duplicates
            if (await db.Users.AnyAsync(x => x.Username.ToLower() == username.ToLower()))
            {
                await BadRequest("Username taken", ctx); return;
            }

            if (await db.UserEmails.AnyAsync(x => x.Email.ToLower() == email.ToLower()))
            {
                await BadRequest("Email taken", ctx); return;
            }

            // Test email
            TaskResult <string> emailResult = User.TestEmail(email);

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

            // This may fix broken email formatting
            email = emailResult.Data;

            // Test username
            TaskResult usernameResult = User.TestUsername(username);

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

            // Test password complexity
            TaskResult passwordResult = User.TestPasswordComplexity(password);

            // Enforce password tests
            if (!passwordResult.Success)
            {
                await BadRequest(passwordResult.Message, ctx); return;
            }


            // Manage referral
            Referral refer = null;

            if (!string.IsNullOrWhiteSpace(referrer))
            {
                User referUser = await db.Users.FirstOrDefaultAsync(x => x.Username.ToLower() == referrer.ToLower());

                if (referUser == null)
                {
                    await BadRequest($"Could not find referrer {referrer}", ctx); return;
                }

                refer = new Referral()
                {
                    Referrer_Id = referUser.Id
                };
            }

            // At this point the safety checks are complete

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

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

            // Create user object
            ServerUser user = new ServerUser()
            {
                Id            = IdManager.Generate(),
                Username      = username,
                Join_DateTime = DateTime.UtcNow,
                Last_Active   = DateTime.UtcNow
            };

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await db.Users.AddAsync(user);

                await db.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                await BadRequest("A critical error occured adding the user.", ctx);

                return;
            }

            // Create email object
            UserEmail emailObj = new UserEmail()
            {
                Email    = email,
                Verified = false,
                User_Id  = user.Id
            };

            try
            {
                // Pray something doesnt break between these
                await db.UserEmails.AddAsync(emailObj);

                await db.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                await BadRequest("A critical error occured adding the email.", ctx);

                return;
            }

            Credential cred = new Credential()
            {
                Credential_Type = CredentialType.PASSWORD,
                Identifier      = email,
                Salt            = salt,
                Secret          = hash,
                User_Id         = user.Id // We need to find what the user's assigned ID is (auto-filled by EF)
            };

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await db.Credentials.AddAsync(cred);

                await db.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                await BadRequest("A critical error occured adding the credentials.", ctx);

                return;
            }

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

            EmailConfirmCode emailConfirm = new EmailConfirmCode()
            {
                Code    = code,
                User_Id = user.Id
            };

            if (refer != null)
            {
                refer.User_Id = user.Id;
                await db.Referrals.AddAsync(refer);

                await db.SaveChangesAsync();
            }

            // An error here would be really bad so we'll be careful and catch any exceptions
            try
            {
                await db.EmailConfirmCodes.AddAsync(emailConfirm);

                await db.SaveChangesAsync();
            }
            catch (System.Exception e)
            {
                Console.WriteLine(e.Message);
                await BadRequest("A critical error occured adding the email confirmation code.", ctx);

                return;
            }

            // Send registration email
            string emsg = $@"<body>
                              <h2 style='font-family:Helvetica;'>
                                Welcome to Valour!
                              </h2>
                              <p style='font-family:Helvetica;>
                                To verify your new account, please use the following link: 
                              </p>
                              <p style='font-family:Helvetica;'>
                                <a href='https://valour.gg/VerifyEmail/{code}'>Verify</a>
                              </p>
                            </body>";

            string rawmsg = $"Welcome to Valour!\nTo verify your new account, please go to the following link:\nhttps://valour.gg/VerifyEmail/{code}";

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

            ctx.Response.StatusCode = 200;
            await ctx.Response.WriteAsync("Success");
        }
Пример #7
0
        /// <summary>
        /// Allows a token to be requested using basic login information
        /// </summary>
        public async Task <TaskResult <string> > RequestStandardToken(string email, string password)
        {
            UserEmail emailObj = await Context.UserEmails.FindAsync(email.ToLower());

            if (emailObj == null)
            {
                return(new TaskResult <string>(false, "There was no user found with that email.", null));
            }

            User user = await emailObj.GetUserAsync();

            if (user.Disabled)
            {
                return(new TaskResult <string>(false, "Your account has been disabled.", null));
            }

            bool authorized = false;

            if (!emailObj.Verified)
            {
                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 TaskResult <string>(false, "The email associated with this account needs to be verified! Please log in using the code " +
                                                   "that was emailed as your password.", null));
                }

                // At this point the email has been confirmed
                emailObj.Verified = true;

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

                authorized = true;
            }
            else
            {
                var result = await UserManager.ValidateAsync(CredentialType.PASSWORD, email, password);

                if (result.Data != null && user.Id != result.Data.Id)
                {
                    return(new TaskResult <string>(false, "A critical error occured. This should not be possible. Seek help immediately.", null));
                }

                if (!result.Success)
                {
                    Console.WriteLine($"Failed password validation for {email}");
                    return(new TaskResult <string>(false, result.Message, null));
                }

                authorized = true;
            }

            // If the verification failed, forward the failure
            if (!authorized)
            {
                return(new TaskResult <string>(false, "Failed to authorize user.", null));
            }

            // Check if there are any tokens already
            AuthToken token = null;

            token = await Context.AuthTokens.FirstOrDefaultAsync(x => x.App_Id == "VALOUR" && x.User_Id == user.Id && x.Scope == Permission.FullControl.Value);

            if (token == null)
            {
                // We now have to create a token for the user
                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();
                }
            }
            else
            {
                token.Time    = DateTime.UtcNow;
                token.Expires = DateTime.UtcNow.AddDays(7);

                using (ValourDB context = new ValourDB(ValourDB.DBOptions))
                {
                    context.AuthTokens.Update(token);
                    await context.SaveChangesAsync();
                }
            }

            return(new TaskResult <string>(true, "Successfully verified and retrieved token!", token.Id));
        }