This commit is contained in:
vfedosevich 2015-04-15 05:23:08 -07:00
parent 599e9a8865
commit 84f9f63407
44 changed files with 560 additions and 92 deletions

View file

@ -9529,7 +9529,7 @@ Hello #user.FirstName#,
</ad:if>
<p>
Your password will expire at #user.PasswordExpirationDateTime#. You can reset your own password by visiting the following page:
Your password expiration date is #user.PasswordExpirationDateTime#. You can reset your own password by visiting the following page:
</p>
<a href="#passwordResetLink#">#passwordResetLink#</a>
@ -9581,7 +9581,7 @@ Set @UserPasswordExpirationLetterTextBody = N'==================================
Hello #user.FirstName#,
</ad:if>
Your password will expire at #user.PasswordExpirationDateTime#. You can reset your own password by visiting the following page:
Your password expiration date is #user.PasswordExpirationDateTime#. You can reset your own password by visiting the following page:
#passwordResetLink#
@ -9612,7 +9612,7 @@ DECLARE @UserPasswordResetLetterHtmlBody nvarchar(2500)
Set @UserPasswordResetLetterHtmlBody = N'<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Password expiration notification</title>
<title>Password reset notification</title>
<style type="text/css">
.Summary { background-color: ##ffffff; padding: 5px; }
.Summary .Header { padding: 10px 0px 10px 10px; font-size: 16pt; background-color: ##E5F2FF; color: ##1F4978; border-bottom: solid 2px ##86B9F7; }

View file

@ -18,7 +18,6 @@ using WebsitePanel.Providers.Common;
using WebsitePanel.Providers.HostedSolution;
using WebsitePanel.Providers.ResultObjects;
namespace WebsitePanel.EnterpriseServer.HostedSolution {
using System.Xml.Serialization;
using System.Web.Services;
@ -37,6 +36,8 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution {
[System.Xml.Serialization.XmlIncludeAttribute(typeof(ServiceProviderItem))]
public partial class esOrganizations : Microsoft.Web.Services3.WebServicesClientProtocol {
private System.Threading.SendOrPostCallback CheckPhoneNumberIsInUseOperationCompleted;
private System.Threading.SendOrPostCallback DeletePasswordresetAccessTokenOperationCompleted;
private System.Threading.SendOrPostCallback SetAccessTokenResponseOperationCompleted;
@ -160,6 +161,9 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution {
this.Url = "http://localhost:9002/esOrganizations.asmx";
}
/// <remarks/>
public event CheckPhoneNumberIsInUseCompletedEventHandler CheckPhoneNumberIsInUseCompleted;
/// <remarks/>
public event DeletePasswordresetAccessTokenCompletedEventHandler DeletePasswordresetAccessTokenCompleted;
@ -337,6 +341,53 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution {
/// <remarks/>
public event GetSupportServiceLevelCompletedEventHandler GetSupportServiceLevelCompleted;
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CheckPhoneNumberIsInUse", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public bool CheckPhoneNumberIsInUse(int itemId, string phoneNumber, string userSamAccountName) {
object[] results = this.Invoke("CheckPhoneNumberIsInUse", new object[] {
itemId,
phoneNumber,
userSamAccountName});
return ((bool)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BeginCheckPhoneNumberIsInUse(int itemId, string phoneNumber, string userSamAccountName, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("CheckPhoneNumberIsInUse", new object[] {
itemId,
phoneNumber,
userSamAccountName}, callback, asyncState);
}
/// <remarks/>
public bool EndCheckPhoneNumberIsInUse(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((bool)(results[0]));
}
/// <remarks/>
public void CheckPhoneNumberIsInUseAsync(int itemId, string phoneNumber, string userSamAccountName) {
this.CheckPhoneNumberIsInUseAsync(itemId, phoneNumber, userSamAccountName, null);
}
/// <remarks/>
public void CheckPhoneNumberIsInUseAsync(int itemId, string phoneNumber, string userSamAccountName, object userState) {
if ((this.CheckPhoneNumberIsInUseOperationCompleted == null)) {
this.CheckPhoneNumberIsInUseOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCheckPhoneNumberIsInUseOperationCompleted);
}
this.InvokeAsync("CheckPhoneNumberIsInUse", new object[] {
itemId,
phoneNumber,
userSamAccountName}, this.CheckPhoneNumberIsInUseOperationCompleted, userState);
}
private void OnCheckPhoneNumberIsInUseOperationCompleted(object arg) {
if ((this.CheckPhoneNumberIsInUseCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.CheckPhoneNumberIsInUseCompleted(this, new CheckPhoneNumberIsInUseCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
/// <remarks/>
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/DeletePasswordresetAccessToken", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public void DeletePasswordresetAccessToken(System.Guid accessToken) {
@ -3260,6 +3311,32 @@ namespace WebsitePanel.EnterpriseServer.HostedSolution {
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
public delegate void CheckPhoneNumberIsInUseCompletedEventHandler(object sender, CheckPhoneNumberIsInUseCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class CheckPhoneNumberIsInUseCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal CheckPhoneNumberIsInUseCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
/// <remarks/>
public bool Result {
get {
this.RaiseExceptionIfNecessary();
return ((bool)(this.results[0]));
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
public delegate void DeletePasswordresetAccessTokenCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e);

View file

@ -1675,6 +1675,21 @@ namespace WebsitePanel.EnterpriseServer
DataProvider.SetAccessTokenResponseMessage(accessToken, response);
}
public static bool CheckPhoneNumberIsInUse(int itemId, string phoneNumber, string userSamAccountName = null)
{
// load organization
Organization org = GetOrganization(itemId);
if (org == null)
{
throw new Exception(string.Format("Organization with id '{0}' not found", itemId));
}
Organizations orgProxy = GetOrganizationProxy(org.ServiceId);
return orgProxy.CheckPhoneNumberIsInUse(phoneNumber, userSamAccountName);
}
public static void UpdateOrganizationPasswordSettings(int itemId, OrganizationPasswordSettings settings)
{
TaskManager.StartTask("ORGANIZATION", "UPDATE_PASSWORD_SETTINGS");

View file

@ -48,6 +48,12 @@ namespace WebsitePanel.EnterpriseServer
{
#region Organizations
[WebMethod]
public bool CheckPhoneNumberIsInUse(int itemId, string phoneNumber, string userSamAccountName = null)
{
return OrganizationController.CheckPhoneNumberIsInUse(itemId, phoneNumber, userSamAccountName);
}
[WebMethod]
public void DeletePasswordresetAccessToken(Guid accessToken)
{

View file

@ -100,5 +100,7 @@ namespace WebsitePanel.Providers.HostedSolution
List<OrganizationUser> GetOrganizationUsersWithExpiredPassword(string organizationId, int daysBeforeExpiration);
void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings passwordSettings);
bool CheckPhoneNumberIsInUse(string phoneNumber, string userSamAccountName = null);
}
}

View file

@ -604,6 +604,58 @@ namespace WebsitePanel.Providers.HostedSolution
}
}
public bool CheckPhoneNumberIsInUse(string phoneNumber, string userPrincipalName = null)
{
if (string.IsNullOrEmpty(phoneNumber))
{
return false;
}
phoneNumber = phoneNumber.Replace("+", "");
var userExcludeQuery = string.IsNullOrEmpty(userPrincipalName) ? string.Empty : string.Format("(!(UserPrincipalName={0}))", userPrincipalName);
string query = string.Format("(&" +
"(objectClass=user)" +
"(|" +
"(|(facsimileTelephoneNumber=+{0})(facsimileTelephoneNumber={0}))" +
"(|(homePhone=+{0})(homePhone={0}))" +
"(|(mobile=+{0})(mobile={0}))" +
"(|(pager=+{0})(pager={0}))" +
"(|(telephoneNumber=+{0})(telephoneNumber={0}))" +
")" +
"{1}" +
")", phoneNumber, userExcludeQuery);
using (Domain d = Domain.GetCurrentDomain())
{
using (DirectoryEntry domain = d.GetDirectoryEntry())
{
var search = new DirectorySearcher(domain)
{
SearchScope = SearchScope.Subtree,
Filter = query
};
search.PropertiesToLoad.Add(ADAttributes.Fax);
search.PropertiesToLoad.Add(ADAttributes.HomePhone);
search.PropertiesToLoad.Add(ADAttributes.MobilePhone);
search.PropertiesToLoad.Add(ADAttributes.Pager);
search.PropertiesToLoad.Add(ADAttributes.BusinessPhone);
SearchResult result = search.FindOne();
if (result != null)
{
return true;
}
return false;
}
}
}
public void ApplyPasswordSettings(string organizationId, OrganizationPasswordSettings settings)
{
HostedSolutionLog.LogStart("ApplyPasswordPolicy");
@ -627,8 +679,6 @@ namespace WebsitePanel.Providers.HostedSolution
else
{
UpdateFineGrainedPasswordPolicy(runspace, psoName, settings);
RemoveFineGrainedPasswordPolicy(runspace, psoName);
}
}
catch (Exception ex)
@ -688,7 +738,7 @@ namespace WebsitePanel.Providers.HostedSolution
{
cmd.Parameters.Add("LockoutDuration", new TimeSpan(0, settings.AccountLockoutDuration, 0));
cmd.Parameters.Add("LockoutThreshold", settings.AccountLockoutThreshold);
cmd.Parameters.Add("LockoutObservationWindow", settings.ResetAccountLockoutCounterAfter);
cmd.Parameters.Add("LockoutObservationWindow", new TimeSpan(0, settings.ResetAccountLockoutCounterAfter, 0));
}
ExecuteShellCommand(runspace, cmd);
@ -724,7 +774,7 @@ namespace WebsitePanel.Providers.HostedSolution
{
cmd.Parameters.Add("LockoutDuration", new TimeSpan(0, settings.AccountLockoutDuration, 0));
cmd.Parameters.Add("LockoutThreshold", settings.AccountLockoutThreshold);
cmd.Parameters.Add("LockoutObservationWindow", settings.ResetAccountLockoutCounterAfter);
cmd.Parameters.Add("LockoutObservationWindow", new TimeSpan(0, settings.ResetAccountLockoutCounterAfter, 0));
}
else
{
@ -733,10 +783,7 @@ namespace WebsitePanel.Providers.HostedSolution
cmd.Parameters.Add("LockoutObservationWindow", 0);
}
var result = ExecuteShellCommand(runspace, cmd);
var s = GetFineGrainedPasswordPolicy(runspace, psoName);
ExecuteShellCommand(runspace, cmd);
}
private void RemoveFineGrainedPasswordPolicy(Runspace runspace, string psoName)

View file

@ -12,7 +12,6 @@
// This source code was auto-generated by wsdl, Version=2.0.50727.3038.
//
using WebsitePanel.Providers.Common;
using WebsitePanel.Providers.OS;
using WebsitePanel.Providers.ResultObjects;
@ -97,6 +96,8 @@ namespace WebsitePanel.Providers.HostedSolution {
private System.Threading.SendOrPostCallback ApplyPasswordSettingsOperationCompleted;
private System.Threading.SendOrPostCallback CheckPhoneNumberIsInUseOperationCompleted;
/// <remarks/>
public Organizations() {
this.Url = "http://localhost:9003/Organizations.asmx";
@ -192,6 +193,9 @@ namespace WebsitePanel.Providers.HostedSolution {
/// <remarks/>
public event ApplyPasswordSettingsCompletedEventHandler ApplyPasswordSettingsCompleted;
/// <remarks/>
public event CheckPhoneNumberIsInUseCompletedEventHandler CheckPhoneNumberIsInUseCompleted;
/// <remarks/>
[System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/OrganizationExists", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
@ -1724,6 +1728,51 @@ namespace WebsitePanel.Providers.HostedSolution {
}
}
/// <remarks/>
[System.Web.Services.Protocols.SoapHeaderAttribute("ServiceProviderSettingsSoapHeaderValue")]
[System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/CheckPhoneNumberIsInUse", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
public bool CheckPhoneNumberIsInUse(string phoneNumber, string userSamAccountName) {
object[] results = this.Invoke("CheckPhoneNumberIsInUse", new object[] {
phoneNumber,
userSamAccountName});
return ((bool)(results[0]));
}
/// <remarks/>
public System.IAsyncResult BeginCheckPhoneNumberIsInUse(string phoneNumber, string userSamAccountName, System.AsyncCallback callback, object asyncState) {
return this.BeginInvoke("CheckPhoneNumberIsInUse", new object[] {
phoneNumber,
userSamAccountName}, callback, asyncState);
}
/// <remarks/>
public bool EndCheckPhoneNumberIsInUse(System.IAsyncResult asyncResult) {
object[] results = this.EndInvoke(asyncResult);
return ((bool)(results[0]));
}
/// <remarks/>
public void CheckPhoneNumberIsInUseAsync(string phoneNumber, string userSamAccountName) {
this.CheckPhoneNumberIsInUseAsync(phoneNumber, userSamAccountName, null);
}
/// <remarks/>
public void CheckPhoneNumberIsInUseAsync(string phoneNumber, string userSamAccountName, object userState) {
if ((this.CheckPhoneNumberIsInUseOperationCompleted == null)) {
this.CheckPhoneNumberIsInUseOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCheckPhoneNumberIsInUseOperationCompleted);
}
this.InvokeAsync("CheckPhoneNumberIsInUse", new object[] {
phoneNumber,
userSamAccountName}, this.CheckPhoneNumberIsInUseOperationCompleted, userState);
}
private void OnCheckPhoneNumberIsInUseOperationCompleted(object arg) {
if ((this.CheckPhoneNumberIsInUseCompleted != null)) {
System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
this.CheckPhoneNumberIsInUseCompleted(this, new CheckPhoneNumberIsInUseCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
}
}
/// <remarks/>
public new void CancelAsync(object userState) {
base.CancelAsync(userState);
@ -2113,4 +2162,30 @@ namespace WebsitePanel.Providers.HostedSolution {
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
public delegate void ApplyPasswordSettingsCompletedEventHandler(object sender, System.ComponentModel.AsyncCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
public delegate void CheckPhoneNumberIsInUseCompletedEventHandler(object sender, CheckPhoneNumberIsInUseCompletedEventArgs e);
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.3038")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class CheckPhoneNumberIsInUseCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
private object[] results;
internal CheckPhoneNumberIsInUseCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) :
base(exception, cancelled, userState) {
this.results = results;
}
/// <remarks/>
public bool Result {
get {
this.RaiseExceptionIfNecessary();
return ((bool)(this.results[0]));
}
}
}
}

View file

@ -267,5 +267,11 @@ namespace WebsitePanel.Server
{
Organization.ApplyPasswordSettings(organizationId, passwordSettings);
}
[WebMethod, SoapHeader("settings")]
public bool CheckPhoneNumberIsInUse(string phoneNumber, string userSamAccountName = null)
{
return Organization.CheckPhoneNumberIsInUse(phoneNumber, userSamAccountName);
}
}
}

View file

@ -2,8 +2,8 @@
{
public interface ISmsDistributionService
{
void SendMessage(string phoneFrom, string phone, string message);
bool SendMessage(string phoneFrom, string phone, string message);
void SendMessage(string phone, string message);
bool SendMessage(string phone, string message);
}
}

View file

@ -31,9 +31,9 @@ namespace WebsitePanel.WebDav.Core.Security.Authentication
{
var response = GenerateResponse();
_smsService.SendMessage(WebDavAppConfigManager.Instance.TwilioParameters.PhoneFrom, phoneTo, response);
var result = _smsService.SendMessage(WebDavAppConfigManager.Instance.TwilioParameters.PhoneFrom, phoneTo, response);
return response;
return result ? response : string.Empty;
}
public string GenerateResponse()

View file

@ -6,7 +6,7 @@ namespace WebsitePanel.WebDav.Core.Services
{
public class TwillioSmsDistributionService : ISmsDistributionService
{
private TwilioRestClient _twilioRestClient { get; set; }
private readonly TwilioRestClient _twilioRestClient;
public TwillioSmsDistributionService()
{
@ -14,14 +14,18 @@ namespace WebsitePanel.WebDav.Core.Services
}
public void SendMessage(string phoneFrom, string phone, string message)
public bool SendMessage(string phoneFrom, string phone, string message)
{
_twilioRestClient.SendSmsMessage(phoneFrom, phone, message);
var result = _twilioRestClient.SendSmsMessage(phoneFrom, phone, message);
return string.IsNullOrEmpty(result.Status) == false;
}
public void SendMessage(string phone, string message)
public bool SendMessage(string phone, string message)
{
_twilioRestClient.SendSmsMessage(WebDavAppConfigManager.Instance.TwilioParameters.PhoneFrom, phone, message);
var result = _twilioRestClient.SendSmsMessage(WebDavAppConfigManager.Instance.TwilioParameters.PhoneFrom, phone, message);
return string.IsNullOrEmpty(result.Status) == false;
}
}
}

View file

@ -12,6 +12,12 @@ namespace WebsitePanel.WebDavPortal
#region Account
routes.MapRoute(
name: AccountRouteNames.PhoneNumberIsAvailible,
url: "account/profile/phone-number-availible",
defaults: new { controller = "Account", action = "PhoneNumberIsAvailible" }
);
routes.MapRoute(
name: AccountRouteNames.UserProfile,
url: "account/profile",

View file

@ -16,5 +16,7 @@ namespace WebsitePanel.WebDavPortal.UI.Routes
public const string PasswordResetSms = "PasswordResetSmsRoute";
public const string PasswordResetSendSms = "PasswordResetSendSmsRoute";
public const string PasswordResetFinalStep = "PasswordResetFinalStepRoute";
public const string PhoneNumberIsAvailible = "PhoneNumberIsAvailibleRoute";
}
}

View file

@ -22,7 +22,7 @@ using WebsitePanel.WebDav.Core;
namespace WebsitePanel.WebDavPortal.Controllers
{
[LdapAuthorization]
public class AccountController : Controller
public class AccountController : BaseController
{
private readonly ICryptography _cryptography;
private readonly IAuthenticationService _authenticationService;
@ -94,11 +94,21 @@ namespace WebsitePanel.WebDavPortal.Controllers
int result = UpdateUserProfile(WspContext.User.ItemId, WspContext.User.AccountId, model);
model.AddMessage(MessageType.Success, Resources.UI.UserProfileSuccessfullyUpdated);
AddMessage(MessageType.Success, Resources.UI.UserProfileSuccessfullyUpdated);
return View(model);
}
public JsonResult PhoneNumberIsAvailible()
{
var value = Request.QueryString.AllKeys.Any() ? Request.QueryString.Get(0) :string.Empty;
var result = !WspContext.Services.Organizations.CheckPhoneNumberIsInUse(WspContext.User.ItemId,
value, WspContext.User.Login);
return Json(result, JsonRequestBehavior.AllowGet);
}
[HttpGet]
public ActionResult PasswordChange()
{
@ -118,7 +128,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
if (_authenticationService.ValidateAuthenticationData(WspContext.User.Login, model.OldPassword) == false)
{
model.AddMessage(MessageType.Error, Resources.Messages.OldPasswordIsNotCorrect);
AddMessage(MessageType.Error, Resources.Messages.OldPasswordIsNotCorrect);
return View(model);
}
@ -127,6 +137,12 @@ namespace WebsitePanel.WebDavPortal.Controllers
WspContext.User.ItemId, WspContext.User.AccountId,
model.PasswordEditor.NewPassword);
var user = _authenticationService.LogIn(WspContext.User.Login, model.PasswordEditor.NewPassword);
_authenticationService.CreateAuthenticationTicket(user);
AddMessage(MessageType.Success, Resources.Messages.PasswordSuccessfullyChanged);
return RedirectToRoute(AccountRouteNames.UserProfile);
}
@ -152,7 +168,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
if (exchangeAccount == null)
{
model.AddMessage(MessageType.Error, Resources.Messages.AccountNotFound);
AddMessage(MessageType.Error, Resources.Messages.AccountNotFound);
return View(model);
}
@ -175,7 +191,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
if (model.IsTokenExist == false)
{
model.AddMessage(MessageType.Error, Resources.Messages.IncorrectPasswordResetUrl);
AddMessage(MessageType.Error, Resources.Messages.IncorrectPasswordResetUrl);
return View(model);
}
@ -184,8 +200,14 @@ namespace WebsitePanel.WebDavPortal.Controllers
{
var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId, accessToken.AccountId);
var response = _smsAuthService.SendRequestMessage(user.MobilePhone);
WspContext.Services.Organizations.SetAccessTokenResponse(accessToken.AccessTokenGuid, response);
if (SendPasswordResetSms(accessToken.AccessTokenGuid, user.MobilePhone))
{
AddMessage(MessageType.Success, Resources.Messages.SmsWasSent);
}
else
{
AddMessage(MessageType.Error, Resources.Messages.SmsWasNotSent);
}
}
return View(model);
@ -210,7 +232,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
return RedirectToRoute(AccountRouteNames.PasswordResetFinalStep);
}
model.AddMessage(MessageType.Error, Resources.Messages.IncorrectSmsResponse);
AddMessage(MessageType.Error, Resources.Messages.IncorrectSmsResponse);
return View(model);
}
@ -245,7 +267,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
if (_smsAuthService.VerifyResponse(token, smsResponse) == false)
{
model.AddMessage(MessageType.Error, Resources.Messages.IncorrectSmsResponse);
AddMessage(MessageType.Error, Resources.Messages.IncorrectSmsResponse);
return RedirectToRoute(AccountRouteNames.PasswordResetSms);
}
@ -258,6 +280,8 @@ namespace WebsitePanel.WebDavPortal.Controllers
WspContext.Services.Organizations.DeletePasswordresetAccessToken(token);
AddMessage(MessageType.Success, Resources.Messages.PasswordSuccessfullyChanged);
return RedirectToRoute(AccountRouteNames.Login);
}
@ -275,14 +299,34 @@ namespace WebsitePanel.WebDavPortal.Controllers
var user = WspContext.Services.Organizations.GetUserGeneralSettings(accessToken.ItemId,
accessToken.AccountId);
var response = _smsAuthService.SendRequestMessage(user.MobilePhone);
WspContext.Services.Organizations.SetAccessTokenResponse(accessToken.AccessTokenGuid, response);
if (SendPasswordResetSms(accessToken.AccessTokenGuid, user.MobilePhone))
{
AddMessage(MessageType.Success, Resources.Messages.SmsWasSent);
}
else
{
AddMessage(MessageType.Error, Resources.Messages.SmsWasNotSent);
}
return RedirectToRoute(AccountRouteNames.PasswordResetSms);
}
#region Helpers
private bool SendPasswordResetSms(Guid token, string mobilePhone)
{
var response = _smsAuthService.SendRequestMessage(mobilePhone);
if (string.IsNullOrEmpty(response))
{
return false;
}
WspContext.Services.Organizations.SetAccessTokenResponse(token, response);
return true;
}
private UserProfile GetUserProfileModel(int itemId, int accountId)
{
var user = WspContext.Services.Organizations.GetUserGeneralSettings(itemId, accountId);

View file

@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebsitePanel.WebDavPortal.Models.Common;
using WebsitePanel.WebDavPortal.Models.Common.Enums;
namespace WebsitePanel.WebDavPortal.Controllers
{
public class BaseController : Controller
{
public const string MessagesKey = "messagesKey";
public void AddMessage(MessageType type, string value)
{
var messages = TempData[MessagesKey] as List<Message>;
if (messages == null)
{
messages = new List<Message>();
}
messages.Add(new Message
{
Type = type,
Value = value
});
TempData[MessagesKey] = messages;
}
}
}

View file

@ -42,7 +42,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
{
[ValidateInput(false)]
[LdapAuthorization]
public class FileSystemController : Controller
public class FileSystemController : BaseController
{
private readonly ICryptography _cryptography;
private readonly IWebDavManager _webdavManager;
@ -276,7 +276,7 @@ namespace WebsitePanel.WebDavPortal.Controllers
if (filePathes == null)
{
model.AddMessage(MessageType.Error, Resources.UI.NoFilesAreSelected);
AddMessage(MessageType.Error, Resources.UI.NoFilesAreSelected);
return Json(model);
}

View file

@ -6,7 +6,7 @@ namespace WebsitePanel.WebDavPortal.CustomAttributes
{
public class PhoneNumberAttribute : RegularExpressionAttribute, IClientValidatable
{
public const string PhonePattern = @"^\+?(\d[\d-. ]+)?(\([\d-. ]+\))?[\d-. ]+\d$";
public const string PhonePattern = @"^\+?\d+$";
public PhoneNumberAttribute()
: base(PhonePattern)

View file

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reflection;
using System.Web.Mvc;
using System.Web.Routing;
using WebsitePanel.WebDav.Core;
namespace WebsitePanel.WebDavPortal.CustomAttributes
{
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class UniqueAdPhoneNumberAttribute : RemoteAttribute
{
protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
Type type = Assembly.GetExecutingAssembly()
.GetTypes()
.FirstOrDefault(validationtype => validationtype.Name == string.Format("{0}controller", this.RouteData["controller"].ToString()));
object response = null;
if (type != null)
{
MethodInfo method = type.GetMethods()
.FirstOrDefault(callingMethod => callingMethod.Name.ToLower() == (string.Format("{0}", this.RouteData["action"]).ToString().ToLower()));
if (method != null)
{
object instance = Activator.CreateInstance(type);
response = method.Invoke(instance, new [] { value });
}
}
if (response is bool)
{
var attributes =
validationContext.ObjectType.GetProperty(validationContext.MemberName)
.GetCustomAttributes(typeof(DisplayNameAttribute), true);
string displayName = attributes != null && attributes.Any()
? (attributes[0] as DisplayNameAttribute).DisplayName
: validationContext.DisplayName;
return (bool)response ? ValidationResult.Success :
new ValidationResult(string.Format(Resources.Messages.AlreadyInUse, displayName));
}
return ValidationResult.Success;
}
public UniqueAdPhoneNumberAttribute(string routeName) : base(routeName) { }
public UniqueAdPhoneNumberAttribute(string action, string controller) : base(action, controller) { }
public UniqueAdPhoneNumberAttribute(string action, string controller,
string area) : base(action, controller, area) { }
}
}

View file

@ -59,8 +59,7 @@ namespace WebsitePanel.WebDavPortal.Mapping.Profiles.Account
.ForMember(ti => ti.Country, x => x.MapFrom(hi => hi.Country))
.ForMember(ti => ti.Notes, x => x.MapFrom(hi => hi.Notes))
.ForMember(ti => ti.PasswordExpirationDateTime, x => x.MapFrom(hi => hi.PasswordExpirationDateTime))
.ForMember(ti => ti.ExternalEmail, x => x.MapFrom(hi => hi.ExternalEmail))
.ForMember(ti => ti.Messages, x => x.Ignore());
.ForMember(ti => ti.ExternalEmail, x => x.MapFrom(hi => hi.ExternalEmail));
}
}
}

View file

@ -5,7 +5,7 @@ using WebsitePanel.WebDavPortal.Models.Common.EditorTemplates;
namespace WebsitePanel.WebDavPortal.Models.Account
{
public class PasswordChangeModel : BaseModel
public class PasswordChangeModel
{
[Display(ResourceType = typeof (Resources.UI), Name = "OldPassword")]
[Required(ErrorMessageResourceType = typeof (Resources.Messages), ErrorMessageResourceName = "Required")]

View file

@ -4,7 +4,7 @@ using WebsitePanel.WebDavPortal.Resources;
namespace WebsitePanel.WebDavPortal.Models.Account
{
public class PasswordResetEmailModel : BaseModel
public class PasswordResetEmailModel
{
[Required]
[Display(ResourceType = typeof(Resources.UI), Name = "Email")]

View file

@ -3,7 +3,7 @@ using WebsitePanel.WebDavPortal.Models.Common;
namespace WebsitePanel.WebDavPortal.Models.Account
{
public class PasswordResetSmsModel : BaseModel
public class PasswordResetSmsModel
{
[Required]
public string Sms { get; set; }

View file

@ -4,10 +4,11 @@ using System.ComponentModel.DataAnnotations;
using System.Security.AccessControl;
using WebsitePanel.WebDavPortal.CustomAttributes;
using WebsitePanel.WebDavPortal.Models.Common;
using WebsitePanel.WebDavPortal.UI.Routes;
namespace WebsitePanel.WebDavPortal.Models.Account
{
public class UserProfile : BaseModel
public class UserProfile
{
[Display(ResourceType = typeof(Resources.UI), Name = "PrimaryEmail")]
[Required(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "Required")]
@ -18,8 +19,14 @@ namespace WebsitePanel.WebDavPortal.Models.Account
[Required(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "Required")]
public string DisplayName { get; set; }
public string AccountName { get; set; }
[Display(ResourceType = typeof(Resources.UI), Name = "FirstName")]
[Required(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "Required")]
public string FirstName { get; set; }
public string Initials { get; set; }
[Display(ResourceType = typeof(Resources.UI), Name = "LastName")]
[Required(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "Required")]
public string LastName { get; set; }
public string JobTitle { get; set; }
public string Company { get; set; }
@ -27,20 +34,29 @@ namespace WebsitePanel.WebDavPortal.Models.Account
public string Office { get; set; }
[PhoneNumber(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "PhoneNumberInvalid")]
[UniqueAdPhoneNumber(AccountRouteNames.PhoneNumberIsAvailible, ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "AlreadyInUse")]
[Display(ResourceType = typeof(Resources.UI), Name = "BusinessPhone")]
public string BusinessPhone { get; set; }
[PhoneNumber(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "PhoneNumberInvalid")]
[UniqueAdPhoneNumber(AccountRouteNames.PhoneNumberIsAvailible, ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "AlreadyInUse")]
[Display(ResourceType = typeof(Resources.UI), Name = "Fax")]
public string Fax { get; set; }
[Display(ResourceType = typeof(Resources.UI), Name = "HomePhone")]
[PhoneNumber(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "PhoneNumberInvalid")]
[UniqueAdPhoneNumber(AccountRouteNames.PhoneNumberIsAvailible, ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "AlreadyInUse")]
public string HomePhone { get; set; }
[Display(ResourceType = typeof(Resources.UI), Name = "MobilePhone")]
[Required(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "Required")]
[PhoneNumber(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "PhoneNumberInvalid")]
[UniqueAdPhoneNumber(AccountRouteNames.PhoneNumberIsAvailible, ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "AlreadyInUse")]
public string MobilePhone { get; set; }
[PhoneNumber(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "PhoneNumberInvalid")]
[Display(ResourceType = typeof(Resources.UI), Name = "Pager")]
[UniqueAdPhoneNumber(AccountRouteNames.PhoneNumberIsAvailible,ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "AlreadyInUse")]
public string Pager { get; set; }
[Url(ErrorMessageResourceType = typeof(Resources.Messages), ErrorMessageResourceName = "UrlInvalid", ErrorMessage = null)]

View file

@ -5,7 +5,7 @@ using WebsitePanel.WebDavPortal.Models.Common;
namespace WebsitePanel.WebDavPortal.Models
{
public class AccountModel : BaseModel
public class AccountModel
{
[Required]
[Display(Name = @"Login")]

View file

@ -1,12 +1,11 @@
using System.Collections.Generic;
using System.Web.Mvc;
using WebsitePanel.WebDavPortal.Models.Common.Enums;
namespace WebsitePanel.WebDavPortal.Models.Common
{
public class BaseModel
public class AjaxModel
{
public BaseModel()
public AjaxModel()
{
Messages = new List<Message>();
}

View file

@ -4,7 +4,7 @@ using WebsitePanel.WebDavPortal.CustomAttributes;
namespace WebsitePanel.WebDavPortal.Models.Common.EditorTemplates
{
public class PasswordEditor : BaseModel
public class PasswordEditor
{
[Display(ResourceType = typeof(Resources.UI), Name = "NewPassword")]

View file

@ -3,7 +3,7 @@ using WebsitePanel.WebDavPortal.Models.Common;
namespace WebsitePanel.WebDavPortal.Models
{
public class ErrorModel : BaseModel
public class ErrorModel
{
public int HttpStatusCode { get; set; }
public string Message { get; set; }

View file

@ -3,7 +3,7 @@ using WebsitePanel.WebDavPortal.Models.Common;
namespace WebsitePanel.WebDavPortal.Models.FileSystem
{
public class DeleteFilesModel : BaseModel
public class DeleteFilesModel : AjaxModel
{
public DeleteFilesModel()
{

View file

@ -6,7 +6,7 @@ using WebsitePanel.WebDavPortal.Models.Common;
namespace WebsitePanel.WebDavPortal.Models
{
public class ModelForWebDav : BaseModel
public class ModelForWebDav
{
public IEnumerable<IHierarchyItem> Items { get; set; }
public string UrlSuffix { get; set; }

View file

@ -2,7 +2,7 @@
namespace WebsitePanel.WebDavPortal.Models
{
public class OfficeOnlineModel : BaseModel
public class OfficeOnlineModel
{
public string Url { get; set; }
public string FileName { get; set; }

View file

@ -69,6 +69,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to {0} is already in use.
/// </summary>
public static string AlreadyInUse {
get {
return ResourceManager.GetString("AlreadyInUse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Email is invalid.
/// </summary>
@ -151,7 +160,7 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
/// <summary>
/// Looks up a localized string similar to Text message (SMS) was sent to the phone number associated to your account. If you didn&apos;t recieve text message (SMS) click {0} for new text message (SMS)..
/// Looks up a localized string similar to Please enter the verification code we sent to your phone. If you didn&apos;t receive a code, you can {0}..
/// </summary>
public static string PasswordResetSmsHintFormat {
get {
@ -168,6 +177,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Your password have been successfully changed.
/// </summary>
public static string PasswordSuccessfullyChanged {
get {
return ResourceManager.GetString("PasswordSuccessfullyChanged", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Password should contain at least {0} non-alphanumeric symbols.
/// </summary>
@ -204,6 +222,24 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Text message (SMS) was not sent to your mobile phone. Invalid phone number..
/// </summary>
public static string SmsWasNotSent {
get {
return ResourceManager.GetString("SmsWasNotSent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Text message (SMS) was sent to your mobile phone..
/// </summary>
public static string SmsWasSent {
get {
return ResourceManager.GetString("SmsWasSent", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Url is invalid.
/// </summary>

View file

@ -120,6 +120,9 @@
<data name="AccountNotFound" xml:space="preserve">
<value>Account was not found</value>
</data>
<data name="AlreadyInUse" xml:space="preserve">
<value>{0} is already in use</value>
</data>
<data name="EmailInvalid" xml:space="preserve">
<value>Email is invalid</value>
</data>
@ -148,11 +151,14 @@
<value>A message was sent to your email address. Please check your email for further instructions.</value>
</data>
<data name="PasswordResetSmsHintFormat" xml:space="preserve">
<value>Text message (SMS) was sent to the phone number associated to your account. If you didn't recieve text message (SMS) click {0} for new text message (SMS).</value>
<value>Please enter the verification code we sent to your phone. If you didn't receive a code, you can {0}.</value>
</data>
<data name="PasswordResetUserReason" xml:space="preserve">
<value>Webdav portal user request.</value>
</data>
<data name="PasswordSuccessfullyChanged" xml:space="preserve">
<value>Your password have been successfully changed</value>
</data>
<data name="PasswordSymbolsCountFormat" xml:space="preserve">
<value>Password should contain at least {0} non-alphanumeric symbols</value>
</data>
@ -165,6 +171,12 @@
<data name="Required" xml:space="preserve">
<value>{0} field is required</value>
</data>
<data name="SmsWasNotSent" xml:space="preserve">
<value>Text message (SMS) was not sent to your mobile phone. Invalid phone number.</value>
</data>
<data name="SmsWasSent" xml:space="preserve">
<value>Text message (SMS) was sent to your mobile phone.</value>
</data>
<data name="UrlInvalid" xml:space="preserve">
<value>Url is invalid</value>
</data>

View file

@ -627,6 +627,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Enter your email address to reset your password. You may need to check your spam folder..
/// </summary>
public static string PasswordResetEmailInfo {
get {
return ResourceManager.GetString("PasswordResetEmailInfo", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to PB.
/// </summary>
@ -798,6 +807,15 @@ namespace WebsitePanel.WebDavPortal.Resources {
}
}
/// <summary>
/// Looks up a localized string similar to Try again.
/// </summary>
public static string TryAgain {
get {
return ResourceManager.GetString("TryAgain", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Type.
/// </summary>

View file

@ -384,4 +384,10 @@
<data name="Zip" xml:space="preserve">
<value>Zip/Postal Code</value>
</data>
<data name="PasswordResetEmailInfo" xml:space="preserve">
<value>Enter your email address to reset your password. You may need to check your spam folder.</value>
</data>
<data name="TryAgain" xml:space="preserve">
<value>Try again</value>
</data>
</root>

View file

@ -3,6 +3,7 @@
@model WebsitePanel.WebDavPortal.Models.AccountModel
@{
ViewBag.Title = "Login";
//Layout = "~/Views/Shared/_Layout.cshtml";
}
<br/>

View file

@ -22,7 +22,7 @@
@Html.EditorFor(x=>x.PasswordEditor)
<div class="form-group">
<div class="col-sm-offset-4 col-sm-10">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">@UI.ChangePassword</button>
</div>
</div>

View file

@ -8,24 +8,16 @@
<div class="container row">
@using (Html.BeginRouteForm(AccountRouteNames.PasswordResetEmail, FormMethod.Post, new { @class = "form-horizontal user-password-reset-email bs-val-styles col-lg-10 col-lg-offset-3", id = "user-password-reset" }))
@using (Html.BeginRouteForm(AccountRouteNames.PasswordResetEmail, FormMethod.Post, new { @class = "user-password-reset-email bs-val-styles col-lg-10 col-lg-offset-3", id = "user-password-reset" }))
{
<div class="form-group">
<h3>@UI.PasswordReset</h3>
</div>
<div class="form-group">
<label for="@Html.IdFor(x => x.Email)" class="col-sm-2 control-label">@UI.Email</label>
<div class="col-sm-10">
<label for="@Html.IdFor(x => x.Email)" class="control-label">@UI.PasswordResetEmailInfo</label>
@Html.TextBoxFor(x => x.Email, new { @class = "form-control", placeholder = UI.Email })
@Html.ValidationMessageFor(x => x.Email)
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">@UI.SendEmail</button>
</div>
</div>
}
</div>

View file

@ -9,7 +9,7 @@
@if (Model.IsTokenExist)
{
<div class="container row">
@using (Html.BeginRouteForm(AccountRouteNames.PasswordResetSms, FormMethod.Post, new {@class = "form-horizontal user-password-reset-sms bs-val-styles col-lg-9 col-lg-offset-3", id = "user-password-reset"}))
@using (Html.BeginRouteForm(AccountRouteNames.PasswordResetSms, FormMethod.Post, new {@class = "user-password-reset-sms bs-val-styles col-lg-9 col-lg-offset-3", id = "user-password-reset"}))
{
@Html.HiddenFor(x=>x.IsTokenExist)
@ -17,21 +17,13 @@
<h3>@UI.PasswordReset</h3>
</div>
<div class="form-group">
<span>@Html.Raw(string.Format(Messages.PasswordResetSmsHintFormat, Html.RouteLink(UI.Here.ToLowerInvariant(), AccountRouteNames.PasswordResetSendSms)))</span>
</div>
<div class="form-group">
<label for="@Html.IdFor(x => x.Sms)" class="col-sm-2 control-label">@UI.Sms</label>
<div class="col-sm-10">
<label for="@Html.IdFor(x => x.Sms)" class="control-label">@Html.Raw(string.Format(Messages.PasswordResetSmsHintFormat, Html.RouteLink(UI.TryAgain.ToLowerInvariant(), AccountRouteNames.PasswordResetSendSms)))</label>
<div >
@Html.TextBoxFor(x => x.Sms, new {@class = "form-control", placeholder = UI.Sms})
@Html.ValidationMessageFor(x => x.Sms)
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">@UI.Next</button>
</div>
</div>
}
</div>
}

View file

@ -16,6 +16,14 @@
@Html.HiddenFor(x => x.PrimaryEmailAddress)
@Html.AntiForgeryToken()
if (ViewData.ModelState.Any(x => x.Value.Errors.Any()))
{
<div class="alert alert-danger">
<a class="close" data-dismiss="alert">&times;</a>
@Html.ValidationSummary(false)
</div>
}
<div class="panel-group" id="accordion" role="tablist" aria-multiselectable="true">
<div class="panel panel-default">
<div class="panel-heading" role="tab" id="heading-general-information">
@ -102,6 +110,7 @@
<label for="@Html.IdFor(x => x.BusinessPhone)" class="col-sm-2 control-label">@UI.BusinessPhone</label>
<div class="col-sm-10">
@Html.TextBoxFor(x => x.BusinessPhone, new { @class = "form-control", placeholder = UI.BusinessPhone })
@Html.ValidationMessageFor(x => x.BusinessPhone)
</div>
</div>
@ -109,6 +118,7 @@
<label for="@Html.IdFor(x => x.Fax)" class="col-sm-2 control-label">@UI.Fax</label>
<div class="col-sm-10">
@Html.TextBoxFor(x => x.Fax, new { @class = "form-control", placeholder = UI.Fax })
@Html.ValidationMessageFor(x => x.Fax)
</div>
</div>
@ -116,6 +126,7 @@
<label for="@Html.IdFor(x => x.HomePhone)" class="col-sm-2 control-label">@UI.HomePhone</label>
<div class="col-sm-10">
@Html.TextBoxFor(x => x.HomePhone, new { @class = "form-control", placeholder = UI.HomePhone })
@Html.ValidationMessageFor(x => x.HomePhone)
</div>
</div>
@ -123,6 +134,7 @@
<label for="@Html.IdFor(x => x.MobilePhone)" class="col-sm-2 control-label">@UI.MobilePhone</label>
<div class="col-sm-10">
@Html.TextBoxFor(x => x.MobilePhone, new { @class = "form-control", placeholder = UI.MobilePhone })
@Html.ValidationMessageFor(x=>x.MobilePhone)
</div>
</div>
@ -130,6 +142,7 @@
<label for="@Html.IdFor(x => x.Pager)" class="col-sm-2 control-label">@UI.Pager</label>
<div class="col-sm-10">
@Html.TextBoxFor(x => x.Pager, new { @class = "form-control", placeholder = UI.Pager })
@Html.ValidationMessageFor(x => x.Pager)
</div>
</div>

View file

@ -3,7 +3,7 @@
@model WebsitePanel.WebDavPortal.Models.ModelForWebDav
<div class="prevent-deselect container">
<div class="prevent-deselect container row">
<table id="webdav-items-table" class="display table table-striped table-bordered noselect" cellspacing="0" width="100%">
<thead>
<tr>

View file

@ -6,7 +6,7 @@
@model WebsitePanel.WebDavPortal.Models.ModelForWebDav
<div id="breadcrumb_wrapper" class="container prevent-deselect">
<div id="breadcrumb_wrapper" class="container row prevent-deselect">
@if (Model != null)
{
string header = WspContext.User.OrganizationId;
@ -48,7 +48,7 @@
</div>
@if (string.IsNullOrEmpty(Model.SearchValue))
{
<div class="container file-actions-menu prevent-deselect">
<div class="container file-actions-menu row prevent-deselect">
@if (Model.Permissions.HasFlag(WebDavPermissions.Write))
{
<div class="file-deletion navbar-left">

View file

@ -2,11 +2,17 @@
@using Ninject
@using WebsitePanel.WebDav.Core
@using WebsitePanel.WebDav.Core.Config
@using WebsitePanel.WebDavPortal.Controllers
@using WebsitePanel.WebDavPortal.DependencyInjection
@using WebsitePanel.WebDavPortal.Models
@using WebsitePanel.WebDavPortal.Models.Common
@using WebsitePanel.WebDavPortal.Resources
@using WebsitePanel.WebDavPortal.UI.Routes;
@model WebsitePanel.WebDavPortal.Models.Common.BaseModel
@{
var messages = TempData[BaseController.MessagesKey] as List<Message> ?? new List<Message>();
}
<!DOCTYPE html>
<html>
@ -73,14 +79,12 @@
</script>
}
@if (Model != null)
{
<script>
$(document).ready(function () {
wsp.messages.showMessages(@Html.Raw(Json.Encode(Model.Messages)));
wsp.messages.showMessages(@Html.Raw(Json.Encode(messages)));
});
</script>
}
@RenderSection("scripts", required: false)
</body>

View file

@ -167,6 +167,7 @@
<Compile Include="Configurations\ControllerConfigurations\OwaControllerConfiguration.cs" />
<Compile Include="Constants\Formats.cs" />
<Compile Include="Controllers\AccountController.cs" />
<Compile Include="Controllers\BaseController.cs" />
<Compile Include="Controllers\ErrorController.cs" />
<Compile Include="Controllers\FileSystemController.cs" />
<Compile Include="Controllers\Api\OwaController.cs" />
@ -174,6 +175,7 @@
<Compile Include="CustomAttributes\LdapAuthorizationAttribute.cs" />
<Compile Include="CustomAttributes\PhoneNumberAttribute.cs" />
<Compile Include="CustomAttributes\OrganizationPasswordPolicyAttribute.cs" />
<Compile Include="CustomAttributes\UniqueAdPhoneNumberAttribute.cs" />
<Compile Include="DependencyInjection\NinjectDependecyResolver.cs" />
<Compile Include="DependencyInjection\PortalDependencies.cs" />
<Compile Include="DependencyInjection\Providers\HttpSessionStateProvider.cs" />
@ -198,7 +200,7 @@
<Compile Include="Models\Account\PasswordResetEmailModel.cs" />
<Compile Include="Models\Account\PasswordResetSmsModel.cs" />
<Compile Include="Models\Account\UserProfile.cs" />
<Compile Include="Models\Common\BaseModel.cs" />
<Compile Include="Models\Common\AjaxModel.cs" />
<Compile Include="Models\Common\DataTable\JqueryDataTableBaseEntity.cs" />
<Compile Include="Models\Common\DataTable\JqueryDataTablesResponse.cs" />
<Compile Include="Models\Common\DataTable\JqueryDataTableColumn.cs" />
@ -490,6 +492,7 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Models\FileSystem\Enums\" />
<Folder Include="Views\Base\" />
<Folder Include="Views\Owa\" />
</ItemGroup>
<ItemGroup>

View file

@ -48,7 +48,7 @@
</li>
<li>
<asp:HyperLink ID="lnkOrganizationUserPasswordResetLetter" runat="server" meta:resourcekey="lnkOrganizationUserPasswordResetLetter"
Text="User Password Expiration Letter" NavigateUrl='<%# GetSettingsLink("UserPasswordResetLetter", "SettingsUserPasswordExpirationLetter") %>'></asp:HyperLink>
Text="User Password Reset Letter" NavigateUrl='<%# GetSettingsLink("UserPasswordResetLetter", "SettingsUserPasswordResetLetter") %>'></asp:HyperLink>
</li>
</ul>
</div>