Skip to content

Commit

Permalink
Merge b1747a7 into a3cc791
Browse files Browse the repository at this point in the history
  • Loading branch information
ezrajrice committed Nov 4, 2022
2 parents a3cc791 + b1747a7 commit 7069d43
Show file tree
Hide file tree
Showing 7 changed files with 303 additions and 107 deletions.
70 changes: 70 additions & 0 deletions .github/workflows/deploy_to_pypi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
name: deploy_to_pypi

on:
push:
tags:
- "v*"

jobs:
build-n-publish:
name: Build and publish Python distributions to PyPI and TestPyPI
runs-on: ubuntu-latest

steps:
- name: Checkout source
uses: actions/checkout@release

- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: "3.10"

- name: Build source and wheel distributions
run: |
python -m pip install --upgrade build twine
python -m build
twine check --strict dist/*
- name: Publish distribution to Test PyPI
uses: pypa/gh-action-pypi-publish@release
with:
user: __token__
password: ${{ secrets.TEST_PYPI_API_TOKEN }}
repository_url: https://test.pypi.org/legacy/
skip_existing: true

- name: Publish distribution to PyPI
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
uses: pypa/gh-action-pypi-publish@release
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
skip_existing: true

- name: Create GitHub Release
id: create_release
uses: actions/create-release@v3
env:
GITHUB-TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: ${{ github.ref }}
draft: false
prerelease: false

- name: Get Asset name
run: |
export PKG=$(ls dist/ | grep tar)
set -- $PKG
echo "name=$1" >> $GITHUB_ENV
- name: Upload Release Asset (sdist) to GitHub
id: upload-release-asset
uses: actions/upload-release-asset@v3
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: dist/${{ env.name }}
asset_name: ${{ env.name }}
asset_content_type: application/zip
54 changes: 45 additions & 9 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -1,37 +1,73 @@
name: test

on: [push, pull_request]
on:
push:
branches:
- "main"
- "release"
pull_request:
branches:
- "*"

env:
GITHUB-TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
black-lint:
name: Lint with Black
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: psf/black@fcf97961061982656a1384ecc1628e217a52a88c

test:
name: Test django-advanced-password-validation
runs-on: ubuntu-latest
strategy:
matrix:
versions:
- { "djangoVersion": "2.2.28", "pythonVersion": "3.7" }
- { "djangoVersion": "2.2.28", "pythonVersion": "3.8" }
- { "djangoVersion": "2.2.28", "pythonVersion": "3.9" }
- { "djangoVersion": "2.2.28", "pythonVersion": "3.10" }
- { "djangoVersion": "3.2.16", "pythonVersion": "3.7" }
- { "djangoVersion": "3.2.16", "pythonVersion": "3.8" }
- { "djangoVersion": "3.2.16", "pythonVersion": "3.9" }
- { "djangoVersion": "3.2.16", "pythonVersion": "3.10" }
- { "djangoVersion": "4.0.8", "pythonVersion": "3.8" }
- { "djangoVersion": "4.0.8", "pythonVersion": "3.9" }
- { "djangoVersion": "4.0.8", "pythonVersion": "3.10" }
- { "djangoVersion": "4.1.2", "pythonVersion": "3.8" }
- { "djangoVersion": "4.1.2", "pythonVersion": "3.9" }
- { "djangoVersion": "4.1.2", "pythonVersion": "3.10" }
steps:
- name: Checkout 🛎️
# Checkout the source
- name: Checkout
uses: actions/checkout@v3
- name: Set up Python 🐍
# Setup Python
- name: Set up Python
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.versions.pythonVersion }}
- name: Install dependencies 📦
# Install Dependencies
- name: Install dependencies
run: python -m pip install -r requirements_test.txt && python -m pip install -e .
- name: Install Django ${{ matrix.versions.djangoVersion }} 📦
# Install Django
- name: Install Django ${{ matrix.versions.djangoVersion }}
run: python -m pip install Django==${{ matrix.versions.djangoVersion }}
- name: Check types, syntax and duckstrings 🦆
# Check syntax
- name: Check types, syntax and duckstrings
run: |
mypy --exclude=setup.py .
flake8 .
interrogate --quiet --fail-under=90 .
- name: Test Django ${{ matrix.versions.djangoVersion }} with coverage 🧪
# Test package
- name: Test Django ${{ matrix.versions.djangoVersion }} with coverage
run: coverage run --source=django_advanced_password_validation -m pytest . && coverage lcov -o coverage.lcov
- name: Submit coverage report to Coveralls 📈
# Generate Coverage Report
- name: Submit coverage report to Coveralls
if: ${{ success() }}
uses: coverallsapp/github-action@1.1.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: ./coverage.lcov

46 changes: 24 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,49 +1,50 @@
# django-advanced_password_validation
# django_advanced_password_validation

Extends Django password validation options to include minimum uppercase, minimum lowercase, minimum numerical, and minimum special characters. This was created in an attempt to keep up with industry standards for strong user passwords.
[![test](https://github.com/ezrajrice/django_advanced_password_validation/actions/workflows/test.yaml/badge.svg?branch=main)](https://github.com/ezrajrice/django_advanced_password_validation/actions/workflows/test.yaml)
[![Coverage Status](https://coveralls.io/repos/github/ezrajrice/django_advanced_password_validation/badge.svg?branch=main)](https://coveralls.io/github/ezrajrice/django_advanced_password_validation?branch=main)

This package works for both python 3.x and 2.x versions.
Extends Django password validation options to include minimum uppercase, minimum lowercase, minimum numerical, and minimum special characters. This was created in an attempt to keep up with industry standards for strong user passwords.

> **_NOTE:_** As of January 01, 2020 python 2.x has been deprecated and will no longer receive continued support. See [Python 2.x EOL](https://www.python.org/doc/sunset-python-2/) for more details.
This package works for python 3.6+.

### Prerequisites
## Prerequisites

Requires Django 1.11 or later.
Requires Django 2.2 or later.
You can install the latest version of Django via pip:

```
$ pip install django
```bash
pip install django
```

Alternatively, you can install a specific version of Django via pip:

```
$ pip install django=2.2
```bash
pip install django=3.2
```

> **_NOTE:_** See the [django-project](https://docs.djangoproject.com) documentation for information on non-deprecated Django versions.
### Installation
## Installation

#### Normal installation
### Normal installation

Install django-advanced_password_validation via pip:

```
$ pip install django-advanced_password_validation
```bash
pip install django-advanced_password_validation
```

#### Development installation
### Development installation

```
$ git clone https://github.com/ezrajrice/django-advanced_password_validation.git
$ cd django-advanced_password_validation
$ pip install --editable .
```bash
git clone https://github.com/ezrajrice/django-advanced_password_validation.git
cd django-advanced_password_validation
pip install --editable .
```

### Usage

The four optional validators must be configured in the settings.py file of your django project.
The optional validators must be configured in the settings.py file of your django project to be actively used in your project.

#### /my-cool-project/settings.py

Expand Down Expand Up @@ -101,12 +102,13 @@ Here is a list of the available options with their default values.

## Authors

* **Ezra Rice** - *Initial work* - [ezrajrice](https://github.com/ezrajrice)
* **Ezra Rice** - _Initial work_ - [ezrajrice](https://github.com/ezrajrice)

## License

This project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for details.

## Acknowledgments

* **Victor Semionov** - *Contributor* - [vsemionov](https://github.com/vsemionov)
* **Victor Semionov** - _Contributor_ - [vsemionov](https://github.com/vsemionov)
* **Mostafa Moradian** - _Contributor_ - [mostafa](https://github.com/mostafa)
71 changes: 28 additions & 43 deletions django_advanced_password_validation/advanced_password_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,14 +47,11 @@ def get_help_text(self):
"""
Get the help text for the validator.
"""
return (
_(
f"Your password must contain at least {self.min_digits} number.",
f"Your password must contain at least {self.min_digits} numbers.",
self.min_digits,
)
% {"min_digits": self.min_digits}
)
return _(
f"Your password must contain at least {self.min_digits} number.",
f"Your password must contain at least {self.min_digits} numbers.",
self.min_digits,
) % {"min_digits": self.min_digits}


class ContainsUppercaseValidator:
Expand Down Expand Up @@ -98,14 +95,11 @@ def get_help_text(self):
"""
Get the help text for the validator.
"""
return (
_(
f"Your password must contain at least {self.min_uppercase} uppercase character.",
f"Your password must contain at least {self.min_uppercase} uppercase characters.",
self.min_uppercase,
)
% {"min_uppercase": self.min_uppercase}
)
return _(
f"Your password must contain at least {self.min_uppercase} uppercase character.",
f"Your password must contain at least {self.min_uppercase} uppercase characters.",
self.min_uppercase,
) % {"min_uppercase": self.min_uppercase}


class ContainsLowercaseValidator:
Expand Down Expand Up @@ -149,14 +143,11 @@ def get_help_text(self):
"""
Get the help text for the validator.
"""
return (
_(
f"Your password must contain at least {self.min_lowercase} lowercase character.",
f"Your password must contain at least {self.min_lowercase} lowercase characters.",
self.min_lowercase,
)
% {"min_lowercase": self.min_lowercase}
)
return _(
f"Your password must contain at least {self.min_lowercase} lowercase character.",
f"Your password must contain at least {self.min_lowercase} lowercase characters.",
self.min_lowercase,
) % {"min_lowercase": self.min_lowercase}


class ContainsSpecialCharactersValidator:
Expand Down Expand Up @@ -201,14 +192,11 @@ def get_help_text(self):
"""
Get the help text for the validator.
"""
return (
_(
f"Your password must contain at least {self.min_characters} special character.",
f"Your password must contain at least {self.min_characters} special characters.",
self.min_characters,
)
% {"min_characters": self.min_characters}
)
return _(
f"Your password must contain at least {self.min_characters} special character.",
f"Your password must contain at least {self.min_characters} special characters.",
self.min_characters,
) % {"min_characters": self.min_characters}


class MaximumLengthValidator:
Expand Down Expand Up @@ -251,19 +239,16 @@ def get_help_text(self):
"""
Get the help text for the validator.
"""
return (
_(
f"Password must contain at maximum {self.max_length} character.",
f"Password must contain at maximum {self.max_length} characters.",
self.max_length,
)
% {"max_length": self.max_length}
)
return _(
f"Password must contain at maximum {self.max_length} character.",
f"Password must contain at maximum {self.max_length} characters.",
self.max_length,
) % {"max_length": self.max_length}


class MaxConsecutiveCharactersValidator:
"""
Validates whether the password contains max_consecutive consecutive characters.
Validates whether the password contains more than max_consecutive consecutive characters.
"""

def __init__(self, max_consecutive=3):
Expand All @@ -277,7 +262,7 @@ def __init__(self, max_consecutive=3):

def validate(self, password, user=None):
"""
Validates whether the password contains max_consecutive consecutive characters.
Validates whether the password contains more than max_consecutive consecutive characters.
Args:
password (str): The password to validate.
Expand All @@ -289,7 +274,7 @@ def validate(self, password, user=None):
"""
for c in password:
if password.count(c) >= self.max_consecutive:
check = c * self.max_consecutive
check = c * (self.max_consecutive + 1)
if check in password:
raise ValidationError(
gettext(
Expand Down

0 comments on commit 7069d43

Please sign in to comment.