{"id":23814219,"url":"https://github.com/stuartpb/whomst","last_synced_at":"2025-08-04T18:34:38.396Z","repository":{"id":50922287,"uuid":"141435442","full_name":"stuartpb/whomst","owner":"stuartpb","description":"Gets user and group info, by any means necessary","archived":false,"fork":false,"pushed_at":"2023-07-11T12:12:50.000Z","size":28,"stargazers_count":2,"open_issues_count":7,"forks_count":3,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-12-19T08:13:37.153Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/stuartpb.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}},"created_at":"2018-07-18T13:01:14.000Z","updated_at":"2023-03-04T05:20:30.000Z","dependencies_parsed_at":"2022-08-28T08:41:21.732Z","dependency_job_id":null,"html_url":"https://github.com/stuartpb/whomst","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fwhomst","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fwhomst/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fwhomst/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stuartpb%2Fwhomst/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stuartpb","download_url":"https://codeload.github.com/stuartpb/whomst/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":232149969,"owners_count":18479564,"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":[],"created_at":"2025-01-02T03:46:52.826Z","updated_at":"2025-01-02T03:46:53.279Z","avatar_url":"https://github.com/stuartpb.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# whomst\n\nGets user and group info, by any means necessary\n\n![whomst](https://user-images.githubusercontent.com/572196/42921299-331bb322-8ad0-11e8-8cc2-b0713b1871fe.jpg)\n\n## Background\n\nNode doesn't have a built-in function to resolve an OS username or groupname to a UID or GID (or vice versa). There are a few native modules that expose the functions necessary to get this information, but native modules can't always be relied upon (in environments where the toolchain isn't present, or the architecture isn't supported, or the targeted ABI is unmaintained, or any of a number of other possible ways native modules can break).\n\nThere are other ways to get this information, but they've all got possible pitfalls themselves. You can query the system database with the `getent` binary, but that will fail if `getent` isn't present. You can try reading the contents of `/etc/passwd`, but that will fail if the current user doesn't have permission to access `/etc/passwd` (or if user IDs are coming from a different source, such as LDAP). You can exploit the locations in Node's code where it calls out to the relevant functions as a side effect (namely `process.setuid` and `os.userInfo`, which both incorporate `getpwnam` under the hood), but this requires the user to have permission to setuid to the user being queried, not to mention being *incredibly* hacky. (Nonetheless, this last technique is the approach [actually used internally by npm][uid-number].)\n\n[uid-number]: https://github.com/npm/uid-number\n\nFor a program to truly be resilient against all these possible contingencies, it should be ready to try *all* of the possible techniques.\n\n## Implementation\n\nwhomst will try obtaining info, in order of availability, from:\n\n- the `getpwnam`and `getgrnam` functions from the [posix][] module\n- the functions from the [userid][] module (if installed)\n- the `getent(1)` binary\n- the contents of `/etc/passwd` and `/etc/group`\n- the results of doing a `setuid` or `setgid` with the given name (as used by   the [uid-number][] module)\n- as a last-ditch effort, seeing if the uid matches the current user's info\n\n[posix]: https://github.com/ohmu/node-posix\n[userid]: https://github.com/jandre/node-userid\n\nAs of v0.1.2, not all of these code paths have been tested (though they are all believed to be implemented).\n\n## API\n\n`whomst.user` and`whomst.group` take a number or string and return a promise. `whomst.sync.user` and `whomst.sync.group` do the same thing, but synchronously instead of via promises.\n\nThese functions return objects compatible with the return values of the corresponding functions from the `posix` package. See the documentation for [posix.getpwnam][] and [posix.getgrnam][] for examples of returns from whomst.user and whomst.group, respectively.\n\n[posix.getpwnam]: https://github.com/ohmu/node-posix#posixgetpwnamuser\n[posix.getgrnam]: https://github.com/ohmu/node-posix#posixgetgrnamgroup\n\nNote that not all fields are guaranteed: if `whomst.group` has to fall back to the `setgid` hack method for determining a group's gid, the return value may only contain `name` and `gid` (or even only `gid`, if the name wasn't provided). This means that *you may not be able to determine a group's name from its gid*, if all the more-reliable mechanisms fail.\n\n## Tips\n\nUnlike some similar modules like `uid-number`, `whomst` does not cache any results between calls (as these results could, in theory, change between two separate invocations). If you wish to cache results between calls to this function (say, if you're going to make thousands of calls to it in the space of a very short time), you may wish to implement a memoization layer like [fast-memoize][] around `whomst`.\n\n[fast-memoize]: https://www.npmjs.com/package/fast-memoize\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartpb%2Fwhomst","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstuartpb%2Fwhomst","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstuartpb%2Fwhomst/lists"}