{"id":17355220,"url":"https://github.com/zephinzer/anna","last_synced_at":"2025-08-09T17:07:44.491Z","repository":{"id":79926412,"uuid":"117454864","full_name":"zephinzer/anna","owner":"zephinzer","description":"Opinionated plug-and-play accounts \u0026\u0026 authentication (ANNA) microservice for use in systems that require a user account system.","archived":false,"fork":false,"pushed_at":"2018-01-18T14:20:59.000Z","size":97,"stargazers_count":1,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-07-02T01:41:02.419Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zephinzer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"zenodo":null}},"created_at":"2018-01-14T18:18:09.000Z","updated_at":"2018-01-17T12:19:02.000Z","dependencies_parsed_at":null,"dependency_job_id":"c7483052-fe52-41e2-a6cd-1828c0756984","html_url":"https://github.com/zephinzer/anna","commit_stats":null,"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/zephinzer/anna","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephinzer%2Fanna","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephinzer%2Fanna/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephinzer%2Fanna/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephinzer%2Fanna/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zephinzer","download_url":"https://codeload.github.com/zephinzer/anna/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zephinzer%2Fanna/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":269606235,"owners_count":24446147,"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","status":"online","status_checked_at":"2025-08-09T02:00:10.424Z","response_time":111,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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-10-15T17:42:39.882Z","updated_at":"2025-08-09T17:07:44.473Z","avatar_url":"https://github.com/zephinzer.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# **Anna** Microservice\n\n[![Build Status](https://travis-ci.org/zephinzer/anna.svg?branch=master)](https://travis-ci.org/zephinzer/anna) [![Maintainability](https://api.codeclimate.com/v1/badges/888a37dfeefee615573d/maintainability)](https://codeclimate.com/github/zephinzer/anna/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/888a37dfeefee615573d/test_coverage)](https://codeclimate.com/github/zephinzer/anna/test_coverage)\n\nOpinionated plug-and-play accounts \u0026\u0026 authentication (ANNA) microservice for use in systems that require a user account system.\n\n- [Overview \u0026 Goals](#overview--goals)\n- [RESTful Endpoints](#restful-endpoints)\n- [Data Schema](#data-schema)\n- [Deployment Configuration](#deployment-configuration)\n- [Contributing](#contributing)\n\n## Overview \u0026 Goals\nAnna was designed as a user management microservice meant for deployment in a microservice/service-oriented architecture. The over-arching goal is to be able to deploy Anna as a service and have other services refer to it as a central source of truth for user information.\n\n### Functional Goals\n\n❌ create an account  \n❌ retrieve account information  \n❌ upate account information  \n❌ create one or more user profiles per account  \n❌ update user profile  \n❌ delete user profiles  \n❌ delete an account and all profile related data  \n❌ handle logins using token-based authentication  \n❌ handle logouts using token-based authentication  \n❌ report session status of a user for microservices  \n\n### Non-Functional Goals\n\n✅ Containerised deployment  \n✅ Expose Prometheus metrics  \n✅ Basic Auth protection for Prometheus metrics endpoint  \n✅ Expose a health check endpoint for container orchestration systems  \n✅ Expose a readiness check endpoint for container orchestration systems  \n✅ Cross-Origin-Resource-Sharing (CORS) enabled  \n✅ response compression  \n✅ RESTful API  \n❌ authentication via JSON web tokens  \n❌ roles based access control  \n❌ level-based logging  \n❌ FluentD logs exporter  \n❌ HTTP/2 communication between services  \n❌ secure communication channel between services  \n❌ GraphQL API  \n\n### Assumptions\n\n- Each account is associated with only one email address\n\n### Entities \u0026 Relationships\n\n#### User\nA user represents an atomic account and stores contact information and credentials.\n\n#### Profiles\nA profile represents the public information related to a user. A profile belongs to a single user, but each user can have multiple profiles.\n\n#### Session\nA session represents the span of time a user spends between logging in and logging out. Each session belongs to a single user, but each user can have multiple sessions.\n\n#### Audit\nAn audit represents changes to any of the afore-mentioned entities and provides a way for verifying user claims. Audits are weakly linked (non-database integrity checked) to updates in user, profile and session information.\n\n## Support Endpoints\n\n### GET `/metrics`\n\u003e Basic Auth protected. This endpoint can be [configured using an environment variable](#metrics_endpoint)\nExposes the Prometheus metrics.\n\n### GET `/healthz`\n\u003e This endpoint can be [configured using an environment variable](#health_check_endpoint) for customisation purposes\n\nExposes a health-check for container orchestration systems to call.\n\nReturns `HTTP 200` with a JSON response body of `\"ok\"` when all is good.\n\n### GET `/readyz`\n\u003e This endpoint can be [configured using an environment variable](#readiness_check_endpoint) for customisation purposes\n\nExposes a readiness-check for container orchestration systems to call. We currently check for:\n\n- database configuration error\n- database client specification error\n- database connection error\n\nReturns `HTTP 200` with a JSON response body of `\"ok\"` when all is good.\n\nReturns `HTTP 500` with a JSON response body of all errors when something is wrong.\n\n## RESTful Endpoints\n\n### GET `/user`\nRetrieves the profile for the current user as identified in the `X-AuthToken` header.\n\n### POST `/user`\nCreates a new user.\n\n### PATCH `/user`\nUpdates the user information for the user as identified in the `X-AuthToken` header.\n\n### DELETE `/user`\nDeletes the user as identified in the `X-AuthToken` header.\n\n### GET `/user/:id`\nRetrieves user information for the user with ID :id.\n\n### GET `/user/:id/profiles`\nRetrieves the profiles for the user identified with ID :id.\n\n### GET `/profiles`\nRetrieves profiles for the user identified in the `X-AuthToken` header.\n\n### GET `/profile/:id`\nRetrieves the profile with ID :id belonging to the user identified in the `X-AuthToken` header.\n\n### POST `/profile`\nCreates a new profile for the user identified in the `X-AuthToken` header.\n\n### PATCH `/profile/:id`\nUpdates the profile identified with ID :id for the user identified in the `X-AuthToken` header.\n\n### DELETE `/profile/:id`\nDeletes the profile identified with ID :id for the user identified in the `X-AuthToken` header.\n\n### GET `/session`\nVerifies if the user is logged in and returns session details if so.\n\n### POST `/session`\nLogs a user in and returns an authentication token.\n\n### DELETE `/session`\nExplicitly logs a user out.\n\n## Data Schema\n\n### User Fields\n\n#### `id` : *number*\n\n#### `uuid` : *string*\n\n#### `handle` : *string*\n\n#### `primary_email` : *string*\n\n#### `secondary_email` : *string*\n\n#### `phone_number` : *string*\n\n#### `password` : *string*\n\n#### `last_modified` : *datetime*\n\n#### `date_created` : *datetime*\n\n### User-Profile Fields\n\n#### `user_id` : *number*\n\n#### `profile_id` : *number*\n\n### Profile Fields\n\n#### `id` : *number*\n\n#### `name_full` : *string*\n\n#### `name_first` : *string*\n\n#### `name_middle` : *string*\n\n#### `name_last` : *string*\n\n#### `name_display` : *string*\n\n#### `picture_display` : *string*\n\n#### `bio` : *text*\n\n#### `gender` : *enum*\n\nEnumerates to one of:\n\n- male\n- female\n- trans_male\n- trans_female\n- others\n- none\n\n#### `birth_date` : *date*\n\n#### `email` : *string*\n\n#### `contact_email` : *string*\n\n#### `contact_number` : *string*\n\n#### `contact_url` : *string*\n\n#### `contact_address` : *text*\n\n#### `others` : *text*\n\n#### `provider_id` : *string*\n\n#### `provider_access_token` : *string*\n\n#### `provider_access_secret` : *string*\n\n#### `last_modified` : *datetime*\n\n#### `date_created` : *datetime*\n\n### Session Fields\n\n#### `id` : *string*\n\n#### `user_id` : *string*\n\n#### `user_agent` : *string*\n\n#### `ipv4_address` : *string*\n\n#### `ipv6_address` : *string*\n\n#### `date_ended` : *datetime*\n\n#### `date_created` : *datetime*\n\n## Deployment Configuration\n\n### `ALLOWED_ORIGINS`\nWhen this is defined, Cross-Origin-Resource-Sharing (CORS) is activated. If the value is an empty string, all origins will be allowed, otherwise, CORS is activated for the specified domains delimited by a comma.\n\nWhen left undefined, Cross-Origin-Resource-Sharing is disabled.\n\n\u003e Defaults to `undefined`.\n\n### `BASIC_AUTH_USERS`\nWhen this is defined, basic auth will be applied to the following endpoints:\n\n- `/metrics`\n\nThe value for this environment variable should be an array of `username:password`s separated by commas. An example:\n\n```\nBASIC_AUTH_USERS=user1:password1,user2:password2\n```\n\nThe above will create two users, `user1` and `user2`, with their respective passwords.\n\n\u003e Defaults to `undefined`.\n\n### `DB_CLIENT`\nDefines the client we should be connecting to the database with. This can be one of `mysql`, `mysql2`, `sqlite3`, `postgresql`.\n\n\u003e Defaults to `\"mysql2\"`.\n\n### `DB_CONNECTION_POOL_MAX`\nDefines the maximum number of connections we should maintain with the database.\n\n\u003e Defaults to `10`.\n\n### `DB_CONNECTION_POOL_MIN`\nDefines the minimum number of connections we should maintain with the database.\n\n\u003e Defaults to `2`.\n\n### `DB_CONNECTION_URL`\nDefines a connection URL.\n\n\u003e Defaults to an object defining the database host (`DB_HOST`), database port (`DB_PORT`), database schema (`DB_SCHEMA`), database user (`DB_USER`) and the password for the user (`DB_PASSWORD`).\n\n### `DB_HOST`\nDefines the database host we should be connecting to. This is ignored if `DB_CONNECTION_URL` is specified.\n\n\u003e Defaults to `\"localhost\"`.\n\n### `DB_MIGRATIONS_TABLE_NAME`\nDefines the name for the database migration table we will be using.\n\n\u003e Defaults to `\"db_migrations_list\"`.\n\n### `DB_PASSWORD`\nDefines the password for the database user defined in the `DB_USER` environment variable. This is ignored if `DB_CONNECTION_URL` is specified.\n\n\u003e Defaults to `\"anna\"`.\n\n### `DB_PORT`\nDefines the database port we should be connecting to. This is ignored if `DB_CONNECTION_URL` is specified.\n\n\u003e Defaults to `3306`.\n\n### `DB_SCHEMA`\nDefines the database schema we should be using. This is ignored if `DB_CONNECTION_URL` is specified.\n\n\u003e Defaults to `\"anna\"`.\n\n### `DB_USER`\nDefines the database user we should be using. This is ignored if `DB_CONNECTION_URL` is specified.\n\n\u003e Defaults to `\"anna\"`.\n\n### `HEALTH_CHECK_ENDPOINT`\nDefines the endpoint for health checks to be done on.\n\n\u003e Defaults to `/healthz`.\n\n### `METRICS_ENDPOINT`\nDefines the endpoint for metrics.\n\n\u003e Defaults to `/metrics`.\n\n### `NODE_ENV`\nDefines the environment we are running in.\n\nValid values are `\"development\"` or `\"production\"`. If it is neither, the server assumes `\"development\"`\n\n\u003e Defaults to `\"development\"`.\n\n### `PORT`\nDefines the port which the server should listen on.\n\n\u003e Defaults to 4000.\n\n### `READINESS_CHECK_ENDPOINT`\nDefines the endpoint for readiness checks to be done on.\n\n\u003e Defaults to `/readyz`.\n\n### `REALM`\nSpecifies the realm for basic authentication.\n\n\u003e Defaults to `\"ANNA\"`.\n\n## Notes On Contributing\n\n### Linting\nWe use ESLint to maintain code conventions and quality. To run the linter:\n\n```bash\nnpm run eslint;\n```\n\nSee the [Travis CI script](./.travis.yml) for more info.\n\n### Functional Testing\nTwo types of tests are present in our tests. The first is unit tests which are most of tests you will see. The second is systems tests which simulates execution of the server and running queries against it - this is found in the `server.test.js`.\n\nWe use `mocha`, `chai`, `sinon` and `supertest` to validate functional behaviour of the service.\n\nTo run the tests:\n\n```bash\nnpm run mocha;\n```\n\nTo run it in development which adds watching and allows for `.only` and `xit` keywords:\n\n```bash\nnpm run mocha-watch;\n```\n\nSee the [Travis CI script](./.travis.yml) for more info.\n\n### Running Locally\nDuring development, we try to keep the feedback loop short, so we avoid running Anna in a Docker container.\n\n#### Database In Development\nRun the database alone using:\n\n```bash\nnpm run db-development\n```\n\nIf you would like it to run in the background, use:\n\n```bash\nnpm run db-development -- -d\n```\n\nThe above command starts the database and builds the development image so that we can do a database migration and seed. If the database migration/seed files are changed, you will have to run the above command again to get the correct version of your database schema.\n\n#### Running Application In Development\nIn development, we can use a live-reload tool such as `nodemon` which watches for file changes and reloads the application when any changes are detected. This allows us to write code, save it and have our server reflect the newly acquired behaviour. To activate this, use:\n\n```bash\nnpm run dev\n```\n\n#### Configuring During Development\nThe file `./.env` contains configurations that assume a database is running on the local computer. This database can be either a local MySQL instance, or you can spin it up using `docker-compose` using `npm run db-development` as shown above.\n\n### Building\nTo create a development build, run:\n\n```bash\nnpm run build -- development\n```\n\nTo create a production build, run:\n\n```bash\nnpm run build -- production\n```\n\nBuilding has no real use, we only use it in the Travis pipeline to push to DockerHub.\n\n### Contribution Flow\n\n#### Raise Issue\n[Start an issue](https://github.com/zephinzer/anna/issues) so that everyone knows what you're working on. It'll suck if someone was doing the same thing you did and only one person's code will be merged in.\n\nYou can also assign the issue to yourself if you are taking up the work.\n\n#### Fork \u0026 Build\nFork this repository and make your changes in your `master` branch. After making your changes:\n\n1. **Update the `README.md`** for the changes you have made\n2. **Add yourself as a contributor** to the `package.json` file (yay)\n3. **Write/rewrite the tests for components you've changed** - think of the tests as functional specifications so that if someone needs to see how something is used, they can refer to the tests.\n4. **Add an appropriate version bump** - use `[major version bump]` for a major version bump and `[minor version bump]` for a minor one according to the [SEMVER](https://semver.org/) specification. Patch versions are automatically bumped if none of those tags are available.\n\n#### Merge Request\nDone making changes? Submit a Pull Request and let the Travis CI pipeline pass. On passing, your code will be reviewed using the Code Climate statistics as well as a human check to ensure leaness and maintainability.\n\n- - -\n\n# Cheers!\n\nFor reading till the end, here's a potato.\n\n![potato](https://cdn.shopify.com/s/files/1/1017/2183/t/2/assets/live-preview-potato.png?4839514862613583315)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzephinzer%2Fanna","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzephinzer%2Fanna","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzephinzer%2Fanna/lists"}