// required references:
// c:\Program Files\Microsoft SDKs\RIA Services\v1.0\Libraries\Server\System.ServiceModel.DomainServices.Hosting.dll
// c:\Program Files\Microsoft SDKs\RIA Services\v1.0\Libraries\Server\System.ServiceModel.DomainServices.Server.dll
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Hosting;
using System.ServiceModel.DomainServices.Server;
using System.ServiceModel.DomainServices.Server.ApplicationServices;
using System.Web.Profile;
using System.Web.Security;
using System.Net;
using System.Net.Mail;

namespace MyAuth.Web
{
    // TODO: Switch to a secure endpoint when deploying the application.
    //       The user's name and password should only be passed using https.
    //       To do this, set the RequiresSecureEndpoint property on EnableClientAccessAttribute to true.
    //   
    //       [EnableClientAccess(RequiresSecureEndpoint = true)]
    //
    //       More information on using https with a Domain Service can be found on MSDN.

    /// <summary>
    /// Domain Service responsible for authenticating users when they log on to the application.
    /// Most of the functionality is already provided by the AuthenticationBase class.
    /// </summary>
    [EnableClientAccess]
    public class AuthenticationService : AuthenticationBase<User>{}

    // TODO: Switch to a secure endpoint when deploying the application.
    //       The user's name and password should only be passed using https.
    //       To do this, set the RequiresSecureEndpoint property on EnableClientAccessAttribute to true.
    //       [EnableClientAccess(RequiresSecureEndpoint = true)]
    //       More information on using https with a Domain Service can be found on MSDN.
    /// <summary>
    /// Domain Service responsible for registering users.
    /// </summary>
    [EnableClientAccess]
    public class UserRegistrationService : DomainService
    {
        /// <summary>
        /// Role to which users will be added by default.
        /// </summary>
        public const string DefaultRole = "Registered Users";

        //// NOTE: This is a sample code to get your application started.
        //// In the production code you should provide a mitigation against a 
        //// denial of service attack by providing CAPTCHA control functionality 
        //// or verifying user's email address.

        /// <summary>
        /// Adds a new user with the supplied <see cref="RegistrationData"/> and <paramref name="password"/>.
        /// </summary>
        [Invoke(HasSideEffects = true)]
        public string CreateUser(RegistrationData user, string password)
        {
            if (user == null)
            {
                throw new ArgumentNullException("user");
            }

            // Run this BEFORE creating the user to make sure roles are enabled and the default role is available.
            // If there is a problem with the role manager, it is better to fail now than to fail after the user is created.
            if (!Roles.RoleExists(UserRegistrationService.DefaultRole))
            {
                Roles.CreateRole(UserRegistrationService.DefaultRole);
            }

            // NOTE: ASP.NET by default uses SQL Server Express to create the user database. 
            // CreateUser will fail if you do not have SQL Server Express installed.
            var createStatus = MembershipCreateStatus.Success;
            Membership.CreateUser(user.Email, password, user.Email, null, null, true, null, out createStatus);
            if (createStatus != MembershipCreateStatus.Success)
            {
                switch (createStatus)
                {
                    case MembershipCreateStatus.DuplicateEmail:
                        return "The e-mail address already exists in the database.";
                    case MembershipCreateStatus.InvalidPassword:
                        return "The password is invalid.";
                    case MembershipCreateStatus.UserRejected:
                        return "This user has been blocked.";
                    default:
                        return createStatus.ToString();
                }
            }

            // Assign the user to the default role.
            // This will fail if role management is disabled.
            Roles.AddUserToRole(user.Email, UserRegistrationService.DefaultRole);

            // Set the friendly name (profile setting).
            // This will fail if the web.config is configured incorrectly.
            var profile = ProfileBase.Create(user.Email, true);
            profile.SetPropertyValue("FriendlyName", user.FriendlyName);
            profile.Save();

            // everything worked OK.
            return null;
        }
        /// <summary>
        /// Resets the user password and sends him an e-mail message.
        /// </summary>
        /// <returns>True if successful.</returns>
        [Invoke(HasSideEffects = true)]
        public string ResetPassword(string userName, string email)
        {
            try
            {
                var newPassword = Membership.Provider.ResetPassword(userName, null);
                SendMailMessage(userName, email, newPassword);
                return null;
            }
            catch (Exception x)
            {
                return x.Message;
            }
        }
        /// <summary>
        /// Changes the password.
        /// </summary>
        /// <returns>True if successful.</returns>
        [Invoke(HasSideEffects = true)]
        public string ChangePassword(string userName, string oldPassword, string newPassword)
        {
            try
            {
                Membership.Provider.ChangePassword(userName, oldPassword, newPassword);
                return null;
            }
            catch (Exception x)
            {
                return x.Message;
            }
        }

        // send password recovery message
        void SendMailMessage(string userName, string email, string newPassword)
        {
            // get mail information from config file
            // this information is stored in the web.config file as follows:
            //<!-- settings used to send e-mail notifications to users -->
            //<appSettings>
            //  <add key="SenderAddress" value="senderApp@hotmail.com" />
            //  <add key="SenderName" value="SenderApp" />
            //  <add key="SenderId" value="password" />
            //  <add key="BccList" value="senderApp@hotmail.com,me@hotmail.com" />
            //  <add key="MsgTitle" value="SenderApp Password Reset" />
            //  <add key="MsgBody" value="Your SenderApp password has been set to {0}.\r\n Please log in, then change it to something easier to remember."/>
            //</appSettings>
            var wc = System.Web.Configuration.WebConfigurationManager.AppSettings;
            var senderAddress = wc["SenderAddress"];
            var senderId = wc["SenderId"];
            var senderName = wc["SenderName"];
            var bccList = wc["BccList"];
            var msgTitle = wc["MsgTitle"];
            var msgBody = wc["MsgBody"].Replace("\\r", "\r").Replace("\\n", "\n");

            var mm = new MailMessage();
            mm.From = new MailAddress(senderAddress, senderName);
            mm.To.Add(new MailAddress(email));
            foreach (var s in bccList.Split(','))
            {
                mm.Bcc.Add(new MailAddress(s));
            }
            mm.Subject = msgTitle;
            mm.Body = string.Format(msgBody, newPassword);
            mm.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;

            var ss = new SmtpClient("smtp.live.com");
            ss.Credentials = new NetworkCredential(senderAddress, senderId);
            ss.EnableSsl = true;
            ss.Send(mm);
        }
    }
}