menu

SiteGenesis / Server-side JS / Source: app_storefront_controllers/cartridge/scripts/models/CustomerModel.js

'use strict';

/*
* Model to manage customer and login information. Creates a CustomerModel class that with helper methods
* to get and create customers, create and edit accounts, and set or verify login information.
* @module models/CustomerModel
*/

var AbstractModel = require('./AbstractModel');
var CustomerMgr = require('dw/customer/CustomerMgr');
var Transaction = require('dw/system/Transaction');
var Form = require('~/cartridge/scripts/models/FormModel');
var Email = require('~/cartridge/scripts/models/EmailModel');

/**
 * Customer helper providing enhanced content functionality
 * @class module:models/CustomerModel~CustomerModel
 *
 * @param {dw.customer.Customer} parameter - The customer object to enhance/wrap.
 */
var CustomerModel = AbstractModel.extend({

    /**
     * Checks the validity of a password reset token.
     * @transactional
     * @alias module:models/CustomerModel~CustomerModel/resetPasswordByToken
     */
    resetPasswordByToken: function (token, password) {
        var customerInstance;
        var resetCustomerPasswordWithTokenResult;

        customerInstance = this;

        resetCustomerPasswordWithTokenResult = Transaction.wrap(function () {
            return customerInstance.object.profile.credentials.setPasswordWithToken(token, password);
        });

        if (resetCustomerPasswordWithTokenResult.error) {
            return false;
        }

        return true;
    },

    /**
     * Checks the validity of a password reset token.
     * @transactional
     * @alias module:models/CustomerModel~CustomerModel/generatePasswordResetToken
     */
    generatePasswordResetToken: function () {
        var token;
        var customerInstance;
        customerInstance = this;

        token = Transaction.wrap(function () {
            return customerInstance.object.profile.credentials.createResetPasswordToken();
        });

        return token;
    }
});

/**
 * Gets the current customer or passes in a customer instance.
 *
 * @alias module:models/CustomerModel~CustomerModel/get
 * @param {dw.customer.Customer} parameter - The customer object to enhance or wrap. If NULL the current customer is
 * retrieved from the session.
 * @returns {module:models/CustomerModel~CustomerModel}
 */
CustomerModel.get = function (parameter) {
    var obj = null;
    if (typeof parameter === 'undefined') {
        obj = customer;
    } else if (typeof parameter === 'object') {
        obj = parameter;
    }
    return new CustomerModel(obj);
};

/**
 * Authenticates the current session using the supplied Login and Password. If a different customer is currently
 * authenticated in the session, then this customer is "logged out" and her/his privacy and form data are deleted.
 *
 * @alias module:models/CustomerModel~CustomerModel/login
 * @param {String} username - Login name.
 * @param {String} password - Password.
 * @param {Boolean} rememberMe - Optional Boolean value indicating whether the customer wants to be remembered on the current
 * computer. If a value of <code>true</code> is supplied a cookie identifying the customer is stored upon successful login. If a value
 * of <code>false</code> or a null value is supplied, then no cookie is stored and any existing cookie is removed.
 * @returns {boolean}
 */
CustomerModel.login = function (username, password, rememberMe) {
    var TempCustomer;
    var authenticatedCustomer;

    TempCustomer = CustomerMgr.getCustomerByLogin(username);

    // @TODO customer locked currently not handled
    if (typeof (TempCustomer) !== 'undefined' && TempCustomer !== null && TempCustomer.profile !== null && TempCustomer.profile.credentials.locked) {
        return false;
    }

    authenticatedCustomer = Transaction.wrap(function () {
        return CustomerMgr.loginCustomer(username, password, rememberMe);
    });

    if (authenticatedCustomer === null) {
        if (typeof (TempCustomer) !== 'undefined' && TempCustomer !== null && TempCustomer.profile !== null && TempCustomer.profile.credentials.locked) {
            Email.get('mail/lockoutemail', TempCustomer.profile.email).setSubject((dw.web.Resource.msg('resource.youraccount', 'email', null))).send({
                TempCustomer: TempCustomer
            });
        }

        return false;
    }
    // @FIXME Rather return a customer instance
    return true;
};

/**
 * Logs out the customer currently logged into the storefront.
 * @alias module:models/CustomerModel~CustomerModel/logout
 */
CustomerModel.logout = function () {
    var rememberMe = Form.get('profile.login.rememberme').value();
    CustomerMgr.logoutCustomer(rememberMe);
};

/**
 * Looks up a customer by its login.
 * @alias module:models/CustomerModel~CustomerModel/getCustomerbyLogin
 * @param {String} login - Login used to retrieve customer.
 */
CustomerModel.retrieveCustomerByLogin = function (login) {
    var customerByLogin = CustomerMgr.getCustomerByLogin(login);

    if (customerByLogin === null) {
        return null;
    }

    return this.get(customerByLogin);
};

/**
 * Creates a customer.
 * @alias module:models/CustomerModel~CustomerModel/createNewCustomer
 * @param {String} login - Login for the customer.
 * A valid login name is between 1 and 256 characters in length, not counting leading or trailing whitespace,
 * and may contain only the following characters:
 *
 * - alphanumeric (Unicode letters or decimal digits)
 * - space
 * - period
 * - dash
 * - underscore
 * - @
 * @param {String} password - Plain customer password, which is encrypted before it is stored at the profile..
 */
CustomerModel.createNewCustomer = function (login, password) {
    var newCustomer = CustomerMgr.createCustomer(login, password);

    if (newCustomer === null) {
        return null;
    }

    return this.get(newCustomer);
};

/**
 * Sets the customer's login.
 *
 * @alias module:models/CustomerModel~CustomerModel/setLogin
 * @param customer - The customer.
 * @param {String} login - Login for the customer.
 * A valid login name is between 1 and 256 characters in length, not counting leading or trailing whitespace,
 * and may contain only the following characters:
 *
 * - alphanumeric (Unicode letters or decimal digits)
 * - space
 * - period
 * - dash
 * - underscore
 * - @
 * @param {String} password - Plain customer password for the current customer, which is encrypted before it is stored at the profile.
 * @return <code>true</code> if the login or password was updated.
 */
CustomerModel.setLogin = function (customerToSet, login, password) {
    //@FIXME Put on customer scope vs. passing in customer
    if ((customerToSet === null) || (login === null) || (password === null) || (customerToSet.profile === null)) {
        return false;
    }
    var result = customerToSet.profile.credentials.setLogin(login, password);
    return result;
};

/**
 * Creates a new customer account.
 * @transactional
 * @alias module:models/CustomerModel~CustomerModel/createAccount
 * @param {String} email - The current customer email address to use for login.
 * @param {String} password - The password of the customer.
 * @param {dw.web.Form} form - The form instance to invalidate.
 * @return <code>true</code> if the account was created successfully.
 * @see module:models/CustomerModel~CustomerModel/createNewCustomer
 * @see module:models/CustomerModel~CustomerModel/setLogin
 */
CustomerModel.createAccount = function (email, password, form) {

    Transaction.begin();

    // Creates a new customer.
    var newCustomer, rememberMe;
    newCustomer = CustomerModel.createNewCustomer(email, password);
    if (newCustomer === null || newCustomer.object === null) {
        Transaction.rollback();
        form.invalidate();
        return false;
    }

    if (!Form.get('profile.customer').copyTo(newCustomer.object.profile)) {
        Transaction.rollback();
        form.invalidate();
        return false;
    }

    // Sets login and password for customer.
    if (!this.setLogin(newCustomer.object, email, password)) {
        Transaction.rollback();
        form.invalidate();
        return false;
    }

    Transaction.commit();

    Form.get('login').copyTo(newCustomer.object.profile.credentials);

    rememberMe = Form.get('profile.login.rememberme').value();

    // Logs the customer in.
    return Transaction.wrap(function () {
        return CustomerMgr.loginCustomer(email, password, rememberMe);
    });

};

/**
 * Checks if the user name exists and communicates the status back.
 *
 * @return <code>true</code> if the login matches the email for the customer
 * @alias module:models/CustomerModel~CustomerModel/checkUserName
 */
CustomerModel.checkUserName = function () {
    //@FIXME get email as parameter
    var profileForm;
    var customerByLogin;

    profileForm = session.forms.profile;

    if (customer.profile.credentials.login === profileForm.customer.email.value) {
        return true;
    }

    customerByLogin = CustomerMgr.getCustomerByLogin(profileForm.customer.email.value);

    if (customerByLogin === null) {
        return true;
    }

    return false;
};

/**
 * Checks validity of a password reset token.
 * @alias module:models/CustomerModel~CustomerModel/getByPasswordResetToken
 * @param token the token to validate
 * @return customer record assocated with the token or null if the token is expired or not associated with
 * a customer record.
 */
CustomerModel.getByPasswordResetToken = function (token) {
    var result;
    var customerByPasswordToken;

    if (empty(token)) {
        result = null;
    } else {
        customerByPasswordToken = CustomerMgr.getCustomerByToken(token);

        if (customerByPasswordToken === null) {
            result = null;
        } else {
            result = CustomerModel.get(customerByPasswordToken);
        }
    }
    return result;
};

/**
 * Updates a customer account with form data.
 * @transactional
 * @alias module:models/CustomerModel~CustomerModel/editAccount
 * @param email the current customer email address to use for login
 * @param password the password of the current customer
 * @param form the form to invalidate
 * @return <code>true</code> if transaction is successfully committed, <code>false</code> if
 * <ul><li>the customer password cannot be set
 * </li><li>the customer login cannot be set
 * </li><li>the new password cannot be saved to the customer profile.</li></ul>
 */
CustomerModel.editAccount = function (email, password, currentPassword, form) {

    Transaction.begin();

    var newPassword = password;
    var oldPassword = currentPassword;
    var setCustomerPassword = customer.profile.credentials.setPassword(newPassword, oldPassword, true);

    if (setCustomerPassword.error || !CustomerModel.setLogin(customer, email, password) || !Form.get('profile.customer').copyTo(customer.profile)) {
        Transaction.rollback();
        return false;
    }

    Transaction.commit();

    form.clear();

    return true;
};

/** The customer class */
module.exports = CustomerModel;