{"id":22572731,"url":"https://github.com/dmfed/users","last_synced_at":"2025-03-28T14:45:01.648Z","repository":{"id":45674998,"uuid":"512907814","full_name":"dmfed/users","owner":"dmfed","description":"very ligthweight and basic user management","archived":false,"fork":false,"pushed_at":"2022-07-30T22:19:54.000Z","size":17,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-02T15:13:48.636Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","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/dmfed.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":"2022-07-11T21:01:58.000Z","updated_at":"2022-07-11T23:56:23.000Z","dependencies_parsed_at":"2022-08-28T01:51:31.887Z","dependency_job_id":null,"html_url":"https://github.com/dmfed/users","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmfed%2Fusers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmfed%2Fusers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmfed%2Fusers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dmfed%2Fusers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dmfed","download_url":"https://codeload.github.com/dmfed/users/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246049618,"owners_count":20715510,"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":"2024-12-08T02:11:25.375Z","updated_at":"2025-03-28T14:45:01.624Z","avatar_url":"https://github.com/dmfed.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Package users\n\n**users** is very basic CRUD for storing user data including username, secret,\nattributes (Go map[string]string data type) and created/updated timestamps. The package is\nintended to be used in smaller projects requiring user authentication. Think of\nyour pet project involving access by multiple users. \n\nCurrently two underlying storage types are supported: Postgres and SQLite.\n\n### Usage\n\nUser info is stored in User struct:\n\n```go\ntype User struct {\n\tUsername string            // username\n\tSecret   string            // secret (e.g. password hash)\n\tEnabled  bool              // is user active\n\tAttrs    map[string]string // various stuff you might put here\n\tCreated  time.Time         // create time\n\tUpdated  time.Time         // last update time\n}\n```\n\nAll the useful stuff can be done with two interfaces exposed by the package.\n\n```go\ntype Authenticator interface {\n\tAuthenticate(username, password string) (bool, error) // Authenticate returns true if password for username checks out.\n}\n\n// Repository is a basic CRUD interface to\n// store User structs.\ntype Repository interface {\n\tGet(username string) (User, error)           // Get returns user with username\n\tPut(user User) error                         // Put saves User struct\n\tUpd(user User) error                         // Update updates User\n\tDel(username string) error                   // Del deletes user with username\n\tRename(oldname string, newname string) error // Rename renames user with oldname setting username to newname\n\tClose() error                                // Closes safely closes the repository\n}\n```\n\nUsage example can be found in **example** directory. \n\nWhen instantiated with **New** function the Authenticator uses bcrypt unde the hood\nto compare provided password with stored hash. \n\nThe package contains a function **BcryptHash** to generate hash of a password (a string).\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\n\t\"github.com/dmfed/users\"\n)\n\nfunc main() {\n\trepo, auth, err := users.NewWithSQLite(\"./testfoo.db\")\n\tif err != nil {\n\t\tfmt.Println(err)\n\t\treturn\n\t}\n\n\terr = repo.Put(users.User{\n\t\tUsername: \"testuser\",\n\t\tSecret:   users.BcryptHash(\"testsecret\"),\n\t\tAttrs: map[string]string{\n\t\t\t\"happy\": \"yes\",\n\t\t},\n\t})\n\n\tif err != nil {\n\t\tfmt.Println(\"OMG we failed\", err)\n\t}\n\n\tu, _ := repo.Get(\"testuser\")\n\tfmt.Println(u)\n\n\tok, _ := auth.Authenticate(\"testuser\", \"testsecret\") // check that password for testuser is \"testsecret\"\n\t// ok is true, err is nil\n\tif !ok {\n\t\tfmt.Println(\"password does not match username 'testuser'\")\n\t}\n\n\trepo.Del(\"testuser\")\n}\n```\n**Put** and **Upd** methods enforce non-zero timestamps for User struct. Actually the only required values for User struct\nare Username and Secret. Failing to fill these will result in non-nil errors from Put and Upd.\n\nAlso note that **Put** method sets user **Enabled** field to **true**.\n\n### command-line utility\n\n**cmd** directory contains a handy cli utility to manage users. \n```bash\n\u003e cd cmd\n\u003e go build\n\u003e ./cmd --help                                                                                                                                   \nUsage of ./cmd:\n  -a\t\u003cusername\u003e \u003chash\u003e add user\n  -c\t\u003cusername\u003e \u003cpassword\u003e check user password against db record\n  -d\t\u003cusername\u003e delete user with username\n  -h\t\u003cpassword\u003e print hash of supplied password\n  -s string\n    \tdata source (sqlite filename or Postgres DSN formatted as postgres://username:password@localhost:5432/db?sslmode=disable)\n  -show\n    \t\u003cusername\u003e show database record a user\n  -t string\n    \tdata source type (sqlite or postgres) (default \"sqlite\")\n  -toggle\n    \ttoggle user \"enabled\" property\n  -u\t\u003cusername\u003e \u003chash\u003e update user record with provided hash\n\n\u003e ./cmd -s testdb.db -a testuser $(./cmd -h password)                                                                                              ✹main \nadded user testuser\n\n\u003e ./cmd -s testdb.db -show testuser                                                                                                              ✹ ✭main \nName: testuser\nHash: $2a$10$kwINOS5wz4L6Ozrho9yEFuRqSo40tMxAXnz0ssC7TThFW.LDkvD.2\nEnabled: true\nAttrs: map[]\nCreated: 2022-07-14 20:37:15 +0300 +0300\nUpdated: 2022-07-14 20:37:15 +0300 +0300\n\n\u003e    \n```\n### Thanks\n\nThanks to **mattn** the creator of excellent library https://github.com/mattn/go-sqlite3\n\nThanks to **jackc** the creator of pgx https://github.com/jackc/pgx","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmfed%2Fusers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdmfed%2Fusers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdmfed%2Fusers/lists"}