using System; using System.Data; using System.Configuration; using System.Collections; using umbraco.DataLayer; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; namespace umbraco.BusinessLogic { /// /// represents a Umbraco back end user /// public class User { private int _id; private bool _isInitialized; private string _name; private string _loginname; private int _startnodeid; private int _startmediaid; private string _email; private string _language = ""; private UserType _usertype; private bool _userNoConsole; private bool _userDisabled; private bool _defaultToLiveEditing; private Hashtable _cruds = new Hashtable(); private bool _crudsInitialized = false; private Hashtable _notifications = new Hashtable(); private bool _notificationsInitialized = false; private static ISqlHelper SqlHelper { get { return Application.SqlHelper; } } /// /// Initializes a new instance of the class. /// /// The ID. public User(int ID) { setupUser(ID); } /// /// Initializes a new instance of the class. /// /// The ID. /// if set to true [no setup]. public User(int ID, bool noSetup) { _id = ID; } /// /// Initializes a new instance of the class. /// /// The login. /// The password. public User(string Login, string Password) { setupUser(getUserId(Login, Password)); } /// /// Initializes a new instance of the class. /// /// The login. public User(string Login) { setupUser(getUserId(Login)); } private void setupUser(int ID) { _id = ID; using (IRecordsReader dr = SqlHelper.ExecuteReader( "Select userNoConsole, userDisabled, userType,startStructureID, startMediaId, userName,userLogin,userEmail,userDefaultPermissions, userLanguage, defaultToLiveEditing from umbracoUser where id = @id", SqlHelper.CreateParameter("@id", ID))) { if (dr.Read()) { _userNoConsole = dr.GetBoolean("usernoconsole"); _userDisabled = dr.GetBoolean("userDisabled"); _name = dr.GetString("userName"); _loginname = dr.GetString("userLogin"); _email = dr.GetString("userEmail"); _language = dr.GetString("userLanguage"); _startnodeid = dr.GetInt("startStructureID"); if (!dr.IsNull("startMediaId")) _startmediaid = dr.GetInt("startMediaID"); _usertype = UserType.GetUserType(dr.GetShort("UserType")); _defaultToLiveEditing = dr.GetBoolean("defaultToLiveEditing"); } else { throw new ArgumentException("No User exists with ID " + ID.ToString()); } } _isInitialized = true; } /// /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility /// public void Save() { OnSaving(EventArgs.Empty); } /// /// Gets or sets the users name. /// /// The name. public string Name { get { if (!_isInitialized) setupUser(_id); return _name; } set { _name = value; SqlHelper.ExecuteNonQuery("Update umbracoUser set UserName = @userName where id = @id", SqlHelper.CreateParameter("@userName", value), SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } } /// /// Gets or sets the users email. /// /// The email. public string Email { get { if (!_isInitialized) setupUser(_id); return _email; } set { _email = value; SqlHelper.ExecuteNonQuery("Update umbracoUser set UserEmail = @email where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@email", value)); FlushFromCache(); } } /// /// Gets or sets the users language. /// /// The language. public string Language { get { if (!_isInitialized) setupUser(_id); return _language; } set { _language = value; SqlHelper.ExecuteNonQuery("Update umbracoUser set userLanguage = @language where id = @id", SqlHelper.CreateParameter("@language", value), SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } } /// /// Gets or sets the users password. /// /// The password. public string Password { get { return GetPassword(); } set { SqlHelper.ExecuteNonQuery("Update umbracoUser set UserPassword = @pw where id = @id", SqlHelper.CreateParameter("@pw", value), SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } } /// /// Gets the password. /// /// public string GetPassword() { return SqlHelper.ExecuteScalar("select UserPassword from umbracoUser where id = @id", SqlHelper.CreateParameter("@id", this.Id)); } static string _connstring = GlobalSettings.DbDSN; /// /// Determines whether this user is an admin. /// /// /// true if this user is admin; otherwise, false. /// public bool IsAdmin() { return UserType.Alias == "admin"; } public bool ValidatePassword(string password) { string userLogin = SqlHelper.ExecuteScalar("select userLogin from umbracoUser where userLogin = @login and UserPassword = @pw", SqlHelper.CreateParameter("@pw", password), SqlHelper.CreateParameter("@login", LoginName) ); return userLogin == this.LoginName; } /// /// Determines whether this user is the root (super user). /// /// /// true if this user is root; otherwise, false. /// public bool IsRoot() { return Id == 0; } /// /// Gets the applications which the user has access to. /// /// The users applications. public Application[] Applications { get { if (!_isInitialized) setupUser(_id); var apps = new List(); using (IRecordsReader appIcons = SqlHelper.ExecuteReader("select appAlias, appIcon, appname from umbracoApp app join umbracoUser2app u2a on u2a.app = app.appAlias and u2a.[user] = @userID order by app.sortOrder", SqlHelper.CreateParameter("@userID", this.Id))) { while (appIcons.Read()) { Application tmp = new Application(); tmp.name = appIcons.GetString("appName"); tmp.icon = appIcons.GetString("appIcon"); tmp.alias = appIcons.GetString("appAlias"); apps.Add(tmp); } } return apps.ToArray(); } } /// /// Gets or sets the users login name /// /// The loginname. public string LoginName { get { if (!_isInitialized) setupUser(_id); return _loginname; } set { if (!ensureUniqueLoginName(value, this)) throw new Exception(String.Format("A user with the login '{0}' already exists", value)); _loginname = value; SqlHelper.ExecuteNonQuery("Update umbracoUser set UserLogin = @login where id = @id", SqlHelper.CreateParameter("@login", value), SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } } private static bool ensureUniqueLoginName(string loginName, User currentUser) { User[] u = User.getAllByLoginName(loginName); if (u.Length != 0) { if (u[0].Id != currentUser.Id) return false; } return true; } /// /// Validates the users credentials. /// /// The login name. /// The password. /// public static bool validateCredentials(string lname, string passw) { return validateCredentials(lname, passw, true); } /// /// Validates the users credentials. /// /// The login name. /// The password. /// if set to true [check for umbraco console access]. /// public static bool validateCredentials(string lname, string passw, bool checkForUmbracoConsoleAccess) { string consoleCheckSql = ""; if (checkForUmbracoConsoleAccess) consoleCheckSql = "and userNoConsole = 0 "; object tmp = SqlHelper.ExecuteScalar( "select id from umbracoUser where userDisabled = 0 " + consoleCheckSql + " and userLogin = @login and userPassword = @pw", SqlHelper.CreateParameter("@login", lname), SqlHelper.CreateParameter("@pw", passw) ); // Logging if (tmp == null) BusinessLogic.Log.Add(BusinessLogic.LogTypes.LoginFailure, BusinessLogic.User.GetUser(0), -1, "Login: '" + lname + "' failed, from IP: " + System.Web.HttpContext.Current.Request.UserHostAddress); return (tmp != null); } /// /// Gets or sets the type of the user. /// /// The type of the user. public UserType UserType { get { if (!_isInitialized) setupUser(_id); return _usertype; } set { _usertype = value; SqlHelper.ExecuteNonQuery( @"Update umbracoUser set userType = @type where id = @id", SqlHelper.CreateParameter("@type", value.Id), SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } } /// /// Gets all users /// /// public static User[] getAll() { IRecordsReader dr; dr = SqlHelper.ExecuteReader("Select id from umbracoUser"); List users = new List(); while (dr.Read()) { users.Add(User.GetUser(dr.GetInt("id"))); } dr.Close(); return users.OrderBy(x => x.Name).ToArray(); } /// /// Gets the current user (logged in) /// /// A user or null public static User GetCurrent() { if (umbraco.BasePages.BasePage.umbracoUserContextID != "") return BusinessLogic.User.GetUser(umbraco.BasePages.BasePage.GetUserId(umbraco.BasePages.BasePage.umbracoUserContextID)); else return null; } /// /// Gets all users by email. /// /// The email. /// public static User[] getAllByEmail(string email) { List retVal = new List(); System.Collections.ArrayList tmpContainer = new System.Collections.ArrayList(); IRecordsReader dr; dr = SqlHelper.ExecuteReader( "Select id from umbracoUser where userEmail LIKE @email", SqlHelper.CreateParameter("@email", String.Format("%{0}%", email))); while (dr.Read()) { retVal.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); } dr.Close(); return retVal.ToArray(); } /// /// Gets all users by login name. /// /// The login. /// public static User[] getAllByLoginName(string login) { return GetAllByLoginName(login, false).ToArray(); } public static IEnumerable GetAllByLoginName(string login, bool partialMatch) { var users = new List(); if (partialMatch) { using (var dr = SqlHelper.ExecuteReader( "Select id from umbracoUser where userLogin LIKE @login", SqlHelper.CreateParameter("@login", String.Format("%{0}%", login)))) { while (dr.Read()) { users.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); } } } else { using (var dr = SqlHelper.ExecuteReader( "Select id from umbracoUser where userLogin=@login", SqlHelper.CreateParameter("@login", login))) { while (dr.Read()) { users.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); } } } return users; } /// /// Create a new user. /// /// The full name. /// The login name. /// The password. /// The user type. [MethodImpl(MethodImplOptions.Synchronized)] public static User MakeNew(string name, string lname, string passw, UserType ut) { SqlHelper.ExecuteNonQuery(@" insert into umbracoUser (UserType,startStructureId,startMediaId, UserName, userLogin, userPassword, userEmail,userLanguage) values (@type,-1,-1,@name,@lname,@pw,'',@lang)", SqlHelper.CreateParameter("@lang", GlobalSettings.DefaultUILanguage), SqlHelper.CreateParameter("@name", name), SqlHelper.CreateParameter("@lname", lname), SqlHelper.CreateParameter("@type", ut.Id), SqlHelper.CreateParameter("@pw", passw)); var u = new User(lname); u.OnNew(EventArgs.Empty); return u; } /// /// Creates a new user. /// /// The name. /// The lname. /// The passw. /// The email. /// The ut. [MethodImpl(MethodImplOptions.Synchronized)] public static User MakeNew(string name, string lname, string passw, string email, UserType ut) { SqlHelper.ExecuteNonQuery(@" insert into umbracoUser (UserType,startStructureId,startMediaId, UserName, userLogin, userPassword, userEmail,userLanguage) values (@type,-1,-1,@name,@lname,@pw,@email,@lang)", SqlHelper.CreateParameter("@lang", GlobalSettings.DefaultUILanguage), SqlHelper.CreateParameter("@name", name), SqlHelper.CreateParameter("@lname", lname), SqlHelper.CreateParameter("@email", email), SqlHelper.CreateParameter("@type", ut.Id), SqlHelper.CreateParameter("@pw", passw)); var u = new User(lname); u.OnNew(EventArgs.Empty); return u; } /// /// Updates the name, login name and password for the user with the specified id. /// /// The id. /// The name. /// The lname. /// The email. /// The ut. public static void Update(int id, string name, string lname, string email, UserType ut) { if (!ensureUniqueLoginName(lname, User.GetUser(id))) throw new Exception(String.Format("A user with the login '{0}' already exists", lname)); SqlHelper.ExecuteNonQuery(@"Update umbracoUser set userName=@name, userLogin=@lname, userEmail=@email, UserType=@type where id = @id", SqlHelper.CreateParameter("@name", name), SqlHelper.CreateParameter("@lname", lname), SqlHelper.CreateParameter("@email", email), SqlHelper.CreateParameter("@type", ut.Id), SqlHelper.CreateParameter("@id", id)); } /// /// Gets the ID from the user with the specified login name and password /// /// The login name. /// The password. /// a user ID public static int getUserId(string lname, string passw) { return getUserId("select id from umbracoUser where userDisabled = 0 and userNoConsole = 0 and userLogin = @login and userPassword = @pw", SqlHelper.CreateParameter("@login", lname), SqlHelper.CreateParameter("@pw", passw)); } /// /// Gets the ID from the user with the specified login name /// /// The login name. /// a user ID public static int getUserId(string lname) { return getUserId("select id from umbracoUser where userLogin = @login", SqlHelper.CreateParameter("@login", lname)); } private static int getUserId(string query, params IParameter[] parameterValues) { object userId = SqlHelper.ExecuteScalar(query, parameterValues); return (userId != null && userId != DBNull.Value) ? int.Parse(userId.ToString()) : -1; } /// /// Deletes this instance. /// [Obsolete("Deleting users are NOT supported as history needs to be kept. Please use the disable() method instead")] public void delete() { //make sure you cannot delete the admin user! if (this.Id == 0) throw new InvalidOperationException("The Administrator account cannot be deleted"); OnDeleting(EventArgs.Empty); //would be better in the notifications class but since we can't reference the cms project (poorly architected) we need to use raw sql SqlHelper.ExecuteNonQuery("delete from umbracoUser2NodeNotify where userId = @userId", SqlHelper.CreateParameter("@userId", Id)); //would be better in the permissions class but since we can't reference the cms project (poorly architected) we need to use raw sql SqlHelper.ExecuteNonQuery("delete from umbracoUser2NodePermission where userId = @userId", SqlHelper.CreateParameter("@userId", Id)); //delete the assigned applications clearApplications(); SqlHelper.ExecuteNonQuery("delete from umbracoUserLogins where userID = @id", SqlHelper.CreateParameter("@id", Id)); SqlHelper.ExecuteNonQuery("delete from umbracoUser where id = @id", SqlHelper.CreateParameter("@id", Id)); FlushFromCache(); } /// /// Disables this instance. /// public void disable() { OnDisabling(EventArgs.Empty); //change disabled and userLogin (prefix with yyyyMMdd_ ) this.Disabled = true; //can't rename if it's going to take up too many chars if (this.LoginName.Length + 9 <= 125) { this.LoginName = DateTime.Now.ToString("yyyyMMdd") + "_" + this.LoginName; } } /// /// Gets the users permissions based on a nodes path /// /// The path. /// public string GetPermissions(string Path) { if (!_isInitialized) setupUser(_id); string cruds = UserType.DefaultPermissions; if (!_crudsInitialized) initCruds(); foreach (string nodeId in Path.Split(',')) { if (_cruds.ContainsKey(int.Parse(nodeId))) cruds = _cruds[int.Parse(nodeId)].ToString(); } return cruds; } /// /// Initializes the user node permissions /// public void initCruds() { if (!_isInitialized) setupUser(_id); // clear cruds System.Web.HttpContext.Current.Application.Lock(); _cruds.Clear(); System.Web.HttpContext.Current.Application.UnLock(); using (IRecordsReader dr = SqlHelper.ExecuteReader("select * from umbracoUser2NodePermission where userId = @userId order by nodeId", SqlHelper.CreateParameter("@userId", this.Id))) { // int currentId = -1; while (dr.Read()) { if (!_cruds.ContainsKey(dr.GetInt("nodeId"))) _cruds.Add(dr.GetInt("nodeId"), String.Empty); _cruds[dr.GetInt("nodeId")] += dr.GetString("permission"); } } _crudsInitialized = true; } /// /// Gets a users notifications for a specified node path. /// /// The node path. /// public string GetNotifications(string Path) { string notifications = ""; if (!_notificationsInitialized) initNotifications(); foreach (string nodeId in Path.Split(',')) { if (_notifications.ContainsKey(int.Parse(nodeId))) notifications = _notifications[int.Parse(nodeId)].ToString(); } return notifications; } /// /// Clears the internal hashtable containing cached information about notifications for the user /// public void resetNotificationCache() { _notificationsInitialized = false; _notifications.Clear(); } /// /// Initializes the notifications and caches them. /// public void initNotifications() { if (!_isInitialized) setupUser(_id); using (IRecordsReader dr = SqlHelper.ExecuteReader("select * from umbracoUser2NodeNotify where userId = @userId order by nodeId", SqlHelper.CreateParameter("@userId", this.Id))) { while (dr.Read()) { int nodeId = dr.GetInt("nodeId"); if (!_notifications.ContainsKey(nodeId)) _notifications.Add(nodeId, String.Empty); _notifications[nodeId] += dr.GetString("action"); } } _notificationsInitialized = true; } /// /// Gets the user id. /// /// The id. public int Id { get { return _id; } } /// /// Clears the list of applications the user has access to. /// public void clearApplications() { SqlHelper.ExecuteNonQuery("delete from umbracoUser2app where [user] = @id", SqlHelper.CreateParameter("@id", this.Id)); } /// /// Adds a application to the list of allowed applications /// /// The app alias. public void addApplication(string AppAlias) { SqlHelper.ExecuteNonQuery("insert into umbracoUser2app ([user],app) values (@id, @app)", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@app", AppAlias)); } /// /// Gets or sets a value indicating whether the user has access to the Umbraco back end. /// /// true if the user has access to the back end; otherwise, false. public bool NoConsole { get { if (!_isInitialized) setupUser(_id); return _userNoConsole; } set { _userNoConsole = value; SqlHelper.ExecuteNonQuery("update umbracoUser set userNoConsole = @userNoConsole where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@userNoConsole", _userNoConsole)); FlushFromCache(); } } /// /// Gets or sets a value indicating whether this is disabled. /// /// true if disabled; otherwise, false. public bool Disabled { get { if (!_isInitialized) setupUser(_id); return _userDisabled; } set { _userDisabled = value; SqlHelper.ExecuteNonQuery("update umbracoUser set userDisabled = @userDisabled where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@userDisabled", _userDisabled)); FlushFromCache(); } } /// /// Gets or sets a value indicating whether a user should be redirected to liveediting by default. /// /// /// true if defaults to live editing; otherwise, false. /// public bool DefaultToLiveEditing { get { if (!_isInitialized) setupUser(_id); return _defaultToLiveEditing; } set { _defaultToLiveEditing = value; SqlHelper.ExecuteNonQuery("update umbracoUser set defaultToLiveEditing = @defaultToLiveEditing where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@defaultToLiveEditing", _defaultToLiveEditing)); FlushFromCache(); } } /// /// Gets or sets the start content node id. /// /// The start node id. public int StartNodeId { get { if (!_isInitialized) setupUser(_id); return _startnodeid; } set { _startnodeid = value; SqlHelper.ExecuteNonQuery("update umbracoUser set startStructureId = @start where id = @id", SqlHelper.CreateParameter("@start", value), SqlHelper.CreateParameter("@id", this.Id)); FlushFromCache(); } } /// /// Gets or sets the start media id. /// /// The start media id. public int StartMediaId { get { if (!_isInitialized) setupUser(_id); return _startmediaid; } set { _startmediaid = value; SqlHelper.ExecuteNonQuery("update umbracoUser set startMediaId = @start where id = @id", SqlHelper.CreateParameter("@start", value), SqlHelper.CreateParameter("@id", this.Id)); FlushFromCache(); } } /// /// Flushes the user from cache. /// protected void FlushFromCache() { OnFlushingFromCache(EventArgs.Empty); if (System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", Id.ToString())] != null) System.Web.HttpRuntime.Cache.Remove(string.Format("UmbracoUser{0}", Id.ToString())); } /// /// Gets the user with a specified ID /// /// The id. /// public static User GetUser(int id) { if (System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", id.ToString())] == null) { try { User u = new User(id); System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoUser{0}", id.ToString()), u); } catch (ArgumentException) { //no user was found return null; } } return (User)System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", id.ToString())]; } //EVENTS /// /// The save event handler /// public delegate void SavingEventHandler(User sender, EventArgs e); /// /// The new event handler /// public delegate void NewEventHandler(User sender, EventArgs e); /// /// The disable event handler /// public delegate void DisablingEventHandler(User sender, EventArgs e); /// /// The delete event handler /// public delegate void DeletingEventHandler(User sender, EventArgs e); /// /// The Flush User from cache event handler /// public delegate void FlushingFromCacheEventHandler(User sender, EventArgs e); /// /// Occurs when [saving]. /// public static event SavingEventHandler Saving; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnSaving(EventArgs e) { if (Saving != null) Saving(this, e); } /// /// Occurs when [new]. /// public static event NewEventHandler New; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnNew(EventArgs e) { if (New != null) New(this, e); } /// /// Occurs when [disabling]. /// public static event DisablingEventHandler Disabling; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnDisabling(EventArgs e) { if (Disabling != null) Disabling(this, e); } /// /// Occurs when [deleting]. /// public static event DeletingEventHandler Deleting; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnDeleting(EventArgs e) { if (Deleting != null) Deleting(this, e); } /// /// Occurs when [flushing from cache]. /// public static event FlushingFromCacheEventHandler FlushingFromCache; /// /// Raises the event. /// /// The instance containing the event data. protected virtual void OnFlushingFromCache(EventArgs e) { if (FlushingFromCache != null) FlushingFromCache(this, e); } } }