Skip to content

Commit

Permalink
Merge pull request #372 from localcontexts/subscriptions
Browse files Browse the repository at this point in the history
Subscriptions to develop merge
  • Loading branch information
birbjam authored Oct 16, 2024
2 parents 09dc3ae + 9ab4290 commit c56017f
Show file tree
Hide file tree
Showing 226 changed files with 13,492 additions and 4,740 deletions.
3 changes: 2 additions & 1 deletion .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ exclude =
conftest.py
env
.env
researchers/tests.py
api/
bclabels/
communities/
Expand All @@ -20,6 +21,6 @@ exclude =
localcontexts/
projects/
tklabels/
researchers/
backups/
serviceproviders/

1 change: 1 addition & 0 deletions .github/workflows/run_testcases.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ jobs:
DB_USER: ${{ secrets.TEST_DB_USER }}
DB_PASS: ${{ secrets.TEST_DB_PASS }}
DB_HOST: ${{ secrets.TEST_DB_HOST }}
SF_VALID_USER_IDS: ${{ secrets.SF_VALID_USER_IDS }}
DB_PORT: ${{ secrets.TEST_DB_PORT }}
CSRF_COOKIE_DOMAIN: ${{ secrets.CSRF_COOKIE_DOMAIN }}
EMAIL_HOST: ${{ secrets.EMAIL_HOST }}
Expand Down
174 changes: 136 additions & 38 deletions accounts/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from django.contrib.sites.shortcuts import get_current_site
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from helpers.emails import send_password_reset_email
Expand All @@ -17,15 +18,15 @@ class RegistrationForm(UserCreationForm):

class Meta:
model = User
fields = ['username', 'email', 'password1', 'password2']
fields = ["username", "email", "password1", "password2"]
widgets = {
'email': forms.EmailInput(attrs={'class': 'w-100'}),
"email": forms.EmailInput(attrs={"class": "w-100"}),
}

def save(self, commit=True):
user = super(RegistrationForm, self).save(commit=False)
# Cleans the data so nothing harmful can get passed though the form
user.email = self.cleaned_data['email']
user.email = self.cleaned_data["email"]

# if we want to save
if commit:
Expand All @@ -38,29 +39,44 @@ class UserCreateProfileForm(forms.ModelForm):

class Meta:
model = User
fields = ['first_name', 'last_name']
fields = ["first_name", "last_name"]
widgets = {
"first_name": forms.TextInput(
attrs={
"class": "w-100",
"autocomplete": "off",
"required": True
}),
"last_name": forms.TextInput(
attrs={
"class": "w-100",
"autocomplete": "off"
})
}


# updating user instance (same as above but includes email)
class UserUpdateForm(forms.ModelForm):

class Meta:
model = User
fields = ['email', 'first_name', 'last_name']
fields = ["email", "first_name", "last_name"]
widgets = {
'email': forms.EmailInput(attrs={'class': 'w-100'}),
'first_name': forms.TextInput(attrs={'class': 'w-100'}),
'last_name': forms.TextInput(attrs={'class': 'w-100'}),
"email": forms.EmailInput(attrs={"class": "w-100"}),
"first_name": forms.TextInput(
attrs={"class": "w-100", "required": True}
),
"last_name": forms.TextInput(attrs={"class": "w-100"}),
}

def clean(self):
super(UserUpdateForm, self).clean()
email = self.cleaned_data.get('email')
email = self.cleaned_data.get("email")
user_id = self.instance.id if self.instance else None
if len(email) == 0:
self._errors['email'] = self.error_class(['Email Is Required'])
self._errors["email"] = self.error_class(["Email Is Required"])
elif User.objects.filter(email=email).exclude(id=user_id).exists():
self._errors['email'] = self.error_class(["Email already exists."])
self._errors["email"] = self.error_class(["Email already exists."])
return self.cleaned_data


Expand All @@ -70,10 +86,10 @@ class Meta:
model = Profile
fields = ['position', 'affiliation', 'city_town', 'state_province_region', 'country']
widgets = {
'position': forms.TextInput(attrs={'style': 'width: 100%;'}),
'affiliation': forms.TextInput(attrs={'class': 'w-100'}),
'city_town': forms.TextInput(attrs={'class': 'w-100'}),
'state_province_region': forms.TextInput(attrs={'class': 'w-100'}),
"position": forms.TextInput(attrs={"style": "width: 100%;"}),
"affiliation": forms.TextInput(attrs={"class": "w-100"}),
"city_town": forms.TextInput(attrs={"class": "w-100"}),
"state_province_region": forms.TextInput(attrs={"class": "w-100"}),
}


Expand All @@ -86,37 +102,33 @@ class Meta:
'state_province_region', 'country'
]
widgets = {
'position': forms.TextInput(attrs={'class': 'w-100'}),
'affiliation': forms.TextInput(attrs={'class': 'w-100'}),
'preferred_language': forms.TextInput(attrs={'class': 'w-100'}),
'languages_spoken': forms.TextInput(attrs={'class': 'w-100'}),
'city_town': forms.TextInput(attrs={'class': 'w-100'}),
'state_province_region': forms.TextInput(attrs={'class': 'w-100'}),
"position": forms.TextInput(attrs={"class": "w-100"}),
"affiliation": forms.TextInput(attrs={"class": "w-100"}),
"preferred_language": forms.TextInput(attrs={"class": "w-100"}),
"languages_spoken": forms.TextInput(attrs={"class": "w-100"}),
"city_town": forms.TextInput(attrs={"class": "w-100"}),
"state_province_region": forms.TextInput(attrs={"class": "w-100"}),
}


class ResendEmailActivationForm(forms.Form):
email = forms.EmailField(
label=_('Email'),
label=_("Email"),
required=True,
widget=forms.EmailInput(attrs={
'class': 'w-100',
'placeholder': 'email@domain.com'
})
)
}))


class SignUpInvitationForm(forms.ModelForm):

class Meta:
model = SignUpInvitation
fields = ['email', 'message']
fields = ["email", "message"]
widgets = {
'message': forms.Textarea(attrs={
'rows': 4,
'cols': 65
}),
'email': forms.EmailInput(attrs={'size': 65}),
"message": forms.Textarea(attrs={"rows": 4, "cols": 65}),
"email": forms.EmailInput(attrs={"size": 65}),
}


Expand All @@ -128,7 +140,7 @@ class ContactOrganizationForm(forms.Form):
})
)
email = forms.EmailField(
label=_('Email Address'),
label=_("Email Address"),
required=True,
widget=forms.EmailInput(attrs={
'class': 'w-100',
Expand Down Expand Up @@ -173,13 +185,99 @@ def save(
for user in self.get_users(email):
user_email = getattr(user, email_field_name)
context = {
'email': user_email,
'domain': domain,
'site_name': site_name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': token_generator.make_token(user),
'protocol': 'https' if use_https else 'http',
"email": user_email,
"domain": domain,
"site_name": site_name,
"uid": urlsafe_base64_encode(force_bytes(user.pk)),
"user": user,
"token": token_generator.make_token(user),
"protocol": "https" if use_https else "http",
**(extra_email_context or {}),
}
send_password_reset_email(request, context)


class SubscriptionForm(forms.Form):
ACCOUNT_TYPE_CHOICES = (
("", "Please select account type..."),
("institution_account", "Institution Account"),
("community_account", "Community Account"),
("researcher_account", "Researcher Account"),
("service_provider_account", "Service Provider Account"),
)
INQUIRY_TYPE_CHOICES = (
("", "Please select inquiry type..."),
("Subscription", "Subscription"),
("Membership", "Membership"),
("Service Provider", "Service Provider"),
("Subscription -- CC Notices Only", "CC Notices Only"),
("Something Else", "Something Else"),
("Not Sure", "Not Sure"),
)
first_name = forms.CharField(
widget=forms.TextInput(
attrs={
"class": "w-100",
"autocomplete": "off",
}
)
)
last_name = forms.CharField(
required=False,
widget=forms.TextInput(
attrs={
"class": "w-100",
"autocomplete": "off",
}
),
)
email = forms.EmailField(
widget=forms.EmailInput(
attrs={
"class": "w-100",
"autocomplete": "off",
}
)
)
account_type = forms.ChoiceField(
choices=ACCOUNT_TYPE_CHOICES,
widget=forms.Select(
attrs={
"class": "w-100",
"autocomplete": "off",
"placeholder": "Please select account type...",
}
),
)
inquiry_type = forms.ChoiceField(
choices=INQUIRY_TYPE_CHOICES,
widget=forms.Select(
attrs={
"class": "w-100",
"autocomplete": "off",
"placeholder": "Please select inquiry type...",
}
),
)
organization_name = forms.CharField(
required=False,
widget=forms.TextInput(
attrs={
"id": "organizationInput",
"class": "w-100",
"autocomplete": "off",
}
)
)

def clean_account_type(self):
account_type = self.cleaned_data.get("account_type")
if not account_type:
raise ValidationError("Please select an account type.")
return account_type

def clean_inquiry_type(self):
inquiry_type = self.cleaned_data.get("inquiry_type")
if not inquiry_type:
raise ValidationError("Please select an inquiry type.")
return inquiry_type
31 changes: 31 additions & 0 deletions accounts/migrations/0020_subscription.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Generated by Django 3.2 on 2024-03-11 12:57

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('communities', '0050_merge_0048_auto_20240123_0046_0049_alter_boundary_id'),
('institutions', '0031_alter_institution_id'),
('researchers', '0036_alter_researcher_id'),
('accounts', '0019_auto_20231220_1706'),
]

operations = [
migrations.CreateModel(
name='Subscription',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('users_count', models.IntegerField()),
('api_key_count', models.IntegerField()),
('project_count', models.IntegerField()),
('notification_count', models.IntegerField()),
('is_subscribed', models.BooleanField(default=False)),
('community', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subscribed_community', to='communities.community')),
('institution', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subscribed_institution', to='institutions.institution')),
('researcher', models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='subscribed_researcher', to='researchers.researcher')),
],
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 4.2.11 on 2024-03-22 11:16

from django.db import migrations, models
import django.utils.timezone


class Migration(migrations.Migration):
dependencies = [
("accounts", "0020_subscription"),
]

operations = [
migrations.AddField(
model_name="subscription",
name="date_last_updated",
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name="subscription",
name="end_date",
field=models.DateTimeField(blank=True, null=True),
),
migrations.AddField(
model_name="subscription",
name="start_date",
field=models.DateTimeField(default=django.utils.timezone.now),
),
]
19 changes: 19 additions & 0 deletions accounts/migrations/0022_remove_subscription_is_subscribed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Generated by Django 4.2.11 on 2024-03-22 14:33

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
(
"accounts",
"0021_subscription_date_last_updated_subscription_end_date_and_more",
),
]

operations = [
migrations.RemoveField(
model_name="subscription",
name="is_subscribed",
),
]
33 changes: 33 additions & 0 deletions accounts/migrations/0023_auto_20240408_1250.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2 on 2024-04-08 16:50

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('accounts', '0022_remove_subscription_is_subscribed'),
]

operations = [
migrations.AlterField(
model_name='subscription',
name='api_key_count',
field=models.IntegerField(help_text='For unlimited counts the value shoud be -1'),
),
migrations.AlterField(
model_name='subscription',
name='notification_count',
field=models.IntegerField(help_text='For unlimited counts the value shoud be -1'),
),
migrations.AlterField(
model_name='subscription',
name='project_count',
field=models.IntegerField(help_text='For unlimited counts the value shoud be -1'),
),
migrations.AlterField(
model_name='subscription',
name='users_count',
field=models.IntegerField(help_text='For unlimited counts the value shoud be -1'),
),
]
Loading

0 comments on commit c56017f

Please sign in to comment.