Implemented Last Login and Created columns for User Manager. Fixes #NX-1219
authorEriks Jenkevics <eriks@netxms.org>
Thu, 17 Aug 2017 15:42:38 +0000 (18:42 +0300)
committerEriks Jenkevics <eriks@netxms.org>
Fri, 18 Aug 2017 13:05:08 +0000 (16:05 +0300)
13 files changed:
include/netxmsdb.h
sql/schema.in
src/java/client/netxms-client/src/main/java/org/netxms/client/users/AbstractUserObject.java
src/java/netxms-eclipse/UserManager/src/org/netxms/ui/eclipse/usermanager/views/UserManagementView.java
src/java/netxms-eclipse/UserManager/src/org/netxms/ui/eclipse/usermanager/views/helpers/UserComparator.java
src/java/netxms-eclipse/UserManager/src/org/netxms/ui/eclipse/usermanager/views/helpers/UserLabelProvider.java
src/server/core/userdb.cpp
src/server/core/userdb_objects.cpp
src/server/include/nms_users.h
src/server/tools/nxdbmgr/upgrade.cpp
webui/webapp/UserManager/src/org/netxms/ui/eclipse/usermanager/views/UserManagementView.java
webui/webapp/UserManager/src/org/netxms/ui/eclipse/usermanager/views/helpers/UserComparator.java
webui/webapp/UserManager/src/org/netxms/ui/eclipse/usermanager/views/helpers/UserLabelProvider.java

index 2fe7b15..b94ded4 100644 (file)
@@ -23,6 +23,6 @@
 #ifndef _netxmsdb_h
 #define _netxmsdb_h
 
-#define DB_FORMAT_VERSION   458
+#define DB_FORMAT_VERSION   459
 
 #endif
index 2a45ef5..3f422cb 100644 (file)
@@ -85,6 +85,7 @@ CREATE TABLE users
   xmpp_id varchar(127) null,
   ldap_dn SQL_TEXT null,
   ldap_unique_id varchar(64) null,
+  created integer not null,
   PRIMARY KEY(id)
 ) TABLE_TYPE;
 
@@ -102,6 +103,7 @@ CREATE TABLE user_groups
   description varchar(255),
   ldap_dn SQL_TEXT null,
   ldap_unique_id varchar(64) null,
+  created integer not null,
   PRIMARY KEY(id)
 ) TABLE_TYPE;
 
index e196072..0e5d5cf 100644 (file)
@@ -18,6 +18,7 @@
  */
 package org.netxms.client.users;
 
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -69,6 +70,7 @@ public abstract class AbstractUserObject
        protected String ldapDn;
        protected String ldapId;
        protected Map<String, String> customAttributes = new HashMap<String, String>(0);
+   private Date created = null;
 
        /**
         * Default constructor
@@ -96,6 +98,7 @@ public abstract class AbstractUserObject
                this.description = src.description;
                this.ldapDn = src.ldapDn;
                this.ldapId = src.ldapId;
+               this.created = src.created;
                this.customAttributes = new HashMap<String, String>(0);
                Iterator<Entry<String, String>> it  = src.customAttributes.entrySet().iterator();
                while(it.hasNext())
@@ -119,6 +122,7 @@ public abstract class AbstractUserObject
                guid = msg.getFieldAsUUID(NXCPCodes.VID_GUID);
                ldapDn = msg.getFieldAsString(NXCPCodes.VID_LDAP_DN);
       ldapId = msg.getFieldAsString(NXCPCodes.VID_LDAP_ID);
+      created = msg.getFieldAsDate(NXCPCodes.VID_CREATION_TIME);
                
                int count = msg.getFieldAsInt32(NXCPCodes.VID_NUM_CUSTOM_ATTRIBUTES);
                long varId = NXCPCodes.VID_CUSTOM_ATTRIBUTES_BASE;
@@ -320,4 +324,14 @@ public abstract class AbstractUserObject
        {
                return ((flags & CANNOT_CHANGE_PASSWORD) == CANNOT_CHANGE_PASSWORD);
        }
+       
+       
+       /**
+        * Get creation date
+        * @return creation date
+        */
+       public Date getCreationTime()
+       {
+          return created;
+       }
 }
index e4467ba..ea26dd5 100644 (file)
@@ -77,6 +77,8 @@ public class UserManagementView extends ViewPart
    public static final int COLUMN_AUTH_METHOD = 5;
        public static final int COLUMN_GUID = 6;
    public static final int COLUMN_LDAP_DN = 7;
+   public static final int COLUMN_LAST_LOGIN = 8;
+   public static final int COLUMN_CREATED = 9;
 
        private TableViewer viewer;
        private NXCSession session;
@@ -109,9 +111,11 @@ public class UserManagementView extends ViewPart
                      Messages.get().UserManagementView_Source, 
                      Messages.get().UserManagementView_Authentication, 
                      Messages.get().UserManagementView_GUID,
-                     "LDAP DN"
+                     "LDAP DN",
+                     "Last Login",
+                     "Created"
                   };
-               final int[] widths = { 100, 80, 180, 250, 80, 170, 250, 400 };
+               final int[] widths = { 100, 80, 180, 250, 80, 170, 250, 400, 250, 250 };
                viewer = new SortableTableViewer(parent, names, widths, 0, SWT.UP, SortableTableViewer.DEFAULT_STYLE);
                viewer.setContentProvider(new ArrayContentProvider());
                viewer.setLabelProvider(new UserLabelProvider());
index 488fa5a..09539d9 100644 (file)
@@ -56,7 +56,8 @@ public class UserComparator extends ViewerComparator
        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
         */
-       @Override
+       @SuppressWarnings("deprecation")
+   @Override
        public int compare(Viewer viewer, Object e1, Object e2)
        {
                int result;
@@ -91,6 +92,14 @@ public class UserComparator extends ViewerComparator
                        case UserManagementView.COLUMN_TYPE:
                                result = compareTypes(e1, e2);
                                break;
+                       case UserManagementView.COLUMN_LAST_LOGIN:
+                          int l1 = (e1 instanceof User) ? ((User)e1).getLastLogin().getSeconds() : -1;
+                          int l2 = (e2 instanceof User) ? ((User)e2).getLastLogin().getSeconds() : -1;
+                          result = l1 - l2;
+                     break;
+                       case UserManagementView.COLUMN_CREATED:
+                          result = Long.signum(((AbstractUserObject)e1).getCreationTime().getSeconds() - ((AbstractUserObject)e2).getCreationTime().getSeconds());
+                          break;
                        default:
                                result = 0;
                                break;
index f10c446..e527cff 100644 (file)
@@ -91,6 +91,10 @@ public class UserLabelProvider extends DecoratingLabelProvider implements ITable
             return ((((AbstractUserObject)element).getFlags() & AbstractUserObject.LDAP_USER) != 0) ? Messages.get().UserLabelProvider_LDAP : Messages.get().UserLabelProvider_Local;
                        case UserManagementView.COLUMN_TYPE:
                                return (element instanceof User) ? Messages.get().UserLabelProvider_User : Messages.get().UserLabelProvider_Group;
+                       case UserManagementView.COLUMN_LAST_LOGIN:
+                          return (element instanceof User) ? ((User)element).getLastLogin().toString() : null;
+                       case UserManagementView.COLUMN_CREATED:
+                          return ((AbstractUserObject)element).getCreationTime().toString();
                }
                return null;
        }
index 2b9a3e5..0722fa4 100644 (file)
@@ -222,7 +222,7 @@ BOOL LoadUsers()
    // Load users
    hResult = DBSelect(hdb,
                           _T("SELECT id,name,system_access,flags,description,guid,ldap_dn,")
-                                                        _T("ldap_unique_id,password,full_name,grace_logins,auth_method,")
+                                                        _T("ldap_unique_id,created,password,full_name,grace_logins,auth_method,")
                                                         _T("cert_mapping_method,cert_mapping_data,auth_failures,")
                                                         _T("last_passwd_change,min_passwd_length,disabled_until,")
                                                         _T("last_login,xmpp_id FROM users"));
@@ -250,7 +250,7 @@ BOOL LoadUsers()
    }
 
    // Load groups
-   hResult = DBSelect(hdb, _T("SELECT id,name,system_access,flags,description,guid,ldap_dn,ldap_unique_id FROM user_groups"));
+   hResult = DBSelect(hdb, _T("SELECT id,name,system_access,flags,description,guid,ldap_dn,ldap_unique_id,created FROM user_groups"));
    if (hResult == NULL)
    {
       DBConnectionPoolReleaseConnection(hdb);
index 00ed9bd..842c7fd 100644 (file)
@@ -87,6 +87,7 @@ UserDatabaseObject::UserDatabaseObject(DB_HANDLE hdb, DB_RESULT hResult, int row
        m_guid = DBGetFieldGUID(hResult, row, 5);
        m_ldapDn = DBGetField(hResult, row, 6, NULL, 0);
        m_ldapId = DBGetField(hResult, row, 7, NULL, 0);
+       m_created = (time_t)DBGetFieldULong(hResult, row, 8);
 }
 
 /**
@@ -102,6 +103,7 @@ UserDatabaseObject::UserDatabaseObject()
        m_systemRights = 0;
        m_description[0] = 0;
        m_flags = 0;
+       m_created = time(NULL);
 }
 
 /**
@@ -117,6 +119,7 @@ UserDatabaseObject::UserDatabaseObject(UINT32 id, const TCHAR *name)
        m_flags = UF_MODIFIED;
        m_ldapDn = NULL;
        m_ldapId = NULL;
+   m_created = time(NULL);
 }
 
 /**
@@ -157,6 +160,7 @@ void UserDatabaseObject::fillMessage(NXCPMessage *msg)
    msg->setField(VID_GUID, m_guid);
    msg->setField(VID_LDAP_DN, m_ldapDn);
    msg->setField(VID_LDAP_ID, m_ldapId);
+   msg->setField(VID_CREATION_TIME, (UINT32)m_created);
    m_attributes.fillMessage(msg, VID_NUM_CUSTOM_ATTRIBUTES, VID_CUSTOM_ATTRIBUTES_BASE);
 }
 
@@ -377,6 +381,7 @@ json_t *UserDatabaseObject::toJson() const
    json_object_set_new(root, "attributes", m_attributes.toJson());
    json_object_set_new(root, "ldapDn", json_string_t(m_ldapDn));
    json_object_set_new(root, "ldapId", json_string_t(m_ldapId));
+   json_object_set_new(root, "created", json_integer((UINT32)m_created));
    return root;
 }
 
@@ -397,7 +402,7 @@ User::User(DB_HANDLE hdb, DB_RESULT hResult, int row) : UserDatabaseObject(hdb,
        TCHAR buffer[256];
 
    bool validHash = false;
-   DBGetField(hResult, row, 8, buffer, 256);
+   DBGetField(hResult, row, 9, buffer, 256);
    if (buffer[0] == _T('$'))
    {
       // new format - with hash type indicator
@@ -426,17 +431,17 @@ User::User(DB_HANDLE hdb, DB_RESULT hResult, int row) : UserDatabaseObject(hdb,
       m_flags |= UF_MODIFIED | UF_CHANGE_PASSWORD;
    }
 
-       DBGetField(hResult, row, 9, m_fullName, MAX_USER_FULLNAME);
-       m_graceLogins = DBGetFieldLong(hResult, row, 10);
-       m_authMethod = DBGetFieldLong(hResult, row, 11);
-       m_certMappingMethod = DBGetFieldLong(hResult, row, 12);
-       m_certMappingData = DBGetField(hResult, row, 13, NULL, 0);
-       m_authFailures = DBGetFieldLong(hResult, row, 14);
-       m_lastPasswordChange = (time_t)DBGetFieldLong(hResult, row, 15);
-       m_minPasswordLength = DBGetFieldLong(hResult, row, 16);
-       m_disabledUntil = (time_t)DBGetFieldLong(hResult, row, 17);
-       m_lastLogin = (time_t)DBGetFieldLong(hResult, row, 18);
-   DBGetField(hResult, row, 19, m_xmppId, MAX_XMPP_ID_LEN);
+       DBGetField(hResult, row, 10, m_fullName, MAX_USER_FULLNAME);
+       m_graceLogins = DBGetFieldLong(hResult, row, 11);
+       m_authMethod = DBGetFieldLong(hResult, row, 12);
+       m_certMappingMethod = DBGetFieldLong(hResult, row, 13);
+       m_certMappingData = DBGetField(hResult, row, 14, NULL, 0);
+       m_authFailures = DBGetFieldLong(hResult, row, 15);
+       m_lastPasswordChange = (time_t)DBGetFieldLong(hResult, row, 16);
+       m_minPasswordLength = DBGetFieldLong(hResult, row, 17);
+       m_disabledUntil = (time_t)DBGetFieldLong(hResult, row, 18);
+       m_lastLogin = (time_t)DBGetFieldLong(hResult, row, 19);
+   DBGetField(hResult, row, 20, m_xmppId, MAX_XMPP_ID_LEN);
 
        // Set full system access for superuser
        if (m_id == 0)
@@ -527,14 +532,14 @@ bool User::saveToDatabase(DB_HANDLE hdb)
       hStmt = DBPrepare(hdb,
          _T("UPDATE users SET name=?,password=?,system_access=?,flags=?,full_name=?,description=?,grace_logins=?,guid=?,")
                        _T("  auth_method=?,cert_mapping_method=?,cert_mapping_data=?,auth_failures=?,last_passwd_change=?,")
-         _T("  min_passwd_length=?,disabled_until=?,last_login=?,xmpp_id=?,ldap_dn=?,ldap_unique_id=? WHERE id=?"));
+         _T("  min_passwd_length=?,disabled_until=?,last_login=?,xmpp_id=?,ldap_dn=?,ldap_unique_id=?,created=? WHERE id=?"));
    }
    else
    {
       hStmt = DBPrepare(hdb,
          _T("INSERT INTO users (name,password,system_access,flags,full_name,description,grace_logins,guid,auth_method,")
          _T("  cert_mapping_method,cert_mapping_data,password_history,auth_failures,last_passwd_change,min_passwd_length,")
-         _T("  disabled_until,last_login,xmpp_id,ldap_dn,ldap_unique_id,id) VALUES (?,?,?,?,?,?,?,?,?,?,?,'',?,?,?,?,?,?,?,?,?)"));
+         _T("  disabled_until,last_login,xmpp_id,ldap_dn,ldap_unique_id,,created,id) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,'',?,?,?,?,?,?,?,?,?)"));
    }
    if (hStmt == NULL)
       return false;
@@ -558,7 +563,8 @@ bool User::saveToDatabase(DB_HANDLE hdb)
    DBBind(hStmt, 17, DB_SQLTYPE_VARCHAR, m_xmppId, DB_BIND_STATIC);
    DBBind(hStmt, 18, DB_SQLTYPE_TEXT, m_ldapDn, DB_BIND_STATIC);
    DBBind(hStmt, 19, DB_SQLTYPE_VARCHAR, m_ldapId, DB_BIND_STATIC);
-   DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, m_id);
+   DBBind(hStmt, 20, DB_SQLTYPE_INTEGER, (UINT32)m_created);
+   DBBind(hStmt, 21, DB_SQLTYPE_INTEGER, m_id);
 
    bool success = DBBegin(hdb);
        if (success)
@@ -841,11 +847,11 @@ bool Group::saveToDatabase(DB_HANDLE hdb)
    DB_STATEMENT hStmt;
    if (IsDatabaseRecordExist(hdb, _T("user_groups"), _T("id"), m_id))
    {
-      hStmt = DBPrepare(hdb, _T("UPDATE user_groups SET name=?,system_access=?,flags=?,description=?,guid=?,ldap_dn=?,ldap_unique_id=? WHERE id=?"));
+      hStmt = DBPrepare(hdb, _T("UPDATE user_groups SET name=?,system_access=?,flags=?,description=?,guid=?,ldap_dn=?,ldap_unique_id=?,created=? WHERE id=?"));
    }
    else
    {
-      hStmt = DBPrepare(hdb, _T("INSERT INTO user_groups (name,system_access,flags,description,guid,ldap_dn,ldap_unique_id,id) VALUES (?,?,?,?,?,?,?,?)"));
+      hStmt = DBPrepare(hdb, _T("INSERT INTO user_groups (name,system_access,flags,description,guid,ldap_dn,ldap_unique_id,created,id) VALUES (?,?,?,?,?,?,?,?,?)"));
    }
    if (hStmt == NULL)
       return false;
@@ -857,7 +863,8 @@ bool Group::saveToDatabase(DB_HANDLE hdb)
    DBBind(hStmt, 5, DB_SQLTYPE_VARCHAR, m_guid);
    DBBind(hStmt, 6, DB_SQLTYPE_TEXT, m_ldapDn, DB_BIND_STATIC);
    DBBind(hStmt, 7, DB_SQLTYPE_VARCHAR, m_ldapId, DB_BIND_STATIC);
-   DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, m_id);
+   DBBind(hStmt, 8, DB_SQLTYPE_INTEGER, (UINT32)m_created);
+   DBBind(hStmt, 9, DB_SQLTYPE_INTEGER, m_id);
 
    bool success = DBBegin(hdb);
        if (success)
index dcbe71e..380a395 100644 (file)
@@ -191,6 +191,7 @@ protected:
        StringMap m_attributes;         // Custom attributes
    TCHAR *m_ldapDn;
    TCHAR *m_ldapId;
+   time_t m_created;
 
        bool loadCustomAttributes(DB_HANDLE hdb);
        bool saveCustomAttributes(DB_HANDLE hdb);
index 6cedbeb..9c8b306 100644 (file)
@@ -585,7 +585,26 @@ static bool SetSchemaVersion(int version)
 }
 
 /**
- * Upgrade from V456 to V457
+ * Upgrade from V458 to V459
+ */
+static BOOL H_UpgradeFromV458(int currVersion, int newVersion)
+{
+   static const TCHAR *batch =
+            _T("ALTER TABLE users ADD created integer null\n")
+            _T("ALTER TABLE user_groups ADD created integer null\n")
+            _T("UPDATE users SET created=0\n")
+            _T("UPDATE user_groups SET created=0\n")
+            _T("<END>");
+   CHK_EXEC(SQLBatch(batch));
+   CHK_EXEC(DBSetNotNullConstraint(g_hCoreDB, _T("users"), _T("created")));
+   CHK_EXEC(DBSetNotNullConstraint(g_hCoreDB, _T("user_groups"), _T("created")));
+
+   CHK_EXEC(SetSchemaVersion(459));
+   return TRUE;
+}
+
+/**
+ * Upgrade from V457 to V458
  */
 static BOOL H_UpgradeFromV457(int currVersion, int newVersion)
 {
@@ -11907,6 +11926,7 @@ static struct
    { 455, 456, H_UpgradeFromV455 },
    { 456, 457, H_UpgradeFromV456 },
    { 457, 458, H_UpgradeFromV457 },
+   { 458, 459, H_UpgradeFromV458 },
    { 0, 0, NULL }
 };
 
index e4467ba..e68da53 100644 (file)
@@ -77,6 +77,8 @@ public class UserManagementView extends ViewPart
    public static final int COLUMN_AUTH_METHOD = 5;
        public static final int COLUMN_GUID = 6;
    public static final int COLUMN_LDAP_DN = 7;
+   public static final int COLUMN_LAST_LOGIN = 8;
+   public static final int COLUMN_CREATED = 9;
 
        private TableViewer viewer;
        private NXCSession session;
@@ -109,9 +111,11 @@ public class UserManagementView extends ViewPart
                      Messages.get().UserManagementView_Source, 
                      Messages.get().UserManagementView_Authentication, 
                      Messages.get().UserManagementView_GUID,
-                     "LDAP DN"
+                     "LDAP DN",
+            "Last Login",
+            "Created"
                   };
-               final int[] widths = { 100, 80, 180, 250, 80, 170, 250, 400 };
+               final int[] widths = { 100, 80, 180, 250, 80, 170, 250, 400, 250, 250 };
                viewer = new SortableTableViewer(parent, names, widths, 0, SWT.UP, SortableTableViewer.DEFAULT_STYLE);
                viewer.setContentProvider(new ArrayContentProvider());
                viewer.setLabelProvider(new UserLabelProvider());
index 488fa5a..dc480d5 100644 (file)
@@ -56,7 +56,8 @@ public class UserComparator extends ViewerComparator
        /* (non-Javadoc)
         * @see org.eclipse.jface.viewers.ViewerComparator#compare(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
         */
-       @Override
+       @SuppressWarnings("deprecation")
+   @Override
        public int compare(Viewer viewer, Object e1, Object e2)
        {
                int result;
@@ -91,6 +92,14 @@ public class UserComparator extends ViewerComparator
                        case UserManagementView.COLUMN_TYPE:
                                result = compareTypes(e1, e2);
                                break;
+         case UserManagementView.COLUMN_LAST_LOGIN:
+            int l1 = (e1 instanceof User) ? ((User)e1).getLastLogin().getSeconds() : -1;
+            int l2 = (e2 instanceof User) ? ((User)e2).getLastLogin().getSeconds() : -1;
+            result = l1 - l2;
+            break;
+         case UserManagementView.COLUMN_CREATED:
+            result = Long.signum(((AbstractUserObject)e1).getCreationTime().getSeconds() - ((AbstractUserObject)e2).getCreationTime().getSeconds());
+            break;
                        default:
                                result = 0;
                                break;
index 0980813..88f25b2 100644 (file)
@@ -91,6 +91,10 @@ public class UserLabelProvider extends DecoratingLabelProvider implements ITable
             return ((((AbstractUserObject)element).getFlags() & AbstractUserObject.LDAP_USER) != 0) ? Messages.get().UserLabelProvider_LDAP : Messages.get().UserLabelProvider_Local;
                        case UserManagementView.COLUMN_TYPE:
                                return (element instanceof User) ? Messages.get().UserLabelProvider_User : Messages.get().UserLabelProvider_Group;
+         case UserManagementView.COLUMN_LAST_LOGIN:
+            return (element instanceof User) ? ((User)element).getLastLogin().toString() : null;
+         case UserManagementView.COLUMN_CREATED:
+            return ((AbstractUserObject)element).getCreationTime().toString();
                }
                return null;
        }