{"id":20530220,"url":"https://github.com/hacktix/ad2","last_synced_at":"2025-09-05T11:45:57.349Z","repository":{"id":143894369,"uuid":"281042848","full_name":"Hacktix/ad2","owner":"Hacktix","description":"A jQuery-like wrapper for ldapjs / activedirectory, but better","archived":false,"fork":false,"pushed_at":"2020-07-24T11:16:01.000Z","size":88,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-16T11:51:53.740Z","etag":null,"topics":["activedirectory","ad","jquery","ldap","server","windows","wrapper"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Hacktix.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-20T07:15:03.000Z","updated_at":"2021-01-28T07:16:52.000Z","dependencies_parsed_at":null,"dependency_job_id":"ca520185-b077-48d2-9660-920edec0ce67","html_url":"https://github.com/Hacktix/ad2","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hacktix%2Fad2","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hacktix%2Fad2/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hacktix%2Fad2/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Hacktix%2Fad2/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Hacktix","download_url":"https://codeload.github.com/Hacktix/ad2/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242133967,"owners_count":20077171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["activedirectory","ad","jquery","ldap","server","windows","wrapper"],"created_at":"2024-11-15T23:35:49.094Z","updated_at":"2025-03-06T02:21:39.487Z","avatar_url":"https://github.com/Hacktix.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AD2\n\n\u003e Making Active Directory jQuery-easy.\n\n---\n\nAD2 is an extension of the original AD package and a Javascript implementation of common Active Directory tasks, built to be simple as possible.\n\nReally simple.\n\nYou can use `async` / `await`:\n\n```js\n(async () =\u003e {\n\ttry {\n\n\t\tawait ad.user().add({\n\t\t\tuserName: 'jsmith'\n\t\t\tfirstName: 'John',\n\t\t\tlastName: 'Smith',\n\t\t\tlocation: '/Users/Sales',\n\t\t\tpassword: 'J@vascr!pt1'\n\t\t});\n\t\tawait ad.group().add('Sales');\n\t\tawait ad.user('jsmith').addToGroup('Sales');\n\n\t} catch(err) {\n\t\t// ...\n\t}\n})();\n```\n\nOr stick with promises:\n\n```js\nad.user('agnes').changePassword('d0ntForgetThisTime')\\\n\t.then(() =\u003e ad.user('crook').disable())\n\t.then(() =\u003e ad.user('larry').move('Dungeon'))\n\t.catch((err) =\u003e {\n\t\t// ...\n\t});\n\n```\n\n### Features\n\n - Robust `user`, `group` and `ou` manipulation methods\n - High and low-level search methods\n - Caching by default\n - Fancy result filtering including column and value filtering, sorting and pagination\n - [Companion drop-in REST API](https://github.com/dthree/addict)\n\n## Getting Started\n\nFirst, install the library:\n\n```bash\nnpm i ad\n```\n\n```bash\nyarn add ad\n```\n\nThen add this to `index.js`:\n\n```js\nconst AD = require('ad');\n\n// Your AD account should be a member\n// of the Administrators group.\nconst ad = new AD({\n\turl: \"ldaps://127.0.0.1\",\n\tuser: \"dthree@acme.co\",\n\tpass: \"howinsecure\"\n});\n\nad.user().get().then(users =\u003e {\n\tconsole.log('Your users:', users);\n}).catch(err =\u003e {\n\tconsole.log('Error getting users:', err);\n});\n\n```\n\nNow run the file:\n\n```bash\nnode index.js\n```\n\nAnd you're off to the races.\n\n## API\n\n```js\nad.user().get(filter)\nad.user().add(options)\nad.user(username).get(filter)\nad.user(userName).exists()\nad.user(userName).addToGroup(groupName)\nad.user(userName).removeFromGroup(groupName)\nad.user(userName).isMemberOf(groupName)\nad.user(userName).authenticate(password)\nad.user(userName).password(password)\nad.user(userName).passwordNeverExpires()\nad.user(userName).passwordExpires()\nad.user(userName).enable()\nad.user(userName).disable()\nad.user(userName).move(location)\nad.user(userName).unlock()\nad.user(userName).remove()\nad.user(userName).location()\n\nad.group().get(filter)\nad.group().add(options)\nad.group(groupName).get(filter)\nad.group(groupName).exists()\nad.group(groupName).addUser(userName)\nad.group(groupName).removeUser(userName)\nad.group(groupName).remove()\n\nad.ou().get(filter)\nad.ou().add(options)\nad.ou(ouName).get()\nad.ou(ouName).exists()\nad.ou(ouName).remove()\n\nad.object().get(filter)\nad.object().add(options)\nad.object(objectName[, location]).exists()\nad.object(objectName[, location]).get()\nad.object(objectName[, location]).remove()\nad.object(objectName[, location]).addToGroup(groupName)\nad.object(objectName[, location]).setProperties(properties)\n\nad.other().get(filter)\nad.all().get(filter)\nad.find(searchString)\n\nad.cache(boolean)\nad.cacheTimeout(millis)\n```\n\n### User Methods\n\n#### ad.user().get(filter)\n\nReturns all user objects.\n\n```js\nawait ad.user().get({fields: 'sAMAccountName'});\n// =\u003e ['jsmith', 'dthree', 'qix'];\n\n```\n\n#### ad.user().add(options)\n\nCreates a new user. Returns the created user object.\n\n##### Options:\n\n* `userName`: String (required)\n* `pass`: String (required)\n* `commonName`: String (required)\n* `firstName`: String\n* `lastName`: String\n* `email`: String\n* `title`: String\n* `location`: String\n\nIf not specified, the first and last name will be based on the `commonName`.\n\n```js\nawait ad.user().add({\n\tuserName: 'jsmith'\n\tcommonName: 'John Smith',\n\tpassword: 'J@vascr!pt1'\n});\n// =\u003e {sAMAccountName: 'jsmith' ... }\n\n```\n\n#### ad.user(userName).get(filter)\n\nReturns a user object. If no user is matched, returns `undefined`.\n\n```js\nawait ad.user('jsmith').get();\n// =\u003e {sAMAccountName: 'jsmith', email: 'jsmith@acme.co' ... }\n\n```\n\n#### ad.user(userName).exists()\n\nReturns a `Boolean` of whether the user account matched.\n\n```js\nawait ad.user('lochness').exists();\n// =\u003e false\n\n```\n\n#### ad.user(userName).addToGroup(groupName)\n\nAdds a user to a security group.\n\n```js\nawait ad.user('jsmith').addToGroup('Sales');\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).removeFromGroup(groupName)\n\nRemoves a user from a security group.\n\n```js\nawait ad.user('jsmith').removeFromGroup('Sales');\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).isMemberOf(groupName)\n\nReturns a `Boolean` based on whether the user is a member of a group.\n\n```js\nawait ad.user('jsmith').isMemberOf('Sales');\n// =\u003e true\n\n```\n\n#### ad.user(userName).authenticate(password)\n\nAttempts to authenticate a user with a given password. Returns `Boolean`.\n\n```js\nawait ad.user('jsmith').authenticate('J@vascript1#!');\n// =\u003e true\n\n```\n\n#### ad.user(userName).password(password)\n\nSets a user's password.\n\n```js\nawait ad.user('jsmith').password('Wh-m@ksp@ssw-rdslIkethis');\n// =\u003e true\n\n```\n\n#### ad.user(userName).passwordNeverExpires()\n\nSets a user's to never expire.\n\n```js\nawait ad.user('jsmith').passwordNeverExpires();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).passwordExpires()\n\nUnchecks the \"Password never expires\" box.\n\n```js\nawait ad.user('jsmith').passwordExpires();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).enable()\n\nEnables a user.\n\n```js\nawait ad.user('jsmith').enable();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).disable()\n\nDisables a user.\n\n```js\nawait ad.user('jsmith').disable();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).unlock()\n\nUnlocks a user who has been locked out by repeated failed login attempts.\n\n```js\nawait ad.user('jsmith').unlock();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).lock()\n\nJust kidding. You can't lock an account. Try disabling it instead.\n\n```js\nawait ad.user('jsmith').disable();\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).move(location)\n\nMoves a user to another directory, starting from the root of the domain.\n\n```js\nawait ad.user('jsmith').move('Users/HR');\n// =\u003e {success: true}\n\n```\nThis is the equivalent of `acme.co =\u003e Users (OU) =\u003e HR (OU)`. The new `Distinguished Name` (DN) would become `CN=John Smith,OU=HR,OU=Users,DC=acme,DC=co`.\n\nTo specify a folder that is not an Organizational Unit, prefix it with `!`:\n\n```js\nawait ad.user('admin').move('!Builtin');\n// =\u003e {success: true}\n\n```\n\n#### ad.user(userName).location()\n\nReturns a user's relative location, separated by `/`es.\n\n```js\nawait ad.user('jsmith').location();\n// =\u003e 'Users/HR'\n\n```\n\n#### ad.user(userName).remove()\n\nDeletes a user. Are you sure you want to do this?\n\n```js\nawait ad.user('jsmith').remove();\n// =\u003e {success: true}\n\n```\n\n\n### Group Methods\n\n#### ad.group().get(filter)\n\nReturns all group objects.\n\n```js\nawait ad.group().get();\n// =\u003e [{ ... }, { ... }];\n\n```\n\n#### ad.group().add(options)\n\nCreates a new group. Returns the created group object.\n\n##### Options:\n\n* `name`: String (required)\n* `location`: String\n* `description`: String\n\n```js\nawait ad.group().add({\n\tname: 'HR'\n\tlocation: '!Builtin',\n\tdescription: 'Human Resources users.'\n});\n// =\u003e {sAMAccountName: 'HR' ... }\n\n```\n\n#### ad.group(groupName).get(filter)\n\nReturns a group object. If no group is matched, returns `undefined`.\n\n```js\nawait ad.group('HR').get();\n// =\u003e {sAMAccountName: 'HR', description: 'Human...' ... }\n\n```\n\n#### ad.group(groupName).exists()\n\nReturns a `Boolean` of whether the group account matched.\n\n```js\nawait ad.group('Beastie Boys').exists();\n// =\u003e false\n\n```\n\n#### ad.group(groupName).addUser(groupName)\n\nAdds a user to a group.\n\n```js\nawait ad.group('HR').addUser('bjones');\n// =\u003e {success: true}\n\n```\n\n#### ad.group(groupName).removeUser(groupName)\n\nRemoves a user from a group.\n\n```js\nawait ad.group('HR').removeUser('bjones');\n// =\u003e {success: true}\n\n```\n\n#### ad.group(groupName).remove()\n\nDeletes a group.\n\n```js\nawait ad.group('HR').remove();\n// =\u003e {success: true}\n\n```\n\n\n### Organizational Unit (OU) Methods\n\n#### ad.ou().get(filter)\n\nReturns all ou objects.\n\n```js\nawait ad.ou().get();\n// =\u003e [{ ... }, { ... }];\n\n```\n\n#### ad.ou().add(options)\n\nCreates a new Organizational Unit. Returns the created OU object.\n\n##### Options:\n\n* `name`: String (required)\n* `location`: String\n* `description`: String\n\n```js\nawait ad.ou().add({\n\tname: 'Sales'\n\tlocation: 'Users'\n\tdescription: 'Sales Users.'\n});\n// =\u003e {ou: 'Sales' ... }\n\n```\n\n#### ad.ou(ouName).get(filter)\n\nReturns an OU object. If no OU is matched, returns `undefined`.\n\n```js\nawait ad.ou('Sales').get();\n// =\u003e {ou: 'Sales', description: 'Sales...' ... }\n\n```\n\n#### ad.ou(ouName).exists()\n\nReturns a `Boolean` of whether the OU exists.\n\n```js\nawait ad.ou('Sales').exists();\n// =\u003e true\n\n```\n\n#### ad.user(userName).remove()\n\nDeletes an Organizational Unit. As a note, if it has any children, this will not work.\n\n```js\nawait ad.ou('Sales').remove();\n// =\u003e {success: true}\n\n```\n\n### Object methods\n\n#### ad.object().get(filter)\n\nReturns all objects that are not users or groups.\n\n```js\nawait ad.other().get();\n// =\u003e [{ ... }, { ... }];\n\n```\n\n#### ad.object().add(options)\n\nCreates a new object in Active Directory. Returns the created object.\n\n```js\nawait ad.object().add({\n\tname: \"My Phone\",\n\tlocation: \"Devices\",\n\tobject: {\n\t\tobjectClass: \"device\"\n\t}\n})\n// =\u003e { cn: \"My Phone\", objectClass: \"device\" }\n```\n\n#### ad.object(objectName).get()\n\nReturns an object that is not a user or a group with the given name. If no object is matched, returns `undefined`.\n\n```js\nawait ad.object(\"My Object\").get()\n// =\u003e { cn: \"My Object\", description: \"Something something...\" ... }\n```\n\n#### ad.object(objectName, location).get()\n\nReturns an object that is not a user or a group with the given name at the given location. If no object is matched, returns `undefined`.\n\n```js\nawait ad.object(\"My Object\", \"SomeOU\").get()\n// =\u003e { cn:\"My Object\", description: \"Something something...\" ... }\n```\n\n#### ad.object(objectName).remove()\n\nRemoves an object from the Active Directory. (**Warning:** Uses first match across all OUs when no location is given)\n\n```js\nawait ad.object(\"My Object\").remove()\n// =\u003e { success: true }\n```\n\n#### ad.object(objectName, location).remove()\n\nRemoves an object from the Active Directory at the given location.\n\n```js\nawait ad.object(\"My Object\", \"SomeOU\").remove()\n// =\u003e { success: true }\n```\n\n#### ad.object(objectName).addToGroup(groupName)\n\nAdds an object to a group in Active Directory.\n\n```js\nawait ad.object(\"My Object\").addToGroup(\"testGroup\")\n// =\u003e { success: true }\n```\n\n#### ad.object(objectName, location).addToGroup(groupName)\n\nAdds an object at the given location to a group in Active Directory.\n\n```js\nawait ad.object(\"My Object\", \"SomeOU\").addToGroup(\"testGroup\")\n// =\u003e { success: true }\n```\n\n#### ad.object(objectName).setProperties(properties)\n\nUpdates already existing properties of the given object in Active Directory.\n\n```js\nawait ad.object(\"My Object\").setProperties({\n\tcustomProperty: \"someValue\"\n})\n// =\u003e { success: true }\n```\n\n\n#### ad.object(objectName, location).setProperties(properties)\n\nUpdates already existing properties of the given object at the given location in Active Directory.\n\n```js\nawait ad.object(\"My Object\", \"SomeOU\").setProperties({\n\tcustomProperty: \"someValue\"\n})\n// =\u003e { success: true }\n```\n\n\n### Other methods\n\n#### ad.other().get(filter)\n\nReturns all objects that are not users or groups.\n\n```js\nawait ad.other().get();\n// =\u003e [{ ... }, { ... }];\n\n```\n\n#### ad.all().get(filter)\n\nReturns all objects in the Active Directory instance, grouping by `users`, `groups` and `other`.\n\n```js\nawait ad.other().get();\n// =\u003e [users: [...], groups: [...], other: [...]];\n\n```\n\n#### ad.find(searchString)\n\nReturns a raw search of the entire Active Directory.\n\n```js\nawait ad.search('CN=Da*');\n// =\u003e [{...}, {...}];\n\n```\n\n\n### Caching\n\n#### ad.cache(boolean)\n\nEnables or disables caching. Defaults to `true`.\n\n```js\nad.cache(false);\n```\n\n#### ad.cacheTimeout(millis)\n\nSets the amount of milliseconds before a cached item expires. Defaults to ten minutes. Chainable to `ad.cache`.\n\n```js\nad.cache(true).cacheTimeout(60000);\n```\n\n\n## Why?\n\nActive Directory / LDAP can be hard. Some of us are stuck with it.\n\nShould you really have to know that `cn` stands for `Common Name` (or was it `Canonical`) in order to use it? Or that `sn` is a `surname`*? I dislike systems that require detailed knowledge of their dirty laundry to do anything with them.\n\nSo this was a selfish project, really.\n\nMade with \u003c3 by [dthree](https://github.com/dthree).\n\n_*last name_\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhacktix%2Fad2","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhacktix%2Fad2","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhacktix%2Fad2/lists"}