{"id":16024278,"url":"https://github.com/axelson/password-validator","last_synced_at":"2026-03-02T14:43:02.367Z","repository":{"id":44908223,"uuid":"98978917","full_name":"axelson/password-validator","owner":"axelson","description":"A Elixir library to validate passwords, with built-in validators for password length as well as the character sets used","archived":false,"fork":false,"pushed_at":"2025-02-15T23:51:46.000Z","size":93,"stargazers_count":21,"open_issues_count":1,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-06T20:48:12.675Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/password_validator","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/axelson.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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":"2017-08-01T08:35:40.000Z","updated_at":"2025-04-01T15:28:00.000Z","dependencies_parsed_at":"2024-07-14T14:54:27.952Z","dependency_job_id":"17b6db2b-deb8-4663-8993-c8a8eeca3902","html_url":"https://github.com/axelson/password-validator","commit_stats":{"total_commits":70,"total_committers":3,"mean_commits":"23.333333333333332","dds":0.05714285714285716,"last_synced_commit":"83cabca1f9eab2bd862aca3eac8cc62bdd6a9fe1"},"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelson%2Fpassword-validator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelson%2Fpassword-validator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelson%2Fpassword-validator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/axelson%2Fpassword-validator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/axelson","download_url":"https://codeload.github.com/axelson/password-validator/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247550653,"owners_count":20956985,"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-10-08T19:06:23.985Z","updated_at":"2026-03-02T14:43:02.361Z","avatar_url":"https://github.com/axelson.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# PasswordValidator\n\n[![Module Version](https://img.shields.io/hexpm/v/password_validator.svg)](https://hex.pm/packages/password_validator)\n[![Hex Docs](https://img.shields.io/badge/hex-docs-lightgreen.svg)](https://hexdocs.pm/password_validator/)\n[![Total Download](https://img.shields.io/hexpm/dt/password_validator.svg)](https://hex.pm/packages/password_validator)\n[![License](https://img.shields.io/hexpm/l/password-validator.svg)](https://github.com/axelson/password-validator/blob/master/LICENSE.md)\n[![Last Updated](https://img.shields.io/github/last-commit/axelson/password-validator.svg)](https://github.com/axelson/password-validator/commits/master)\n\nPasswordValidator is a library to validate passwords, makes sense doesn't it? By\ndefault two validators are built in, but it is also possible to create your own\ncustom validator for more advanced usage.\n\nValidators:\n* LengthValidator - validates the length of the password\n* CharacterSetValidator - validates the characters contained within the\n  password, number of lower case, number of upper case, number of special\n  characters, etc.\n* [ZXCVBNValidator](https://github.com/axelson/password-validator-zxcvbn) - Uses\n  Dropbox's [zxcvbn](https://github.com/dropbox/zxcvbn) algorithm to rate\n  passwords\n\nThe primary use case is validating an `%Ecto.Changeset{}`\n\n## Installation\n\n`PasswordValidator` is [available in Hex](https://hex.pm/packages/password_validator), the package can be installed\nby adding `password_validator` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:password_validator, \"~\u003e 0.5\"},\n  ]\nend\n```\n\nThe docs can be found at [https://hexdocs.pm/password_validator](https://hexdocs.pm/password_validator).\n\n## Usage\n\nPasswordValidator will typically be used within the changeset function of an Ecto schema:\n\n``` elixir\n@password_opts [\n  length: [min: 7, max: 30, messages: [too_short: \"Password is too short!\"]],\n  character_set: [\n    lower_case: 5,  # at least five lower case letters\n    upper_case: [3, :infinity], # at least three upper case letters\n    numbers: [1, 4],  # from 1 to 4 number characters\n    special: [0, 0],  # no special characters allowed\n  ]\n]\n\ndef changeset(user, attrs) do\n  user\n  |\u003e cast(attrs, [:name, :age, :password])\n  |\u003e validate_required([:name, :age, :password])\n  # Add this to your changeset\n  |\u003e PasswordValidator.validate(:password, @password_opts)\nend\n```\n\nExample interactive usage:\n\n``` elixir\niex\u003e opts = [\n...\u003e   length: [min: 12, max: 30],\n...\u003e ]\niex\u003e changeset = Ecto.Changeset.change({%{password: \"simple_pass\"}, %{}}, %{})\n#Ecto.Changeset\u003caction: nil, changes: %{}, errors: [], data: %{password: \"simple_pass\"}, valid?: true, ...\u003e\niex\u003e PasswordValidator.validate(changeset, :password, opts)\n#Ecto.Changeset\u003caction: nil, changes: %{}, errors: [password: {\"String is too short. Only 11 characters instead of 12\", [validator: PasswordValidator.Validators.LengthValidator, error_type: :too_short]}], data: %{password: \"simple_pass\"}, valid?: false, ...\u003e\n```\n\nFull example:\n``` elixir\niex\u003e opts = [\n...\u003e   length: [min: 5, max: 30],\n...\u003e   character_set: [\n...\u003e     lower_case: 1,  # at least one lower case letter\n...\u003e     upper_case: [3, :infinity], # at least three upper case letters\n...\u003e     numbers: [0, 4],  # at most 4 numbers\n...\u003e     special: [0, 0],  # no special characters allowed\n...\u003e   ]\n...\u003e ]\niex\u003e changeset = Ecto.Changeset.change({%{password: \"Simple_pass12345\"}, %{}}, %{})\niex\u003e changeset = PasswordValidator.validate(changeset, :password, opts)\niex\u003e changeset.errors\n[password: {\"Too many special (1 but maximum is 0)\", [\n  {:validator, PasswordValidator.Validators.CharacterSetValidator},\n  {:error_type, :too_many_special}\n]},\npassword: {\"Too many numbers (5 but maximum is 4)\", [\n  {:validator, PasswordValidator.Validators.CharacterSetValidator},\n  {:error_type, :too_many_numbers}\n]},\npassword: {\"Not enough upper_case characters (only 1 instead of at least 3)\", [\n  {:validator, PasswordValidator.Validators.CharacterSetValidator},\n  {:error_type, :too_few_upper_case}\n]}]\n```\n\nIf you want to check that a PasswordValidator error was added then in the changeset's errors field you can check that there is an error with the key `:validator`\n\nPasswordValidator can also be run directly on a String:\n\n```\niex\u003e opts = [\n...\u003e   length: [max: 6],\n...\u003e ]\niex\u003e PasswordValidator.validate_password(\"too_long\", opts)\n{:error, [\"String is too long. 8 but maximum is 6\"]}\n```\n\nNote: The `CharacterSetValidator` set of allowed special characters defaults to\nany character that is not lower case, upper case, or a number. If the\n`CharacterSetValidator` is passed `allowed_special_characters` (as a string)\nthen just those characters will be considered as special characters and any\nother characters will be considered \"other\" and will fail the password check.\nFor full details see the `CharacterSetValidator` docs.\n\nNote: On an invalid configuration the library will raise an error.\n\n## Custom validators\n\nCustom Validators need to implement the `PasswordValidator.Validator` behaviour.\nCurrently the only callback is `validate`. They can then be supplied as options (to either `PasswordValidator.validate/3` or `PasswordValidator.validate_password/2`)\n\n## Constraints\n\n* Doesn't deal well with non-latin characters\n* Currently always pulls in Ecto as a dependency\n\n## Contributing\n\nTo run the default test suite, run `mix test`\n\nPR's and discussions welcome!\n\n## Copyright and License\n\nCopyright (c) 2017 Jason Axelson\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxelson%2Fpassword-validator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faxelson%2Fpassword-validator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faxelson%2Fpassword-validator/lists"}