Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions .flake8

This file was deleted.

12 changes: 8 additions & 4 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
repos:
- repo: https://github.com/pycqa/flake8
rev: '6.1.0' # pick a git hash / tag to point to
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version
rev: v0.15.10
hooks:
- id: flake8
exclude: 'migrations|docs|examples|vendor|venv|management|static'
# Run the linter
- id: ruff-check
args: [ --diff ]
# Run the formatter
- id: ruff-format
101 changes: 50 additions & 51 deletions apps/accounts/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@


class UserTypeFilter(admin.SimpleListFilter):
title = "User type"
parameter_name = "userprofile__type"
title = 'User type'
parameter_name = 'userprofile__type'

def lookups(self, request, model_admin):
return [
(USER_TYPE_ALIGNED_NETWORKS_BENEFICIARY, "Beneficiary"),
(USER_TYPE_DEV, "Developer"),
(USER_TYPE_ALIGNED_NETWORKS_BENEFICIARY, "Aligned Network Beneficiary")
(USER_TYPE_ALIGNED_NETWORKS_BENEFICIARY, 'Beneficiary'),
(USER_TYPE_DEV, 'Developer'),
(USER_TYPE_ALIGNED_NETWORKS_BENEFICIARY, 'Aligned Network Beneficiary'),
]

def queryset(self, request, queryset):
Expand All @@ -34,52 +34,51 @@ def queryset(self, request, queryset):


class ActiveAccountFilter(admin.SimpleListFilter):
title = "User activation status"
parameter_name = "status"
title = 'User activation status'
parameter_name = 'status'

def lookups(self, request, model_admin):
return [
("active", "Active"),
("inactive_all", "Inactive"),
("inactive_expired", "Inactive (expired activation key)")
]
return [('active', 'Active'), ('inactive_all', 'Inactive'), ('inactive_expired', 'Inactive (expired activation key)')]

def queryset(self, request, queryset):
if self.value() == "inactive_expired":
if self.value() == 'inactive_expired':
return queryset.filter(
is_active=False,
activationkey__key_status="expired",
activationkey__key_status='expired',
) | queryset.filter(
# Since the activation keys only reach "expired" status when they are
# used post-expiration, we need to check the "created" status as well
is_active=False,
activationkey__key_status="created",
activationkey__key_status='created',
activationkey__expires__lt=(datetime.today()),
)
elif self.value() == "inactive_all":
elif self.value() == 'inactive_all':
return queryset.filter(is_active=False)
elif self.value() == "active":
elif self.value() == 'active':
return queryset.filter(is_active=True)


class UserAdmin(DjangoUserAdmin):
list_display = (
"username",
"get_type",
"email",
"first_name",
"last_name",
"is_staff",
"is_superuser",
"is_active",
"date_joined",
'username',
'get_type',
'email',
'first_name',
'last_name',
'is_staff',
'is_superuser',
'is_active',
'date_joined',
)

list_filter = (UserTypeFilter, ActiveAccountFilter,)
list_filter = (
UserTypeFilter,
ActiveAccountFilter,
)

@admin.display(
description="Type",
ordering="userprofile__user_type",
description='Type',
ordering='userprofile__user_type',
)
def get_type(self, obj):
return obj.userprofile.user_type
Expand All @@ -92,43 +91,43 @@ def get_type(self, obj):
@admin.register(UserProfile)
class UserProfileAdmin(admin.ModelAdmin):
@admin.display(
description="Email Address",
ordering="user__email",
description='Email Address',
ordering='user__email',
)
def get_user_email(self, obj):
return obj.user.email

@admin.display(
description="Date Joined",
ordering="user__date_joined",
description='Date Joined',
ordering='user__date_joined',
)
def get_user_joined(self, obj):
return obj.user.date_joined

list_display = (
"user",
"name",
"user_type",
"organization_name",
"get_user_email",
"get_user_joined",
'user',
'name',
'user_type',
'organization_name',
'get_user_email',
'get_user_joined',
)
search_fields = (
"user__username",
"user__email",
"user__first_name",
"user__last_name",
"user_type",
"organization_name",
"user__date_joined",
'user__username',
'user__email',
'user__first_name',
'user__last_name',
'user_type',
'organization_name',
'user__date_joined',
)
raw_id_fields = ("user",)
raw_id_fields = ('user',)


@admin.register(UserIdentificationLabel)
class UserIdentificationLabelAdmin(admin.ModelAdmin):
model = UserIdentificationLabel
filter_horizontal = ("users",)
list_display = ("name", "slug", "weight")
list_filter = ("name", "slug")
ordering = ("weight",)
filter_horizontal = ('users',)
list_display = ('name', 'slug', 'weight')
list_filter = ('name', 'slug')
ordering = ('weight',)
2 changes: 1 addition & 1 deletion apps/accounts/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
class OAuth2AccountsConfig(AppConfig):
name = 'apps.accounts'
label = 'accounts'
verbose_name = "Accounts and Invites"
verbose_name = 'Accounts and Invites'
2 changes: 1 addition & 1 deletion apps/accounts/backends.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


class EmailAuthBackend(ModelBackend):
""" Authenticaton backend that uses email """
"""Authenticaton backend that uses email"""

def authenticate(self, request, username=None, password=None):
UserModel = get_user_model()
Expand Down
67 changes: 33 additions & 34 deletions apps/accounts/constants.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

# Enrollment and Identity Proofing. NIST SP 800-63-33 B
# Authenticator Assurance Level
AAL_CHOICES = (
Expand All @@ -9,15 +8,15 @@
('3', 'AAL3'),
)
ADDITION = 1
ACCT_ACTIVATED_MSG = '''Your account has been activated. You may now login.'''
ACCT_HAS_ISSUE_MSG = '''There may be an issue with your account.
Contact us at bluebuttonapi@cms.hhs.gov'''
ACCT_ACTIVATED_MSG = """Your account has been activated. You may now login."""
ACCT_HAS_ISSUE_MSG = """There may be an issue with your account.
Contact us at bluebuttonapi@cms.hhs.gov"""
ACCT_MAIL_LOGGER_NAME = 'hhs_server.apps.accounts.emails'
CHANGE = 2
DELETION = 3
DOT_EXT_SIGNAL_LOGGER_NAME = 'hhs_server.apps.dot_ext.signals'
# Set the default Encoding standard. typically 'utf-8'
ENCODED = "utf-8"
ENCODED = 'utf-8'

# Enrollment and Identity Proofing. NIST SP 800-63-3 A
# Identity assurance level
Expand All @@ -29,8 +28,8 @@
('3', 'IAL3'),
)

LINK_EXPIRED_MSG = '''The activation key is expired.
Contact us at bluebuttonapi@cms.hhs.gov for further assistance'''
LINK_EXPIRED_MSG = """The activation key is expired.
Contact us at bluebuttonapi@cms.hhs.gov for further assistance"""

# Enrollment and Identity Proofing. NIST SP 800-63-A
# Level of Assurance - Legacy/Deprecated See NIST SP 800-63-2
Expand Down Expand Up @@ -61,46 +60,46 @@

QUESTION_3_CHOICES = (
('1', 'What was the make of your first automobile?'),
('2', 'What was your maternal grandmother\'s maiden name?'),
('3', 'What was your paternal grandmother\'s maiden name?'),
('2', "What was your maternal grandmother's maiden name?"),
('3', "What was your paternal grandmother's maiden name?"),
)

# password rules used by validator: PasswordComplexityValidator,
# this is part of the validation logic, exercise caution when make changes
PASSWORD_RULES = [
{
"name": "min_length_digit",
"regex": "[0-9]",
"msg": "Password must contain at least {} digit(s).",
"help": "{} digit(s)",
"min_len": 1,
'name': 'min_length_digit',
'regex': '[0-9]',
'msg': 'Password must contain at least {} digit(s).',
'help': '{} digit(s)',
'min_len': 1,
},
{
"name": "min_length_alpha",
"regex": "[a-zA-Z]",
"msg": "Password must contain at least {} letter(s).",
"help": "{} letter(s)",
"min_len": 1,
'name': 'min_length_alpha',
'regex': '[a-zA-Z]',
'msg': 'Password must contain at least {} letter(s).',
'help': '{} letter(s)',
'min_len': 1,
},
{
"name": "min_length_special",
"regex": "[~!{}@#$%^&*_+\":;()'[]",
"msg": "Password must contain at least {} special character(s).",
"help": "{} special char(s)",
"min_len": 1,
'name': 'min_length_special',
'regex': '[~!{}@#$%^&*_+":;()\'[]',
'msg': 'Password must contain at least {} special character(s).',
'help': '{} special char(s)',
'min_len': 1,
},
{
"name": "min_length_lower",
"regex": "[a-z]",
"msg": "Password must contain at least {} lower case letter(s)",
"help": "{} lower case char(s)",
"min_len": 1,
'name': 'min_length_lower',
'regex': '[a-z]',
'msg': 'Password must contain at least {} lower case letter(s)',
'help': '{} lower case char(s)',
'min_len': 1,
},
{
"name": "min_length_upper",
"regex": "[A-Z]",
"msg": "Password must contain at least {} upper case letter(s).",
"help": "{} upper case char(s)",
"min_len": 1,
'name': 'min_length_upper',
'regex': '[A-Z]',
'msg': 'Password must contain at least {} upper case letter(s).',
'help': '{} upper case char(s)',
'min_len': 1,
},
]
38 changes: 17 additions & 21 deletions apps/accounts/emails.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,39 +13,35 @@


def random_secret(y=40):
return ''.join(random.choice('abcdefghijklmnopqrstuvwxyz'
'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
'0123456789') for x in range(y))
return ''.join(random.choice('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') for x in range(y))


@waffle_function_switch('outreach_email')
def send_activation_key_via_email(user, signup_key):
""" Send an email with activation key and welcome message. """
activation_link = '%s%s' % (get_hostname(),
reverse('activation_verify',
args=(signup_key,)))
mailer = Mailer(subject='Verify Your Blue Button 2.0 Developer Sandbox Account',
template_text='email/email-activate.txt',
template_html='email/email-activate.html',
to=[user.email, ],
context={"ACTIVATION_LINK": activation_link,
"ACTIVATION_KEY": signup_key,
"EXPIRATION": settings.SIGNUP_TIMEOUT_DAYS})
"""Send an email with activation key and welcome message."""
activation_link = '%s%s' % (get_hostname(), reverse('activation_verify', args=(signup_key,)))
mailer = Mailer(
subject='Verify Your Blue Button 2.0 Developer Sandbox Account',
template_text='email/email-activate.txt',
template_html='email/email-activate.html',
to=[
user.email,
],
context={'ACTIVATION_LINK': activation_link, 'ACTIVATION_KEY': signup_key, 'EXPIRATION': settings.SIGNUP_TIMEOUT_DAYS},
)
mailer.send()
logger.info("Activation link sent to {} ({})".format(user.username, user.email))
logger.info('Activation link sent to {} ({})'.format(user.username, user.email))


def get_hostname():
hostname = getattr(settings, 'HOSTNAME_URL', 'http://localhost:8000')

if "http://" in hostname.lower():
if 'http://' in hostname.lower():
pass
elif "https://" in hostname.lower():
elif 'https://' in hostname.lower():
pass
else:
logger.debug("HOSTNAME_URL [%s] "
"does not contain http or https prefix. "
"Issuer:%s" % (settings.HOSTNAME_URL, hostname))
logger.debug('HOSTNAME_URL [%s] does not contain http or https prefix. Issuer:%s' % (settings.HOSTNAME_URL, hostname))
# no http/https prefix in HOST_NAME_URL so we add it
hostname = "https://%s" % (hostname)
hostname = 'https://%s' % (hostname)
return hostname
Loading
Loading