示例#1
0
    /// <summary>
    /// Request an autologin using the values from the HttpRequest if
    /// is need.
    /// </summary>
    public static void RequestAutologin(HttpRequest Request)
    {
        // First, check standard 'Authorization' header
        var auth = Request.Headers["Authorization"];

        if (!String.IsNullOrEmpty(auth))
        {
            var m = System.Text.RegularExpressions.Regex.Match(auth, "^LC alu=([^,]+),alk=(.+)$");
            if (m.Success)
            {
                var alu = m.Groups[1].Value;
                var alk = m.Groups[2].Value;
                LcAuth.Autologin(alu, alk);
            }
        }
        else
        {
            // Using custom headers first, best for security using the REST API.
            var Q   = Request.QueryString;
            var alk = N.DW(Request.Headers["alk"]) ?? Q["alk"];
            var alu = N.DW(Request.Headers["alu"]) ?? Q["alu"];

            // Autologin feature for anonymous sessions with autologin parameters on request
            if (!Request.IsAuthenticated &&
                alk != null &&
                alu != null)
            {
                // 'alk' url parameter stands for 'Auto Login Key'
                // 'alu' url parameter stands for 'Auto Login UserID'
                LcAuth.Autologin(alu, alk);
            }
        }
    }
示例#2
0
 public static void Logout()
 {
     LcAuth.RemovesCurrentUserAuthorization();
     // Log out of the current user context
     WebSecurity.Logout();
     Session.Clear();
 }
示例#3
0
    public static void checkAccountIsConfirmed(string username)
    {
        // #454: User is auto-logged on registering, allowing it to do the Onboarding,
        // But next times, it is required to confirm email before logged.
        // Since we set IsConfirmed as true on database to let 'auto-logging on register',
        // we must check for the existance of a confirmation token:
        var userId = WebSecurity.GetUserId(username);

        using (var db = new LcDatabase())
        {
            string token = LcAuth.GetConfirmationToken(userId);

            if (userId > -1 && !string.IsNullOrWhiteSpace(token))
            {
                // Resend confirmation mail
                var confirmationUrl = LcUrl.LangUrl + "Account/Confirm/?confirmationCode=" + Uri.EscapeDataString(token ?? "");

                var isProvider = (bool)(db.QueryValue("SELECT IsProvider FROM users WHERE UserID=@0", userId) ?? false);

                if (isProvider)
                {
                    LcMessaging.SendWelcomeProvider(userId, username);
                }
                else
                {
                    LcMessaging.SendWelcomeCustomer(userId, username);
                }

                /// http 409:Conflict
                throw new HttpException(409, "Your account has not yet been confirmed. Please check your inbox and spam folders and click on the e-mail sent.");
            }
        }
    }
示例#4
0
    /// <summary>
    /// Quick signup, just username/email and a password.
    ///
    /// IMPORTANT: It was used in a previous iteration of the project, now the detailed is in use and this lacks some of the latest
    /// additions, like client-confirmationCode code.
    /// </summary>
    /// <param name="page"></param>
    /// <returns></returns>
    public static LoginResult QuickSignup(WebPage page)
    {
        page.Validation.Add("password", new PasswordValidator());
        page.Validation.RequireField("email", "You must specify an email.");
        // Username is an email currently, so need to be restricted
        page.Validation.Add("email",
                            Validator.Regex(LcValidators.EmailAddressRegexPattern, "The email is not valid."));
        page.Validation.RequireField("password", "You must specify a password.");

        if (page.Validation.IsValid())
        {
            var username = Request.Form["email"];
            var password = Request.Form["password"];
            var rememberMe = Request.Form["rememberMe"].AsBool();
            var returnProfile = Request.Form["returnProfile"].AsBool();
            var profileTypeStr = Request.Form["profileType"] ?? "";
            var isProvider = new string[] { "SERVICE-PROFESSIONAL", "FREELANCE", "FREELANCER", "PROVIDER" }.Contains(profileTypeStr.ToUpper());
            var utm = Request.Url.Query;

            // If the user exists, try to log-in with the given password,
            // becoming a provider if that was the requested profileType and follow as
            // a normal login.
            // If the password didn't match, throw a sign-up specific error (email in use)
            // Otherwise, just register the user.
            if (LcAuth.ExistsEmail(username))
            {
                // Try Login
                try
                {
                    var logged = Login(username, password, rememberMe, returnProfile);
                    // throw exception on error
                    if (isProvider)
                    {
                        LcAuth.BecomeProvider(logged.userID);
                    }
                    return(logged);
                }
                catch (HttpException ex)
                {
                    // Not valid log-in, throw a 'email exists' error with Conflict http code
                    throw new HttpException(409, "Email address is already in use.");
                }
            }
            else
            {
                var registered = LcAuth.RegisterUser(username, "", "", password, isProvider, utm);
                LcAuth.SendRegisterUserEmail(registered);
                // Auto login:
                return(Login(username, password, rememberMe, returnProfile, true));
            }
        }
        else
        {
            // Bad request, input data incorrect because of validation rules
            throw new HttpException(400, LcRessources.ValidationSummaryTitle);
        }
    }
示例#5
0
    public static LoginResult FacebookLogin(WebPage page, bool createAccount = false, bool isProvider = false)
    {
        var returnProfile = Request.Form["returnProfile"].AsBool();

        // Get Facebook User using the Request["accessToken"],
        // or signed_request or cookie.
        var fbuser  = LcFacebook.GetUserFromCurrentRequest();
        var fuserid = fbuser != null ? ((string)fbuser["id"] ?? "0").AsLong() : 0;

        if (fuserid > 0)
        {
            // It exists?
            var user = LcAuth.GetFacebookUser(fuserid);
            if (user != null)
            {
                // Become provider
                if (createAccount && isProvider)
                {
                    LcAuth.BecomeProvider(user.UserID);
                    user.IsProvider = true;
                    LcAuth.SendRegisterUserEmail(user);
                }
            }
            else
            {
                if (createAccount)
                {
                    user = CreateFacebookAccount(fbuser, isProvider);
                }
                else
                {
                    throw new HttpException(400, "[[[Incorrect user]]]");
                }
            }

            // Performs system login, using the autologin info since
            // there is no password here.
            var ret = GetLoginResultForID(new LcAuth.UserAuthorization
            {
                userID = user.UserID,
                token  = LcAuth.RegisterAuthorizationForUser(user.UserID)
            }, returnProfile);
            LcAuth.Autologin(ret.userID.ToString(), ret.authKey);
            return(ret);
        }
        else
        {
            throw new HttpException(500, "[[[Invalid Facebook credentials]]]");
        }
    }
示例#6
0
    private static LcAuth.RegisteredUser CreateFacebookAccount(dynamic facebookUser, bool isProvider)
    {
        // Create user with Facebook
        var result = LcAuth.RegisterUser(
            facebookUser.email,
            facebookUser.first_name,
            facebookUser.last_name,
            LcAuth.GeneratePassword(),
            isProvider,
            Request.Url.Query
            //,facebookUser.gender
            );

        LcAuth.ConnectWithFacebookAccount(result.userID, facebookUser.id);
        LcAuth.SendRegisterUserEmail(result);
        return(result);
    }
示例#7
0
    public static LoginResult Login(string username, string password, bool rememberMe = false, bool returnProfile = false, bool allowUnconfirmed = false)
    {
        // DISABLED CONFIRMATION CHECK FOR BETA PERIOD, BECAUSE WE HAVE NOT THE EMAIL CONFIRMATION READY
        // AFTER THE WHOLE SITE AND MESSAGING CHANGE.
        // TODO: RE-ENABLE AFTER BETA
        //if (!allowUnconfirmed)
        //    checkAccountIsConfirmed(username);

        if (LcAuth.Login(username, password, rememberMe))
        {
            var userId = WebSecurity.GetUserId(username);
            return(GetLoginResultForID(userId, returnProfile));
        }
        else
        {
            throw new HttpException(400, "Incorrect username or password.");
        }
    }
示例#8
0
    private static LoginResult GetLoginResultForID(int userID, bool returnProfile)
    {
        var authKey = LcAuth.GetAutologinKey(userID);

        LcRest.UserProfile profile = null;

        if (returnProfile)
        {
            profile = LcRest.UserProfile.Get(userID);
        }

        return(new LoginResult {
            redirectUrl = getRedirectUrl(userID),
            userID = userID,
            authKey = authKey,
            profile = profile,
            onboardingStep = profile == null ? null : profile.onboardingStep
        });
    }
示例#9
0
    static UserAuthorization GetUserAuthorizationFromQueryString(System.Collections.Specialized.NameValueCollection queryString)
    {
        // #827 Simple token Authorization header
        var token = queryString["access_token"];

        if (!String.IsNullOrEmpty(token))
        {
            var userID = LcAuth.GetUserIdByAuthorizationToken(token);
            if (userID.HasValue)
            {
                return(new UserAuthorization
                {
                    userID = userID.Value,
                    token = token
                });
            }
        }
        return(null);
    }
示例#10
0
    /// <summary>
    /// Request an autologin using the values from the HttpRequest if
    /// is need.
    /// </summary>
    public static void RequestAutologin(HttpRequest Request)
    {
        // First, check standard 'Authorization' header
        var auth = Request.Headers["Authorization"];

        if (!String.IsNullOrEmpty(auth))
        {
            // First: support standard authorization
            if (!StartSessionWithAuthorizationHeader(auth))
            {
                // Legacy 'header based on autologin scheme' feature as fallback (to be removed as soon as Apps using it are updated)
                var m = System.Text.RegularExpressions.Regex.Match(auth, "^LC alu=([^,]+),alk=(.+)$");
                if (m.Success)
                {
                    var alu = m.Groups[1].Value;
                    var alk = m.Groups[2].Value;
                    LcAuth.Autologin(alu, alk);
                }
            }
        }
        else
        {
            var Q = Request.QueryString;
            // First: support standard authorization
            if (!StartSessionWithAuthorizationQueryString(Q))
            {
                // Legacy 'autologin' feature as fallback (to be removed as soon as Apps and emails using it are updated)
                // Using custom headers first, best for security using the REST API.
                var alk = N.DW(Request.Headers["alk"]) ?? Q["alk"];
                var alu = N.DW(Request.Headers["alu"]) ?? Q["alu"];

                // Autologin feature for anonymous sessions with autologin parameters on request
                if (!Request.IsAuthenticated &&
                    alk != null &&
                    alu != null)
                {
                    // 'alk' url parameter stands for 'Auto Login Key'
                    // 'alu' url parameter stands for 'Auto Login UserID'
                    LcAuth.Autologin(alu, alk);
                }
            }
        }
    }
示例#11
0
    private static LoginResult GetLoginResultForID(LcAuth.UserAuthorization authorization, bool returnProfile)
    {
        var authKey = LcAuth.GetAutologinKey(authorization.userID);

        LcRest.UserProfile profile = null;

        if (returnProfile)
        {
            profile = LcRest.UserProfile.Get(authorization.userID);
        }

        return(new LoginResult {
            redirectUrl = getRedirectUrl(authorization.userID),
            userID = authorization.userID,
            authKey = authKey,
            authToken = authorization.token,
            //authorization = authorization,
            profile = profile,
            onboardingStep = profile == null ? null : profile.onboardingStep
        });
    }
示例#12
0
    static UserAuthorization GetUserAuthorizationFromHeader(string authorizationHeaderValue)
    {
        if (String.IsNullOrWhiteSpace(authorizationHeaderValue))
        {
            return(null);
        }

        var tokenMatch = System.Text.RegularExpressions.Regex.Match(authorizationHeaderValue, "^Bearer (.+)$");

        if (tokenMatch.Success)
        {
            var token  = tokenMatch.Groups[1].Value;
            var userID = LcAuth.GetUserIdByAuthorizationToken(token);
            if (userID.HasValue)
            {
                return(new UserAuthorization
                {
                    userID = userID.Value,
                    token = token
                });
            }
        }
        return(null);
    }
    /// <summary>
    /// Process a request to create a user job title given a jobTitleID or as
    /// fallback a validated and sanitized jobTitleName (pass in GetValidatedJobTitleName result)
    /// </summary>
    /// <param name="userID"></param>
    /// <param name="jobTitleID"></param>
    /// <param name="jobTitleName"></param>
    /// <returns></returns>
    public dynamic Create(int userID, int jobTitleID, string jobTitleName)
    {
        var jobTitleExists = false;

        if (jobTitleID == 0)
        {
            // Look-up/new-job-title version: it's possible that the user wrotes a
            // job title name without pick-up one from the list, we look-up for that in database
            // for a jobTitleID,
            // and may not exists, so we try to create a new one with a template.

            // Name for the job title is required
            if (String.IsNullOrEmpty(jobTitleName))
            {
                throw new HttpException(400, "A Job Title is required");
            }

            // Search
            var jobTitle = LcRest.PublicJobTitle.AutocompleteSearch(jobTitleName, LcRest.Locale.Current).FirstOrDefault();
            if (jobTitle != null)
            {
                // Use the first one
                jobTitleID     = jobTitle.value;
                jobTitleExists = true;
            }
            else
            {
                //  Create a new job-title based on the given name #650
                jobTitleID = LcData.JobTitle.CreateJobTitleByName(jobTitleName, LcRest.Locale.Current.languageID, LcRest.Locale.Current.countryID, userID);
                // Check well know custom error codes
                if (jobTitleID == -1)
                {
                    throw new HttpException(400, String.Format("The Job Title '{0}' is not allowed.", jobTitleName));
                }
                LcMessaging.NotifyNewJobTitle(jobTitleName, jobTitleID);
                jobTitleExists = true;
            }
        }
        else
        {
            // Double check that the job title exists
            jobTitleExists = LcRest.PublicJobTitle.Get(jobTitleID, LcRest.Locale.Current) != null;
        }

        if (jobTitleID > 0 && jobTitleExists)
        {
            // Read data; It stops on not valid:
            var data = GetValidatedItemBodyInput();

            LcData.JobTitle.InsertUserJobTitle(
                userID,
                jobTitleID,
                data.policyID,
                data.intro,
                data.instantBooking,
                data.collectPaymentAtBookMeButton,
                LcRest.Locale.Current.languageID,
                LcRest.Locale.Current.countryID
                );

            // If user is just a client, needs to become a professional
            var user = LcRest.UserProfile.Get(userID);
            if (!user.isServiceProfessional)
            {
                LcAuth.BecomeProvider(userID);
                // Set onboarding step as done for 'add job titles' to avoid display that screen again to the user:
                LcData.UserInfo.SetOnboardingStep(userID, "addJobTitles");
                // Send email as provider
                LcMessaging.SendWelcomeProvider(userID, WebSecurity.CurrentUserName);
            }
        }
        else
        {
            throw new HttpException(404, "Job Title not found or disapproved");
        }

        return(GetItem(userID, jobTitleID));
    }
示例#14
0
    /// <summary>
    /// Convert a user record with 'Not Enabled Account' into a standard enabled account. See IsUserButNotEnabledAccount
    /// for more info, and check that value before call this to prevent an error when user has an enabled account.
    /// This supports the cases
    /// - User with status of 'serviceProfessionalClient': the user has an account created as client by a service professional.
    /// - User with status of 'subscriber': the user submitted it's email through a Lead Generation API to get in touch with newsletters or
    ///   to reference a service professional.
    ///
    /// For the conversion, we need support next actions/requests:
    /// - A: We need to communicate that specific situation (error message), generate a confirmation code
    ///   for the existent user, send email to let him to confirm that he/she owns the given e-mail.
    /// - B: On returning here after request/response A, a confirmation code is being provided and we must proceed
    ///   by checking the confirmation code and, on success, enable account (change status), update the membership password and
    ///   continue with a valid set of LoginResult. External code should allow user to update any additional account data.
    /// </summary>
    /// <param name="userID"></param>
    /// <param name="email"></param>
    /// <param name="password"></param>
    /// <param name="returnProfile"></param>
    /// <returns></returns>
    private static LoginResult SignupANotEnabledAccount(int userID, string email, string password, bool returnProfile, int accountStatusID, bool isOrganization)
    {
        // Get confirmation code, if any
        var confirmationCode = Request["confirmationCode"];
        // Prepare error message
        var errTpl = "";

        if (accountStatusID == (int)LcEnum.AccountStatus.serviceProfessionalClient)
        {
            errTpl = UserIsServiceProfessionalClientMessage;
        }
        else if (accountStatusID == (int)LcEnum.AccountStatus.subscriber)
        {
            errTpl = UserIsSubscriberMessage;
        }
        else
        {
            throw new Exception("[[[Not allowed]]]");
        }
        var errMsg = String.Format(errTpl, email);

        // Action/Request A: Create confirmation code
        if (String.IsNullOrEmpty(confirmationCode))
        {
            // To generate a confirmation code (creates the Membership record, that does not exists still)
            // this needs a random password (we still didn't verified the user, so do NOT trust on the given password).
            // NOTE: since this can be attempted several time by the user, and next attempts will fail because the Membership
            // record will exists already, just double check and try creation only if record don't exists:
            if (!LcAuth.HasMembershipRecord(userID))
            {
                WebSecurity.CreateAccount(email, LcAuth.GeneratePassword(), true);
            }
            StartOnboardingForUser(userID);
            // send email to let him to confirm it owns the given e-mail
            LcMessaging.SendWelcomeCustomer(userID, email);
            // Not valid after all, just communicate was was done and needs to do to active its account:
            throw new HttpException(409, errMsg);
        }
        // Action/Request B: confirm confirmation code
        else
        {
            // If confirmation token is valid, enable account and reset password
            if (LcAuth.GetConfirmationToken(userID) == confirmationCode)
            {
                // We know is valid, we can update the accountStatus to be an standard/enabled account
                // and that will allow to set the account as confirmed
                using (var db = new LcDatabase())
                {
                    db.Execute("UPDATE users SET accountStatusID = @1 WHERE UserID = @0", userID, LcEnum.AccountStatus.active);
                }
                // now we can confirm (we already know the code is valid, it will just double check and update database)
                LcAuth.ConfirmAccount(confirmationCode);
                // set the password provided by the user. Trick: we need to generate a reset token in order to set the password.
                var token = WebSecurity.GeneratePasswordResetToken(email);
                LcAuth.ResetPassword(token, password);
                // Left continue with profile data update..
            }
            else
            {
                // RE-send email to let him to confirm it owns the given e-mail
                LcMessaging.SendWelcomeCustomer(userID, email);
                throw new HttpException(409, errMsg);
            }
        }

        // We need a logged object, and additionally a double check is performed (so we ensure setting the password process worked).
        return(Login(email, password, false, returnProfile, false));
    }
示例#15
0
    /// <summary>
    /// Signup with fields:
    /// - email [required]
    /// - password [required when no facebookUserID is given]
    /// - facebookUserID [optional]
    /// - countryID [optional defaults to COUNTRY_CODE_USA]
    /// - profileType [optional defaults to client]
    /// - utm [optional, not a named form parameter but the whole query string]
    /// - firstName [optional except atBooking]
    /// - lastName [optional except atBooking]
    /// - phone [optional except atBooking]
    /// - returnProfile [optional defaults to false] Returns the user profile in a property of the result
    /// - atBooking [optional]
    /// - isOrganization [optional] Default false
    /// </summary>
    /// <param name="page"></param>
    /// <returns></returns>
    public static LoginResult Signup(WebPage page)
    {
        page.Validation.RequireField("email", "[[[You must specify an email.]]]");
        // Username is an email currently, so need to be restricted
        page.Validation.Add("email",
                            Validator.Regex(LcValidators.EmailAddressRegexPattern, "[[[The email is not valid.]]]"));

        // First data
        var profileTypeStr        = Request.Form["profileType"] ?? "";
        var isServiceProfessional = SERVICE_PROFESSIONAL_TYPE == profileTypeStr.ToUpper();
        var isClient            = !isServiceProfessional;
        var facebookUserID      = Request.Form["facebookUserID"].AsLong(0);
        var facebookAccessToken = Request.Form["facebookAccessToken"];
        var email          = Request.Form["email"];
        var atBooking      = Request.Form["atBooking"].AsBool();
        var isOrganization = Request.Form["isOrganization"].AsBool();

        //
        // Conditional validations
        // Facebook
        var useFacebookConnect = facebookUserID > 0 && !String.IsNullOrEmpty(facebookAccessToken);

        if (!useFacebookConnect)
        {
            page.Validation.RequireField("password", "[[[You must specify a password.]]]");
            // We manually validate if a password was given, in order to prevent
            // showing up the validation format message additionally to the 'required password' message
            if (!String.IsNullOrWhiteSpace(Request.Form["password"]))
            {
                page.Validation.Add("password", new PasswordValidator());
            }
        }
        else
        {
            var prevFbUser = LcAuth.GetFacebookUser(facebookUserID);
            if (prevFbUser != null)
            {
                throw new HttpException(409, "[[[Facebook account already connected. Sign in.]]]");
            }
        }

        // For a signup at a client booking, we require more fields
        if (atBooking)
        {
            page.Validation.RequireField("phone", "[[[You must specify your mobile phone number.]]]");
            page.Validation.RequireField("firstName", "[[[You must specify your first name.]]]");
            page.Validation.RequireField("lastName", "[[[You must specify your last name.]]]");
        }

        if (page.Validation.IsValid())
        {
            // TODO To use countryCode for a more 'open' public REST API, where 'code' is a well know ISO 2-letters CODE
            //var countryCode = Request.Form["countryCode"] ?? "US";
            var countryID = Request.Form["countryID"].AsInt(COUNTRY_CODE_AU);

            // Autogenerated password (we need to save one) on facebook connect:
            var password      = useFacebookConnect ? LcAuth.GeneratePassword() : Request.Form["password"];
            var firstName     = Request.Form["firstName"];
            var lastName      = Request.Form["lastName"];
            var phone         = Request.Form["phone"];
            var returnProfile = Request.Form["returnProfile"].AsBool();

            var         utm    = Request.Url.Query;
            LoginResult logged = null;

            // If the user exists, try to log-in with the given password,
            // becoming a provider if that was the requested profileType and follow as
            // a normal login.
            // If the password didn't match, throw a sign-up specific error (email in use)
            // Otherwise, just register the user.
            if (LcAuth.ExistsEmail(email))
            {
                // We query the user with that email
                var userID = WebSecurity.GetUserId(email);
                var user   = LcRest.UserProfile.Get(userID);
                // There are special cases when a user is registered, but never has accepted TOU or created a password (Not Enabled Account),
                // and is possible for that user to become an regular/enabled account.
                if (IsUserButNotEnabledAccount(user))
                {
                    logged = SignupANotEnabledAccount(userID, email, password, returnProfile, user.accountStatusID, isOrganization);
                }
                else
                {
                    // If the email exists, we try to log-in using the provided password, to don't bother with "e-mail in use" error
                    // if the user provides the correct credentials (maybe just don't remember he/she has already an account; make it easy for them
                    // to return).
                    // Try Login
                    try
                    {
                        logged = Login(email, password, false, returnProfile, true);
                        userID = logged.userID;
                        // Ensure we set-up
                        // as a professional if requested
                        // Next code will throw exception on error
                        if (isServiceProfessional)
                        {
                            LcAuth.BecomeProvider(userID);
                        }
                    }
                    catch (HttpException)
                    {
                        // Not valid log-in, throw a 'email exists' error with Conflict http code
                        throw new HttpException(409, "[[[E-mail address is already in use.]]]");
                    }
                }

                // Update account data with the extra information.
                using (var db = new LcDatabase())
                {
                    db.Execute(@"
                        UPDATE users SET
                            firstName = coalesce(@1, firstName),
                            lastName = coalesce(@2, lastName),
                            mobilePhone = coalesce(@3, mobilePhone),
                            isOrganization = @4
                        WHERE userID = @0
                    ", userID, firstName, lastName, phone, isOrganization);
                    // Create a home address record almost with the country
                    var home = LcRest.Address.GetHomeAddress(userID);
                    home.countryCode = LcRest.Locale.GetCountryCodeByID(countryID);
                    home.countryID   = countryID;
                    LcRest.Address.SetAddress(home);

                    StartOnboardingForUser(userID);
                }

                // SIGNUP
                LcMessaging.SendMail("*****@*****.**", "Sign-up", String.Format(@"
                    <html><body><h3>Sign-up.</h3>
                    <strong>This user was already in the database, is re-registering itself again!</strong><br/>
                    <dl>
                    <dt>Profile:</dt><dd>{0}</dd>
                    <dt>First Name:</dt><dd>{1}</dd>
                    <dt>Last Name:</dt><dd>{2}</dd>
                    <dt>Country:</dt><dd>{5}</dd>
                    <dt>Email:</dt><dd>{3}</dd>
                    <dt>UserID:</dt><dd>{4}</dd>
                    <dt>Phone:</dt><dd>{6}</dd>
                    </dl>
                    </body></html>
                ", profileTypeStr, firstName, lastName, email, logged.userID, countryID, phone));

                return(logged);
            }
            else
            {
                if (useFacebookConnect)
                {
                    // Verify Facebook ID and accessToken contacting to Facebook Servers
                    if (LcFacebook.GetUserFromAccessToken(facebookUserID.ToString(), facebookAccessToken) == null)
                    {
                        throw new HttpException(400, "[[[Facebook account does not exists.]]]");
                    }
                }

                var registered = LcAuth.RegisterUser(email, firstName, lastName, password,
                                                     isServiceProfessional, utm, -1, null, phone, null, countryID, isOrganization);

                // Create a home address record almost with the country
                var home = LcRest.Address.GetHomeAddress(registered.UserID);
                home.countryCode = LcRest.Locale.GetCountryCodeByID(countryID);
                home.countryID   = countryID;
                LcRest.Address.SetAddress(home);

                if (useFacebookConnect)
                {
                    // Register connection between the new account and the Facebook account
                    LcAuth.ConnectWithFacebookAccount(registered.UserID, facebookUserID);
                }

                // Welcome and confirmation e-mail
                LcAuth.SendRegisterUserEmail(registered);

                // SIGNUP
                LcMessaging.SendMail("*****@*****.**", "Sign-up", String.Format(@"
                    <html><body><h3>Sign-up.</h3>
                    <dl>
                    <dt>Profile:</dt><dd>{0}</dd>
                    <dt>First Name:</dt><dd>{1}</dd>
                    <dt>Last Name:</dt><dd>{2}</dd>
                    <dt>Country:</dt><dd>{5}</dd>
                    <dt>Email:</dt><dd>{3}</dd>
                    <dt>UserID:</dt><dd>{4}</dd>
                    <dt>Phone:</dt><dd>{6}</dd>
                    </dl>
                    </body></html>
                ", profileTypeStr, firstName, lastName, email, registered.UserID, countryID, phone));

                // Auto login:
                return(Login(email, password, false, returnProfile, true));
            }
        }
        else
        {
            // Bad request, input data incorrect because of validation rules
            throw new HttpException(400, LcRessources.ValidationSummaryTitle);
        }
    }
示例#16
0
    /// <summary>
    /// Signup with fields:
    /// - email [required]
    /// - password [required when no facebookUserID is given]
    /// - facebookUserID [optional]
    /// - countryID [optional defaults to COUNTRY_CODE_USA]
    /// - profileType [optional defaults to client]
    /// - utm [optional, not a named form parameter but the whole query string]
    /// - firstName [optional for professionals, required for clients]
    /// - lastName [optional for professionals, required for clients]
    /// - postalCode [optional]
    /// - referralCode [optional]
    /// - device [optional]
    /// - phone [optional for professionals, required for clients]
    /// - returnProfile [optional defaults to false] Returns the user profile in a property of the result
    /// </summary>
    /// <param name="page"></param>
    /// <returns></returns>
    public static LoginResult Signup(WebPage page)
    {
        page.Validation.RequireField("email", "You must specify an email.");
        // Username is an email currently, so need to be restricted
        page.Validation.Add("email",
                            Validator.Regex(LcValidators.EmailAddressRegexPattern, "The email is not valid."));

        // First data
        var profileTypeStr        = Request.Form["profileType"] ?? "";
        var isServiceProfessional = SERVICE_PROFESSIONAL_TYPE == profileTypeStr.ToUpper();
        var isClient            = !isServiceProfessional;
        var facebookUserID      = Request.Form["facebookUserID"].AsLong(0);
        var facebookAccessToken = Request.Form["facebookAccessToken"];
        var email = Request.Form["email"];

        //
        // Conditional validations
        // Facebook
        var useFacebookConnect = facebookUserID > 0 && !String.IsNullOrEmpty(facebookAccessToken);

        if (!useFacebookConnect)
        {
            page.Validation.RequireField("password", "You must specify a password.");
            // We manually validate if a password was given, in order to prevent
            // showing up the validation format message additionally to the 'required password' message
            if (!String.IsNullOrWhiteSpace(Request.Form["password"]))
            {
                page.Validation.Add("password", new PasswordValidator());
            }
        }
        else
        {
            var prevFbUser = LcAuth.GetFacebookUser(facebookUserID);
            if (prevFbUser != null)
            {
                throw new HttpException(409, "Facebook account already connected. Sign in.");
            }
        }
        // Profile Type
        if (isClient)
        {
            page.Validation.RequireField("phone", "You must specify your mobile phone number.");
            page.Validation.RequireField("firstName", "You must specify your first name.");
            page.Validation.RequireField("lastName", "You must specify your last name.");
        }

        if (page.Validation.IsValid())
        {
            var postalCode = Request.Form["postalCode"];
            // TODO To use countryCode for a more 'open' public REST API, where 'code' is a well know ISO 2-letters CODE
            //var countryCode = Request.Form["countryCode"] ?? "US";
            var countryID = Request.Form["countryID"].AsInt(COUNTRY_CODE_USA);

            // Postal code is Optional
            if (!String.IsNullOrEmpty(postalCode))
            {
                // Validate postal code before continue
                var add = new LcRest.Address
                {
                    postalCode = postalCode,
                    //countryCode = countryCode
                    countryID = countryID
                };
                if (!LcRest.Address.AutosetByCountryPostalCode(add))
                {
                    // bad postal code
                    page.ModelState.AddError("postalCode", "Invalid postal code");
                    throw new HttpException(400, LcRessources.ValidationSummaryTitle);
                }
            }

            // Autogenerated password (we need to save one) on facebook connect:
            var password      = useFacebookConnect ? LcAuth.GeneratePassword() : Request.Form["password"];
            var firstName     = Request.Form["firstName"];
            var lastName      = Request.Form["lastName"];
            var referralCode  = Request.Form["referralCode"];
            var device        = Request.Form["device"];
            var phone         = Request.Form["phone"];
            var returnProfile = Request.Form["returnProfile"].AsBool();

            var         utm    = Request.Url.Query;
            LoginResult logged = null;

            // If the user exists, try to log-in with the given password,
            // becoming a provider if that was the requested profileType and follow as
            // a normal login.
            // If the password didn't match, throw a sign-up specific error (email in use)
            // Otherwise, just register the user.
            if (LcAuth.ExistsEmail(email))
            {
                // If the email exists, we try to log-in using the provided password, to don't bother with "e-mail in use" error
                // if the user provides the correct credentials (maybe just don't remember he/she has already an account; make it easy for them
                // to return).
                // BUT we have a special situation that needs extra checks:
                // CLIENT--CONFIRMATION LOGIC
                // The email can exists because the user has an account created as client by a service professional:
                // - A: On that cases, we need to communicate that specific situation (error message), generate a confirmation code
                // for the existent user, send email to let him to confirm it owns the given e-mail.
                // - B: On returning here after point A, a confirmation code is provided and we must proceed
                // by checking the confirmation code and, on success, unlock and update the membership password and
                // continue updating any given data.
                var userID = WebSecurity.GetUserId(email);
                var user   = LcRest.UserProfile.Get(userID);
                if (user.accountStatusID != (int)LcEnum.AccountStatus.serviceProfessionalClient)
                {
                    // NOT a client, just standard sign-up that requires verify the email/password or fail
                    // Try Login
                    try
                    {
                        logged = Login(email, password, false, returnProfile, true);
                        userID = logged.userID;
                        // throw exception on error
                        if (isServiceProfessional)
                        {
                            LcAuth.BecomeProvider(userID);
                        }
                    }
                    catch (HttpException)
                    {
                        // Not valid log-in, throw a 'email exists' error with Conflict http code
                        throw new HttpException(409, "E-mail address is already in use.");
                    }
                }
                else
                {
                    // CLIENT--CONFIRMATION LOGIC
                    // The email can exists because the user has an account created as client by a service professional:
                    // - A: On that cases, we need to communicate that specific situation (error message), generate a confirmation code
                    // for the existent user, send email to let him to confirm it owns the given e-mail.
                    // - B: On returning here after point A, a confirmation code is provided and we must proceed
                    // by checking the confirmation code and, on success, unlock and update the membership password and
                    // continue updating any given data.
                    var confirmationCode = Request["confirmationCode"];
                    var errMsg           = String.Format(@"We see one of our service professionals has already scheduled services for you in the past.
                        We've just sent an invitation to create your account to {0}.
                        Please follow its instructions. We can't wait to get you on board!", email
                                                         );
                    if (String.IsNullOrEmpty(confirmationCode))
                    {
                        // Point A: create confirmation code
                        // generate a confirmation code (creates the Membership record, that does not exists still since is as just a client)
                        // this needs a random password (we still didn't verified the user, so do NOT trust on the given password).
                        // NOTE: since this can be attempted several time by the user, and next attempts will fail because the Membership
                        // record will exists already, just double check and try creation only if record don't exists:
                        if (!LcAuth.HasMembershipRecord(userID))
                        {
                            WebSecurity.CreateAccount(email, LcAuth.GeneratePassword(), true);
                        }
                        // send email to let him to confirm it owns the given e-mail
                        LcMessaging.SendWelcomeCustomer(userID, email);
                        // Not valid after all, just communicate was was done and needs to do to active its account:
                        throw new HttpException(409, errMsg);
                    }
                    else
                    {
                        // Point B: confirm confirmation code
                        if (LcAuth.GetConfirmationToken(userID) == confirmationCode)
                        {
                            // We know is valid, we can update the accountStatus to not be any more a "service professional's client"
                            // and that will allow to set the account as confirmed
                            using (var db = new LcDatabase())
                            {
                                db.Execute("UPDATE users SET accountStatusID = @1 WHERE UserID = @0", userID, LcEnum.AccountStatus.active);
                            }
                            // now we can confirm (we already know the code is valid, it will just double check and update database)
                            LcAuth.ConfirmAccount(confirmationCode);
                            // set the password provided by the user. Trick: we need to generate a reset token in order to set the password.
                            var token = WebSecurity.GeneratePasswordResetToken(email);
                            LcAuth.ResetPassword(token, password);
                            // Left continue with profile data update..
                        }
                        else
                        {
                            // RE-send email to let him to confirm it owns the given e-mail
                            LcMessaging.SendWelcomeCustomer(userID, email);
                            throw new HttpException(409, errMsg);
                        }
                    }

                    // We need a logged object, and additionally a double check is performed (so we ensure setting the password process worked).
                    logged = Login(email, password, false, returnProfile, false);
                }

                // Update account data with the extra information.
                using (var db = new LcDatabase())
                {
                    db.Execute(@"
                        UPDATE users SET
                            firstName = coalesce(@1, firstName),
                            lastName = coalesce(@2, lastName),
                            mobilePhone = coalesce(@3, mobilePhone),
                            signupDevice = coalesce(@4, signupDevice)
                        WHERE userID = @0
                    ", userID, firstName, lastName, phone, device);

                    if (!String.IsNullOrEmpty(postalCode))
                    {
                        var address = LcRest.Address.GetHomeAddress(userID);
                        if (address.postalCode != postalCode)
                        {
                            address.postalCode = postalCode;
                            //address.countryCode = countryCode;
                            address.countryCode = LcRest.Locale.GetCountryCodeByID(countryID);
                            address.countryID   = countryID;
                            LcRest.Address.SetAddress(address);
                        }
                    }
                }

                // SIGNUP
                LcMessaging.SendMail("*****@*****.**", "Sign-up", String.Format(@"
                    <html><body><h3>Sign-up.</h3>
                    <strong>This user was already in the database, is re-registering itself again!</strong><br/>
                    <dl>
                    <dt>Profile:</dt><dd>{0}</dd>
                    <dt>First Name:</dt><dd>{1}</dd>
                    <dt>Last Name:</dt><dd>{2}</dd>
                    <dt>Postal code:</dt><dd>{3}</dd>
                    <dt>Country:</dt><dd>{9}</dd>
                    <dt>Referral code:</dt><dd>{4}</dd>
                    <dt>Device:</dt><dd>{5}</dd>
                    <dt>Phone:</dt><dd>{6}</dd>
                    <dt>Email:</dt><dd>{7}</dd>
                    <dt>UserID:</dt><dd>{8}</dd>
                    </dl>
                    </body></html>
                ", profileTypeStr, firstName, lastName, postalCode, referralCode, device, phone, email, logged.userID, countryID));

                return(logged);
            }
            else
            {
                if (useFacebookConnect)
                {
                    // Verify Facebook ID and accessToken contacting to Facebook Servers
                    if (LcFacebook.GetUserFromAccessToken(facebookUserID.ToString(), facebookAccessToken) == null)
                    {
                        throw new HttpException(400, "Facebook account does not exists.");
                    }
                }

                var registered = LcAuth.RegisterUser(email, firstName, lastName, password, isServiceProfessional, utm, -1, null, phone, device);
                if (!String.IsNullOrEmpty(postalCode))
                {
                    // Set address
                    var address = LcRest.Address.GetHomeAddress(registered.UserID);
                    address.postalCode = postalCode;
                    //address.countryCode = countryCode;
                    address.countryCode = LcRest.Locale.GetCountryCodeByID(countryID);
                    address.countryID   = countryID;
                    LcRest.Address.SetAddress(address);
                }

                if (useFacebookConnect)
                {
                    // Register connection between the new account and the Facebook account
                    LcAuth.ConnectWithFacebookAccount(registered.UserID, facebookUserID);
                }

                // Welcome and confirmation e-mail
                LcAuth.SendRegisterUserEmail(registered);

                // SIGNUP
                LcMessaging.SendMail("*****@*****.**", "Sign-up", String.Format(@"
                    <html><body><h3>Sign-up.</h3>
                    <dl>
                    <dt>Profile:</dt><dd>{0}</dd>
                    <dt>First Name:</dt><dd>{1}</dd>
                    <dt>Last Name:</dt><dd>{2}</dd>
                    <dt>Postal code:</dt><dd>{3}</dd>
                    <dt>Country:</dt><dd>{9}</dd>
                    <dt>Referral code:</dt><dd>{4}</dd>
                    <dt>Device:</dt><dd>{5}</dd>
                    <dt>Phone:</dt><dd>{6}</dd>
                    <dt>Email:</dt><dd>{7}</dd>
                    <dt>UserID:</dt><dd>{8}</dd>
                    </dl>
                    </body></html>
                ", profileTypeStr, firstName, lastName, postalCode, referralCode, device, phone, email, registered.UserID, countryID));

                // Auto login:
                return(Login(email, password, false, returnProfile, true));
            }
        }
        else
        {
            // Bad request, input data incorrect because of validation rules
            throw new HttpException(400, LcRessources.ValidationSummaryTitle);
        }
    }
示例#17
0
    /// <summary>
    /// Process a request to create a user job title given a jobTitleID with
    /// a validated and sanitized jobTitleName (pass in GetValidatedJobTitleName result)
    /// as a custom listing title.
    /// </summary>
    /// <param name="userID"></param>
    /// <param name="jobTitleID"></param>
    /// <param name="jobTitleName"></param>
    /// <returns></returns>
    public dynamic Create(int userID, int jobTitleID, string jobTitleName)
    {
        if (jobTitleID == 0 || jobTitleID == LcRest.UserJobTitle.UserGeneratedJobTitleID)
        {
            // new-job-title version: it's possible that the user wrotes a
            // job title name without pick-up one from the list, on that case
            // the user generated job title is assigned and the given title name is
            // used as listing title

            // Name for the job title is required
            if (String.IsNullOrWhiteSpace(jobTitleName))
            {
                throw new HttpException(400, "A Job Title is required");
            }

            // Search: we try an exact match, just in case we have already the job title (singular or plural) and
            // user didn't select it from the list
            var locale   = LcRest.Locale.Current;
            var jobTitle = LcRest.JobTitle.FindExactName(jobTitleName, locale.languageID, locale.countryID);
            if (jobTitle.HasValue)
            {
                // Use the first one
                jobTitleID = jobTitle.Value;
            }
            else
            {
                //  Create a new job-title based on the given name #650
                jobTitleID = LcRest.UserJobTitle.UserGeneratedJobTitleID;
            }
        }
        // Double check that the job title exists
        else
        {
            var existentTitle = LcRest.PublicJobTitle.Get(jobTitleID, LcRest.Locale.Current);
            if (existentTitle == null)
            {
                throw new HttpException(404, "Job Title not found or disapproved");
            }
            // If exists, we use the user given title, with fallback to the one we have for the given jobTitleID
            else if (String.IsNullOrWhiteSpace(jobTitleName))
            {
                jobTitleName = existentTitle.singularName;
            }
        }

        // Read data; It stops on not valid:
        var data = GetValidatedItemBodyInput();

        LcRest.UserJobTitle.Create(new LcRest.UserJobTitle
        {
            userID                       = userID,
            jobTitleID                   = jobTitleID,
            title                        = jobTitleName,
            intro                        = data.intro,
            cancellationPolicyID         = data.policyID,
            collectPaymentAtBookMeButton = data.collectPaymentAtBookMeButton,
            instantBooking               = data.instantBooking
        });

        // If user is just a client, needs to become a professional
        var user = LcRest.UserProfile.Get(userID);

        if (!user.isServiceProfessional)
        {
            LcAuth.BecomeProvider(userID);
            // Set onboarding step as done for 'add job title' to avoid display that screen again to the user:
            LcData.UserInfo.SetOnboardingStep(userID, "addJobTitle");
            // Send email as provider
            LcMessaging.SendWelcomeProvider(userID, WebSecurity.CurrentUserName);
        }

        return(LcRest.UserJobTitle.GetItem(userID, jobTitleID));
    }