Inheritance: INotifyPropertyChanging, INotifyPropertyChanged
Example #1
0
        /// <summary>
        /// Create a pending user in the DB.
        /// 
        /// Returns the authCode and token necessary to complete registration via e-mail.
        /// 
        /// If an error occurs, returns false and sets a user displayable message in `error`.
        /// </summary>
        public static bool CreatePendingUser(string email, string password, string realname, out string token, out string authCode, out string error)
        {
            if (Models.User.FindUserByEmail(email) != null)
            {
                token = null;
                authCode = null;
                error = "Email already in use.";
                return false;
            }

            var db = Current.WriteDB;

            string pwSalt;
            string pwHash = Current.SecureHash(password, out pwSalt);

            token = Current.UniqueId().ToString();
            authCode = Current.MakeAuthCode(new { email, token, realname });

            var pendingUser = new PendingUser
            {
                AuthCode = authCode,
                CreationDate = Current.Now,
                PasswordHash = pwHash,
                PasswordSalt = pwSalt
            };

            db.PendingUsers.InsertOnSubmit(pendingUser);
            db.SubmitChanges();

            error = null;
            return true;
        }
Example #2
0
        /// <summary>
        /// Create a pending user in the DB.
        ///
        /// Returns the authCode and token necessary to complete registration via e-mail.
        ///
        /// If an error occurs, returns false and sets a user displayable message in `error`.
        /// </summary>
        public static bool CreatePendingUser(string email, string password, string realname, out string token, out string authCode, out string error)
        {
            if (Models.User.FindUserByEmail(email) != null)
            {
                token    = null;
                authCode = null;
                error    = "Email already in use.";
                return(false);
            }

            var db = Current.WriteDB;

            string pwSalt;
            string pwHash = Current.SecureHash(password, out pwSalt);

            token    = Current.UniqueId().ToString();
            authCode = Current.MakeAuthCode(new { email, token, realname });

            var pendingUser = new PendingUser
            {
                AuthCode     = authCode,
                CreationDate = Current.Now,
                PasswordHash = pwHash,
                PasswordSalt = pwSalt
            };

            db.PendingUsers.InsertOnSubmit(pendingUser);
            db.SubmitChanges();

            error = null;
            return(true);
        }
Example #3
0
 partial void DeletePendingUser(PendingUser instance);
Example #4
0
 partial void UpdatePendingUser(PendingUser instance);
Example #5
0
 partial void InsertPendingUser(PendingUser instance);
Example #6
0
        /// <summary>
        /// Create a new account given an email and password
        /// </summary>
        public static bool CreateAccount(string email, PendingUser pendingUser, DateTime now, string vanity, string realname, out User created, out string errorMessage)
        {
            email = email.ToLowerInvariant();

            if (vanity.HasValue() && !Models.User.IsValidVanityId(vanity, out errorMessage))
            {
                created = null;

                return(false);
            }

            var db = Current.WriteDB;

            // Quick check to make sure the vanity id is not in use elsewhere
            if (vanity.HasValue() && db.Users.Any(u => u.VanityProviderId == vanity))
            {
                created      = null;
                errorMessage = "That Vanity OpenId is already in use";

                return(false);
            }

            var provider = Current.UniqueId();

            // Odds of colision are miniscule, but might as well check
            while (db.Users.Any(u => u.ProviderId == provider))
            {
                provider = Current.UniqueId();
            }

            // We need to compute these way before we use them for some length checks
            byte   emailVersion;
            string emailIV, emailHMAC;
            var    emailEncrypted = Current.Encrypt(email, out emailIV, out emailVersion, out emailHMAC);

            byte   nameVersion = 0xFF;
            string nameEncrypted = null, nameIV = null, nameHMAC = null;

            if (realname.HasValue())
            {
                nameEncrypted = Current.Encrypt(realname, out nameIV, out nameVersion, out nameHMAC);
            }

            if (emailEncrypted.Length > 267)
            {
                created      = null;
                errorMessage = "Email is too long";

                return(false);
            }

            if (nameEncrypted.HasValue() && nameEncrypted.Length > 267)
            {
                created      = null;
                errorMessage = "Name is too long";

                return(false);
            }

            string emailHash;
            byte   emailSaltVersion;

            emailHash = Current.SystemHash(email, out emailSaltVersion);

            var newUser =
                new User
            {
                LastActivityDate = DateTime.UtcNow,
                EmailHash        = emailHash,
                EmailSaltVersion = emailSaltVersion,
                ProviderId       = provider,
                PasswordHash     = pendingUser.PasswordHash,
                PasswordSalt     = pendingUser.PasswordSalt,
                CreationDate     = now,
                VanityProviderId = vanity,
                UserTypeId       = Models.UserTypeId.Normal
            };

            try
            {
                db.Users.InsertOnSubmit(newUser);
                db.SubmitChanges();
            }
            catch (Exception e)
            {
                // Hack: There isn't really a nice way to detect a unique constraint conflict,
                //       so... check the message.  Checking for the constraint name so this isn't
                //       *guaranteed* to break on non-English language systems... still not guaranteed
                //       to work though.
                if (e is System.Data.SqlClient.SqlException && e.Message.Contains("Users_EmailHash_EmailSaltVersion"))
                {
                    created      = null;
                    errorMessage = "Email address already registered.";
                    return(false);
                }

                Current.LogException(e);
                created      = null;
                errorMessage = "User account could not be created.";
                return(false);
            }

            // Open season on this user until the context is torn down.
            db.LiftUserRestrictionsOnId = newUser.Id;

            // Can't put a unique constrain on VanityProviderId (as its normally null), so
            //    this is a hack to make sure no two users end up slipping in and getting the
            //    same vanity id.
            if (vanity.HasValue() && db.Users.Count(u => u.VanityProviderId == vanity) != 1)
            {
                newUser.VanityProviderId = null;
                db.SubmitChanges();
            }

            var emailAttr =
                new UserAttribute
            {
                UserId              = newUser.Id,
                CreationDate        = now,
                UserAttributeTypeId = UserAttributeTypeId.Email,
                Encrypted           = emailEncrypted,
                IV         = emailIV,
                KeyVersion = emailVersion,
                HMAC       = emailHMAC
            };

            db.UserAttributes.InsertOnSubmit(emailAttr);
            db.SubmitChanges();

            if (realname.HasValue())
            {
                var nameAttr =
                    new UserAttribute
                {
                    UserId              = newUser.Id,
                    CreationDate        = now,
                    UserAttributeTypeId = UserAttributeTypeId.RealName,
                    Encrypted           = nameEncrypted,
                    IV         = nameIV,
                    KeyVersion = nameVersion,
                    HMAC       = nameHMAC
                };

                db.UserAttributes.InsertOnSubmit(nameAttr);
                db.SubmitChanges();
            }

            created      = newUser;
            errorMessage = null;

            return(true);
        }
Example #7
0
        /// <summary>
        /// Create a new account given an email and password
        /// </summary>
        public static bool CreateAccount(string email, PendingUser pendingUser, DateTime now, string vanity, string realname, out User created, out string errorMessage)
        {
            email = email.ToLowerInvariant();

            if (vanity.HasValue() && !Models.User.IsValidVanityId(vanity, out errorMessage))
            {
                created = null;

                return false;
            }

            var db = Current.WriteDB;

            // Quick check to make sure the vanity id is not in use elsewhere
            if (vanity.HasValue() && db.Users.Any(u => u.VanityProviderId == vanity))
            {
                created = null;
                errorMessage = "That Vanity OpenId is already in use";

                return false;
            }

            var provider = Current.UniqueId();

            // Odds of colision are miniscule, but might as well check
            while (db.Users.Any(u => u.ProviderId == provider))
                provider = Current.UniqueId();

            // We need to compute these way before we use them for some length checks
            byte emailVersion;
            string emailIV, emailHMAC;
            var emailEncrypted = Current.Encrypt(email, out emailIV, out emailVersion, out emailHMAC);

            byte nameVersion = 0xFF;
            string nameEncrypted= null, nameIV = null, nameHMAC = null;

            if (realname.HasValue())
            {
                nameEncrypted = Current.Encrypt(realname, out nameIV, out nameVersion, out nameHMAC);
            }

            if (emailEncrypted.Length > 267)
            {
                created = null;
                errorMessage = "Email is too long";

                return false;
            }

            if (nameEncrypted.HasValue() && nameEncrypted.Length > 267)
            {
                created = null;
                errorMessage = "Name is too long";

                return false;
            }

            string emailHash;
            byte emailSaltVersion;
            emailHash = Current.SystemHash(email, out emailSaltVersion);

            var newUser =
                new User
                {
                    LastActivityDate = DateTime.UtcNow,
                    EmailHash = emailHash,
                    EmailSaltVersion = emailSaltVersion,
                    ProviderId = provider,
                    PasswordHash = pendingUser.PasswordHash,
                    PasswordSalt = pendingUser.PasswordSalt,
                    CreationDate = now,
                    VanityProviderId = vanity,
                    UserTypeId = Models.UserTypeId.Normal
                };

            try
            {
                db.Users.InsertOnSubmit(newUser);
                db.SubmitChanges();
            }
            catch (Exception e)
            {
                // Hack: There isn't really a nice way to detect a unique constraint conflict,
                //       so... check the message.  Checking for the constraint name so this isn't
                //       *guaranteed* to break on non-English language systems... still not guaranteed
                //       to work though.
                if(e is System.Data.SqlClient.SqlException && e.Message.Contains("Users_EmailHash_EmailSaltVersion"))
                {
                    created = null;
                    errorMessage = "Email address already registered.";
                    return false;
                }

                Current.LogException(e);
                created = null;
                errorMessage = "User account could not be created.";
                return false;
            }

            // Open season on this user until the context is torn down.
            db.LiftUserRestrictionsOnId = newUser.Id;

            // Can't put a unique constrain on VanityProviderId (as its normally null), so
            //    this is a hack to make sure no two users end up slipping in and getting the 
            //    same vanity id.
            if (vanity.HasValue() && db.Users.Count(u => u.VanityProviderId == vanity) != 1)
            {
                newUser.VanityProviderId = null;
                db.SubmitChanges();
            }

            var emailAttr =
                new UserAttribute
                {
                    UserId = newUser.Id,
                    CreationDate = now,
                    UserAttributeTypeId = UserAttributeTypeId.Email,
                    Encrypted = emailEncrypted,
                    IV = emailIV,
                    KeyVersion = emailVersion,
                    HMAC = emailHMAC
                };

            db.UserAttributes.InsertOnSubmit(emailAttr);
            db.SubmitChanges();

            if (realname.HasValue())
            {
                var nameAttr =
                    new UserAttribute
                    {
                        UserId = newUser.Id,
                        CreationDate = now,
                        UserAttributeTypeId = UserAttributeTypeId.RealName,
                        Encrypted = nameEncrypted,
                        IV = nameIV,
                        KeyVersion = nameVersion,
                        HMAC = nameHMAC
                    };

                db.UserAttributes.InsertOnSubmit(nameAttr);
                db.SubmitChanges();
            }

            created = newUser;
            errorMessage = null;

            return true;
        }
Example #8
0
        public void PendingUserUpdateDeletionDate()
        {
            var r = new Restrictions();

            var pending = new PendingUser
            {
                Id = 1,
                DeletionDate = DateTime.Now
            };

            var updates = new Dictionary<object, Restrictions.ShadowModifiedMember[]>();
            updates[pending] = new Restrictions.ShadowModifiedMember[]
                {
                    new Restrictions.ShadowModifiedMember
                    {
                        Member = typeof(PendingUser).GetProperty("DeletionDate"),
                        CurrentValue = pending.DeletionDate,
                        OriginalValue = null
                    }
                };

            string ignored;
            Assert.IsTrue(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>() { pending }, new List<int>(), out ignored));
        }
Example #9
0
        public void NoPendingUserUpdateOnNonDeletionDate()
        {
            var r = new Restrictions();

            var pending = new PendingUser
            {
                Id = 1
            };

            var updates = new Dictionary<object, Restrictions.ShadowModifiedMember[]>();
            updates[pending] = new Restrictions.ShadowModifiedMember[]
                {
                    new Restrictions.ShadowModifiedMember
                    {
                        Member = typeof(PendingUser).GetProperty("Id"),
                        CurrentValue = pending.Id,
                        OriginalValue = 2
                    }
                };

            string ignored;
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>(){pending}, new List<int>(), out ignored));
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>(), new List<object>(){pending}, new List<int>() { 1 }, out ignored));
        }
Example #10
0
        public void NoPendingUserInsert()
        {
            var r = new Restrictions();

            var pending = new PendingUser
            {
                Id = 1
            };

            var updates = new Dictionary<object, Restrictions.ShadowModifiedMember[]>();

            string ignored;
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>() { pending }, new List<object>(), new List<int>(), out ignored));
            Assert.IsFalse(r.IsValidChangeSet(updates, new List<object>(), new List<object>() { pending }, new List<object>(), new List<int>() { 1 }, out ignored));
        }