UNPKG

windows-users

Version:

Native addon for Node.js to query Windows User API

451 lines (411 loc) 19.8 kB
# windows-users A native addon for Node.js to query user accounts on Windows platforms ## Install <pre style="color:#ccc;background-color:#222;"> C:\Users\myUser><b>npm install windows-users</b> </pre> **Note to users of pre-C++-2011 compilers only:** During the build, the compiler will print many warnings like this: <pre style="color:#ff0;background-color:#222;"> ..\src\deepinfo.cc(63): warning C4482: nonstandard extension used: enum 'UserField' used in qualified name </pre> These can be safely ignored. ## Usage ```js var users = require('windows-users') var nameList = users.list() console.log('The user accounts on this system are:', nameList.join(', ')) nameList.forEach(function(username) { var account = users.getDetails(username) if (account.accountType === 'administrator' && !account.disabled) { // ... } }) var infoList = users.list({detailed: true}) for (var i = 0; i < infoList.length; i++) { var account = infoList[i] if (account.disabled || account.lockedOut) continue var fullInfo = users.getDetails(account.name) console.log('Account %s has SID: %s', fullInfo.name, fullInfo.sid) if (fullInfo.lastLogon > 0) console.log('Last logon was', new Date(fullInfo.lastLogon * 1000)) var localGrps = users.getLocalGroups(account.name) var globalGrps = users.getGlobalGroups(account.name) // ... } ``` For each of the four available functions, the user may expect the result of querying the localhost as the synchronous return value *if no callback function is added to the argument list*. Simply supply a callback function as the last argument to turn the call asynchronous. A callback function is *required* if a host other than the localhost is to be queried. **Note:** In some environments, the synchronous functions may throw an `Error` of `"access is denied to current user"`, and any of the asynchronous functions may pass this error to the callback. This would be a consequence of the user's permissions versus the particular security configuration of the domain. --- ## API <a name="list-sync"></a> ### users.list([options]) *Synchronous.* Returns a list of all user accounts known to the local system, optionally according to the specified options. - `options` {Object} *Optional.* * `detailed` {Boolean} A flag to request additional fields of data with each account name. The default is to return account names only. See [Enumeration Fields](#enumfields) table below. Note that the additional fields included by giving this option are not exhaustive; for that, see [`users.getDetails()`](#getdetails-sync) with the `fullDetails` option. * `filter` {Number} A bit-field specifying the types of user accounts to include (See [User Account Type Constants](#accttypeconsts) below). This field can be made to specify multiple types by combining them with logical OR (`|`) notation. The default is to request all types; a value of `0` will also get this result, as will a combination of all the constants. - Return: {Array} array of {String | Object} If no `options` are given, this will be an array of the names of every user account known to the system, including special account types if any. If option `detailed` is set `true`, it will be an array of objects containing all of the fields in the [Enumeration Fields](#enumfields) table below. If option `filter` is given and set non-zero, the array will include only the accounts with type(s) matching the specified value(s). <a name="list-async"></a> ### users.list([options,] [hostname,] callback) *Asynchronous.* Passes a list of all user accounts known to the local system (or on the system named by `hostname` instead) to the `callback` function. The contents of the list depends on whether and which options are given, as described above for the synchronous version. If `hostname` is given and it is unknown or cannot be accessed, an `Error` is passed back. - `options` {Object} *Optional.* As described for synchronous version. - `hostname` {String} *Optional.* The name of a host in the domain to query. An empty value (`undefined`, `null`, or empty string) may be passed to get the same effect as omitting this argument. - `callback` {Function} * **error** {Error | `null`} * **data** {Array} as described for return value of synchronous version, if no error. <a name="getdetails-sync"></a> ### users.getDetails(username [, fullDetails]) *Synchronous.* Returns information about the named user account if it is known on the local system; otherwise an `Error` is thrown. - `username` {String} Logon name of user account. - `fullDetails` {Boolean} *Optional.* Pass `true` to request all available details. - Return: {Object} A user account record containing all of the fields listed in the [Enumeration Fields](#enumfields) table; if a `true` value was passed for the `fullDetails` parameter, the record will also contain the fields listed in the [Additional Fields](#fulldetails) table. <a name="getdetails-async"></a> ### users.getDetails(username [, fullDetails] [, hostname], callback) *Asynchronous.* Passes the account information for the named user (optionally on the system named by `hostname`) to the `callback` function, if the username is known; otherwise an `Error` is passed to the callback. If `hostname` is given and it is unknown or cannot be accessed, an `Error` is passed back. - `username` {String} Logon name of user account. - `fullDetails` {Boolean} *Optional.* Pass `true` to request all available details. - `hostname` {String} *Optional.* The name of a host in the domain to query. An empty value (`undefined`, `null`, or empty string) may be passed to get the same effect as omitting this argument. - `callback` {Function} * **error** {Error | `null`} * **data** {Object} as described for return value of synchronous version, if no error. <a name="getggroups-sync"></a> ### users.getGlobalGroups(username) *Synchronous.* Returns the list of global groups to which the named user account belongs, if the `username` is known on the local system; otherwise an `Error` is thrown. - `username` {String} Logon name of user account. - Return: {Array} array of global group names as strings <a name="getggroups-async"></a> ### users.getGlobalGroups(username [, hostname], callback) *Asynchronous.* Retrieves the list of global groups to which the named user account belongs (optionally on the system named by `hostname`) and passes it to the `callback` function, if the username is known to the host; otherwise an `Error` is passed to the callback. If `hostname` is given and it is unknown or cannot be accessed, an `Error` is passed back. - `username` {String} Logon name of user account. - `hostname` {String} *Optional.* The name of a host in the domain to query. An empty value (`undefined`, `null`, or empty string) may be passed to get the same effect as omitting this argument. - `callback` {Function} * **error** {Error | `null`} * **data** {Array} as described for return value of synchronous version, if no error. <a name="getlgroups-sync"></a> ### users.getLocalGroups(username) *Synchronous.* Returns the list of local groups to which the named user account belongs, if the `username` is known on the local system; otherwise an `Error` is thrown. - `username` {String} Logon name of user account. - Return: {Array} array of local group names as strings <a name="getlgroups-async"></a> ### users.getLocalGroups(username [, hostname], callback) *Asynchronous.* Retrieves the list of local groups to which the named user account belongs (optionally on the system named by `hostname`) and passes it to the `callback` function, if the username is known to the host; otherwise an `Error` is passed to the callback. If `hostname` is given and it is unknown or cannot be accessed, an `Error` is passed back. - `username` {String} Logon name of user account. - `hostname` {String} *Optional.* The name of a host in the domain to query. An empty value (`undefined`, `null`, or empty string) may be passed to get the same effect as omitting this argument. - `callback` {Function} * **error** {Error | `null`} * **data** {Array} as described for return value of synchronous version, if no error. <a name="accttypeconsts"></a> ### User Account Type Constants - **`users.constants.NORMAL`** - Default account type, representing a typical user. The corresponding string value returned for the `accountType` field is `"normal"`. - **`users.constants.TEMP_DUPLICATE`** - Account type for users whose primary account is in another domain. The corresponding `accountType` field value is `"temp duplicate"`. - **`users.constants.INTERDOMAIN_TRUST`** - A Permit To Trust account for a domain that trusts other domains. The corresponding `accountType` field value is `"interdomain trust"`. - **`users.constants.WORKSTATION_TRUST`** - A computer account for a computer that is a member of this domain. The corresponding `accountType` field value is `"workstation trust"` - **`users.constants.SERVER_TRUST`** - A computer account for a backup domain controller that is a member of this domain. The corresponding `accountType` field value is `"server trust"`. <a name="enumfields"></a> ### Enumeration Fields <table> <thead> <tr><th>Field Name</th><th>Type</th><th>Description</th></tr> </thead> <tbody> <tr> <td><code>name</code></td> <td><code>String</code></td> <td>The username for account logon.</td> </tr> <tr> <td><code>fullName</code></td> <td><code>String</code></td> <td>Alternate identification of user; may be an empty string.</td> </tr> <tr> <td><code>comment</code></td> <td><code>String</code></td> <td>Descriptive comment; may be an empty string.</td> </tr> <tr> <td><code>accountType</code></td> <td><code>String</code></td> <td>Account usage type. See notes for <a href="#accttypeconsts">User Account Type Constants</a>.</td> </tr> <tr> <td><code>disabled</code></td> <td><code>Boolean</code></td> <td>The user's account is disabled.</td> </tr> <tr> <td><code>lockedOut</code></td> <td><code>Boolean</code></td> <td>The account is currently locked out.</td> </tr> <tr> <td><code>passwdRequired</code></td> <td><code>Boolean</code></td> <td>The user must use a password to log on.</td> </tr> <tr> <td><code>passwdCanChange</code></td> <td><code>Boolean</code></td> <td>The user can change the password.</td> </tr> <tr> <td><code>passwdExpired</code></td> <td><code>Boolean</code></td> <td>The user's password has expired.</td> </tr> <tr> <td><code>passwdNeverExpires</code></td> <td><code>Boolean</code></td> <td>Currently set for password never to expire.</td> </tr> <tr> <td><code>encryptedPasswdOK</code></td> <td><code>Boolean</code></td> <td>Password is stored under reversible encryption in the Active Directory.</td> </tr> <tr> <td><code>smartcardRequired</code></td> <td><code>Boolean</code></td> <td>The user must log on with a smart card.</td> </tr> <tr> <td><code>useOnlyDES</code></td> <td><code>Boolean</code></td> <td>Restricted to use only DES encryption types for keys.</td> </tr> <tr> <td><code>noPreauthRequired</code></td> <td><code>Boolean</code></td> <td>No Kerberos preauthentication required for logon.</td> </tr> <tr> <td><code>notDelegated</code></td> <td><code>Boolean</code></td> <td>Other users cannot act as delegates of this account.</td> </tr> <tr> <td><code>trustedForDeleg</code></td> <td><code>Boolean</code></td> <td>The account is enabled for delegation.</td> </tr> <tr> <td><code>trustedToAuthDeleg</code></td> <td><code>Boolean</code></td> <td>The account is trusted to authenticate a user outside of the Kerberos security package and delegate that user through constrained delegation.</td> </tr> </tbody> </table> > > For more information about the `Boolean` fields above, see the table of corresponding flags under the description of the **usri20_flags** field on [this page at MSDN.microsoft.com](https://msdn.microsoft.com/en-us/library/windows/desktop/aa371123.aspx). <a name="fulldetails"></a> ### Additional Fields Available through `getDetails()` <table> <thead> <tr><th>Field Name</th><th>Type</th><th>Description</th></tr> </thead> <tbody> <tr> <td><code>sid</code></td> <td><code>String</code></td> <td>The unique <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379597.aspx">security identifier (SID)</a> of the user.</td> </tr> <tr> <td><code>primaryGroupId</code></td> <td><code>Number</code></td> <td>The relative identifier (RID) of the Primary Global Group for the user. Information about RIDs can be found on the <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379597.aspx">MSDN page about SID Components</a>.</td> </tr> <tr> <td><code>homeDir</code></td> <td><code>String</code></td> <td>Path of the user's home directory; may be an empty string.</td> </tr> <tr> <td><code>homeDirDrive</code></td> <td><code>String</code></td> <td>The letter of the drive where the user's home directory resides; may be an empty string if <code>homeDir</code> is empty.</td> </tr> <tr> <td><code>profilePath</code></td> <td><code>String</code></td> <td>Path of the user's profile; can be an empty string, a local absolute path, or a UNC path.</td> </tr> <tr> <td><code>scriptPath</code></td> <td><code>String</code></td> <td>Path of the user's logon script file; may be an empty string.</td> </tr> <tr> <td><code>maxStorage</code></td> <td><code>Number</code></td> <td>If not <code>null</code>, the maximum disk space the user can use, in bytes. A <code>null</code> value means "unlimited".</td> </tr> <tr> <td><code>privilegeLevel</code></td> <td><code>String</code></td> <td><code>"guest"</code>, <code>"user"</code>, or <code>"administrator"</code> (see <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa379306.aspx">MSDN page about Privileges</a>).</td> </tr> <tr> <td><code>isAccountsOperator</code></td> <td><code>Boolean</code></td> <td>Flag: the user has Accounts Operator privilege.</td> </tr> <tr> <td><code>isServerOperator</code></td> <td><code>Boolean</code></td> <td>Flag: the user has Print Operator privilege.</td> </tr> <tr> <td><code>isPrintOperator</code></td> <td><code>Boolean</code></td> <td>Flag: the user has Server Operator privilege.</td> </tr> <tr> <td><code>userComment</code></td> <td><code>String</code></td> <td>Another comment associated with the user; may be an empty string.</td> </tr> <tr> <td><code>countryCode</code></td> <td><code>Number</code></td> <td>The country/region code for the user's language of choice.</td> </tr> <tr> <td><code>codePage</code></td> <td><code>Number</code></td> <td>The code page for the user's language of choice.</td> </tr> <tr> <td><code>appParams</code></td> <td><code>String</code></td> <td>Reserved for use by some applications; may be an empty string.</td> </tr> <tr> <td><code>passwdAge</code></td> <td><code>Number</code></td> <td>Number of seconds passed since password was last changed. The value <code>0</code> means "never".</td> </tr> <tr> <td><code>accountExpires</code></td> <td><code>Number</code></td> <td>If not <code>null</code>, the time when the account expires, in number of seconds after UNIX epoch. A <code>null</code> value means "never".</td> </tr> <tr> <td><code>logonHours</code></td> <td><code>Array</code></td> <td>If not <code>null</code>, a 2-dimensional array identifying GMT hours of the week during which the user can log on. The outer array has an element for each day of the week, starting with Sunday; each element is an array of integers representing 0-indexed hours of the day, GMT (<a href="#logonhours">see "How To" below</a>). A <code>null</code> value means no restriction.</td> </tr> <tr> <td><code>workstations</code></td> <td><code>String</code></td> <td>Comma-delimited list of workstations from which the user can log on; may be an empty string, meaning: unrestricted.</td> </tr> <tr> <td><code>logonServer</code></td> <td><code>String</code></td> <td>Name of the server to which logon requests are sent. The value <code>"\\\\*"</code> means any logon server can handle requests. An empty string means the domain controller handles requests.</td> </tr> <tr> <td><code>lastLogon</code></td> <td><code>Number</code></td> <td>Time of last logon, in number of seconds after UNIX epoch; the value <code>0</code> means "never". About accuracy, see special notes for corresponding field <strong>usri4_last_logon</strong> on <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa371339.aspx">this page at MSDN.microsoft.com</a>.</td> </tr> <tr> <td><code>logonCount</code></td> <td><code>Number</code></td> <td>If not <code>null</code>, the number of times logon to this account was successful. A <code>null</code> value means "unknown". About accuracy, see special notes for corresponding field <strong>usri4_num_logons</strong> on <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa371339.aspx">this page at MSDN.microsoft.com</a>.</td> </tr> <tr> <td><code>badPasswdCount</code></td> <td><code>Number</code></td> <td>If not <code>null</code>, the number of times logon was attempted with an incorrect password. A <code>null</code> value means "unknown". About accuracy, see special notes for corresponding field <strong>usri4_bad_pw_count</strong> on <a href="https://msdn.microsoft.com/en-us/library/windows/desktop/aa371339.aspx">this page at MSDN.microsoft.com</a>.</td> </tr> </tbody> </table> <a name="logonhours"></a> #### **Logon Hours: How To...** As noted above, the values in the `logonHours` structure are according to Greenwich Mean Time (GMT). You will probably want to convert to values relative to your local timezone. - If your timezone offset is positive: 1. add the offset to the value to get result A 2. if result A is less than 24, it applies to the given day 3. else take the modulus (result A % 24) and apply it to the following day. Note that if the day index is 6, the following day would be Sunday (index 0). - If your timezone offset is negative: 1. add the offset to the value to get result A 2. if result A is positive, it applies to the given day 3. else add (result A + 24) and apply it to the previous day. Note that if the day index is 0, the previous day would be Saturday (index 6). ------ **License: MIT**