Skip to content

Commit 86f878a

Browse files
authored
Merge pull request #17 from HackAssistant/review
Review
2 parents 4a23373 + 8fd70a0 commit 86f878a

30 files changed

+445
-117
lines changed

app/settings.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@
166166
'CLIENT_ID': os.environ.get('OPENID_CLIENT_ID', 'client_id'), # Required
167167
'TYPE': 'fake' if DEBUG else 'local', # Required
168168
'RESPONSE_TYPE': 'id_token', # Required
169-
'RENAME_ATTRIBUTES': {'sub': 'email'}, # Optional
169+
'RENAME_ATTRIBUTES': {'sub': 'email', 'groups': 'get_groups'}, # Optional
170170

171171
}
172172
JWT_SERVER = {

app/templates/base.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
{% include 'components/tabs.html' %}
5252
{% endif %}
5353
<div class="bg-{{ theme }} text-{% if theme == 'dark' %}white{% else %}black{% endif %}">
54-
<div style="padding: 20px">
54+
<div class="p-4">
5555
{% block content %}
5656
{% endblock %}
5757
</div>

application/apps.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ def auto_create_application_types(self):
1919
for name, obj in inspect.getmembers(sys.modules['application.forms']):
2020
if inspect.isclass(obj) and issubclass(obj, ApplicationForm) and obj != ApplicationForm:
2121
type_name = name.split('Form')[0]
22+
Group.objects.get_or_create(name=type_name)
2223
ApplicationTypeConfig.objects.get_or_create(name=type_name, defaults={
2324
'group_id': organizer_group.pk,
2425
'end_application_date': timezone.now() + timezone.timedelta(days=300)})

application/emails.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from django.urls import reverse
2+
3+
from app.emails import Email
4+
5+
6+
def send_email_to_blocked_admins(request, users, application, blocked_user):
7+
url = request.build_absolute_uri(reverse('change_status_application', kwargs={
8+
'uuid': application.get_uuid, 'status': application.STATUS_PENDING
9+
}))
10+
context = {
11+
'application': application,
12+
'blocked_user': blocked_user,
13+
'url': url,
14+
}
15+
Email(name='new_blocked', context=context, to=users, request=request).send()
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Generated by Django 4.0.4 on 2022-08-23 13:14
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('application', '0008_application_last_modified'),
10+
]
11+
12+
operations = [
13+
migrations.AlterModelOptions(
14+
name='application',
15+
options={'permissions': (('can_review_application', 'Can review application'), ('can_invite_application', 'Can invite application'), ('can_review_dubious_application', 'Can review dubious application'), ('can_review_blocked_application', 'Can review blocked application'))},
16+
),
17+
migrations.AlterField(
18+
model_name='application',
19+
name='status',
20+
field=models.CharField(choices=[('P', 'Under review'), ('R', 'Wait listed'), ('I', 'Invited'), ('LR', 'Last reminder'), ('C', 'Confirmed'), ('X', 'Cancelled'), ('A', 'Attended'), ('E', 'Expired'), ('D', 'Dubious'), ('IV', 'Invalid'), ('BL', 'Blocked'), ('NC', 'Needs change')], default='P', max_length=2),
21+
),
22+
]
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Generated by Django 4.0.4 on 2022-08-23 18:07
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('application', '0009_alter_application_options_alter_application_status'),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name='applicationtypeconfig',
15+
name='needs_confirmation',
16+
),
17+
migrations.RemoveField(
18+
model_name='applicationtypeconfig',
19+
name='review',
20+
),
21+
migrations.AddField(
22+
model_name='applicationtypeconfig',
23+
name='auto_blocklist',
24+
field=models.BooleanField(default=True, help_text='Applications pass test of blocklist table on apply'),
25+
),
26+
migrations.AddField(
27+
model_name='applicationtypeconfig',
28+
name='auto_confirm',
29+
field=models.BooleanField(default=False, help_text='Applications set on status confirmed by default'),
30+
),
31+
migrations.AddField(
32+
model_name='applicationtypeconfig',
33+
name='dubious',
34+
field=models.BooleanField(default=True, help_text='Dubious reviewing system'),
35+
),
36+
migrations.AddField(
37+
model_name='applicationtypeconfig',
38+
name='vote',
39+
field=models.BooleanField(default=True, help_text='Activate voting system'),
40+
),
41+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.0.4 on 2022-08-23 18:10
2+
3+
from django.db import migrations
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('application', '0010_remove_applicationtypeconfig_needs_confirmation_and_more'),
10+
]
11+
12+
operations = [
13+
migrations.RenameField(
14+
model_name='applicationtypeconfig',
15+
old_name='auto_blocklist',
16+
new_name='blocklist',
17+
),
18+
]
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Generated by Django 4.0.4 on 2022-08-23 18:35
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
('application', '0011_rename_auto_blocklist_applicationtypeconfig_blocklist'),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name='applicationtypeconfig',
15+
name='compatible_with_others',
16+
field=models.BooleanField(default=False, help_text='User can confirm in more than one type'),
17+
),
18+
]

application/models.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,17 @@ class ApplicationTypeConfig(models.Model):
3232
start_application_date = models.DateTimeField(default=timezone.now, null=True)
3333
end_application_date = models.DateTimeField(default=timezone.now, null=True)
3434
group = models.ForeignKey(Group, on_delete=models.DO_NOTHING)
35-
review = models.BooleanField(default=True)
36-
needs_confirmation = models.BooleanField(default=False)
35+
vote = models.BooleanField(default=True, help_text=_('Activate voting system'))
36+
dubious = models.BooleanField(default=True, help_text=_('Dubious reviewing system'))
37+
blocklist = models.BooleanField(default=True, help_text=_('Applications pass test of blocklist table on apply'))
38+
auto_confirm = models.BooleanField(default=False, help_text=_('Applications set on status confirmed by default'))
39+
compatible_with_others = models.BooleanField(default=False, help_text=_('User can confirm in more than one type'))
40+
41+
def vote_enabled(self):
42+
return self.vote and not self.auto_confirm
43+
44+
def dubious_enabled(self):
45+
return self.dubious and not self.auto_confirm
3746

3847
@property
3948
def get_token(self):
@@ -86,7 +95,7 @@ class Application(models.Model):
8695
STATUS_DUBIOUS = 'D'
8796
STATUS_NEEDS_CHANGE = 'NC'
8897
STATUS_INVALID = 'IV'
89-
STATUS_BLACKLISTED = 'BL'
98+
STATUS_BLOCKED = 'BL'
9099
STATUS = [
91100
(STATUS_PENDING, _('Under review')),
92101
(STATUS_REJECTED, _('Wait listed')),
@@ -98,7 +107,7 @@ class Application(models.Model):
98107
(STATUS_EXPIRED, _('Expired')),
99108
(STATUS_DUBIOUS, _('Dubious')),
100109
(STATUS_INVALID, _('Invalid')),
101-
(STATUS_BLACKLISTED, _('Blacklisted')),
110+
(STATUS_BLOCKED, _('Blocked')),
102111
(STATUS_NEEDS_CHANGE, _('Needs change')),
103112
]
104113
STATUS_COLORS = {
@@ -113,7 +122,7 @@ class Application(models.Model):
113122
STATUS_EXPIRED: 'danger',
114123
STATUS_INVALID: 'danger',
115124
STATUS_REJECTED: 'danger',
116-
STATUS_BLACKLISTED: 'danger',
125+
STATUS_BLOCKED: 'danger',
117126
}
118127
STATUS_DESCRIPTION = {
119128
STATUS_NEEDS_CHANGE: _('Your application might have some misleading information. '
@@ -127,7 +136,7 @@ class Application(models.Model):
127136
STATUS_EXPIRED: _('Your application have been expired. Please contact us quick if you want to come.'),
128137
STATUS_INVALID: _('Your application have been invalidated. It seems you cannot join us with this role.'),
129138
STATUS_REJECTED: _('We are so sorry, but our hack is full...'),
130-
STATUS_BLACKLISTED: _('User was blacklisted by your organization.'),
139+
STATUS_BLOCKED: _('User was blocked by your organization.'),
131140
STATUS_DUBIOUS: _('This application has something suspicious'),
132141
STATUS_ATTENDED: _('You have arrived at the event. Have fun!'),
133142
}
@@ -162,14 +171,15 @@ def form_data(self):
162171

163172
def set_status(self, status):
164173
self.status = status
174+
self.status_changed = True
165175
self.status_update_date = timezone.now()
166176

167177
@form_data.setter
168178
def form_data(self, data):
169179
self.data = json.dumps(data)
170180

171181
def __str__(self):
172-
return self.user.email
182+
return '%s: %s' % (self.type.name, self.user.email)
173183

174184
@property
175185
def get_uuid(self):
@@ -180,7 +190,7 @@ def get_public_status_display(self):
180190
return [y for (x, y) in self.STATUS if x == status][0]
181191

182192
def get_public_status(self):
183-
if self.status in [self.STATUS_BLACKLISTED, self.STATUS_DUBIOUS]:
193+
if self.status in [self.STATUS_BLOCKED, self.STATUS_DUBIOUS]:
184194
return self.STATUS_PENDING
185195
return self.status
186196

@@ -218,7 +228,10 @@ def can_edit(self):
218228
return self.status in [self.STATUS_PENDING, self.STATUS_NEEDS_CHANGE]
219229

220230
def save(self, *args, **kwargs):
221-
self.last_modified = timezone.now()
231+
if getattr(self, 'status_changed', False):
232+
self.last_modified = self.status_update_date
233+
else:
234+
self.last_modified = timezone.now()
222235
super().save(*args, **kwargs)
223236

224237
class Meta:
@@ -227,6 +240,7 @@ class Meta:
227240
('can_review_application', _('Can review application')),
228241
('can_invite_application', _('Can invite application')),
229242
('can_review_dubious_application', _('Can review dubious application')),
243+
('can_review_blocked_application', _('Can review blocked application')),
230244
)
231245

232246

application/templates/application_form.html

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
{% extends 'base.html' %}
22
{% load i18n %}
33
{% load static %}
4+
{% load perms %}
45
{% block subtitle %}{% if edit %}{% blocktrans %}{{ full_name }}'s {{ application_type }} application{% endblocktrans %}{% else %}{% blocktrans %}Applying as {{ application_type }}{% endblocktrans %}{% endif %}{% endblock %}
56
{% block content %}
6-
<div class="row">
7-
<div class="col-lg-2">
8-
{% if edit or public %}
9-
<a href="{% if request.user.is_organizer and edit %}{% url 'application_detail' application_form.instance.get_uuid %}{% else %}{% url 'apply_home' %}{% endif %}" class="btn btn-secondary" onclick="history.back()"><i class="bi bi-caret-left-fill"></i> {% trans 'Back' %}</a>
10-
{% endif %}
7+
{% if edit or public %}
8+
<div class="row justify-content-between mb-3">
9+
<div class="col-12 col-lg-2 d-grid d-md-block">
10+
<a href="{% if request.user.is_organizer and edit %}{% url 'application_detail' application_form.instance.get_uuid %}{% else %}{% url 'apply_home' %}{% endif %}" class="btn btn-secondary col-12"><i class="bi bi-caret-left-fill"></i> {% trans 'Back' %}</a>
11+
</div>
1112
</div>
12-
<h1 class="col-lg-8" style="text-align: center">{% if edit %}{% blocktrans %}{{ full_name }}'s {{ application_type }} application{% endblocktrans %}{% else %}{% blocktrans %}Applying as {{ application_type }}{% endblocktrans %}{% endif %}</h1>
13-
{% if edit %}
14-
<div class="list-group rounded-3" style="margin-bottom: 10px; padding: calc(var(--bs-gutter-x) * .5);">
15-
<div class="list-group-item list-group-item-{% if request.user.is_organizer %}{{ application_form.instance.get_status_color|default:theme }}{% else %}{{ application_form.instance.get_public_status_color|default:theme }}{% endif %}" style="text-align: center">
16-
<h3 class="mb-1">{% translate 'Status' %} {% if request.user.is_organizer %}{{ application_form.instance.get_status_display }}{% else %}{{ application_form.instance.get_public_status_display }}{% endif %}</h3>
17-
<p>
18-
{{ application_form.instance.get_public_status_description }}
19-
</p>
20-
</div>
13+
{% endif %}
14+
<h1 style="text-align: center">{% if edit %}{% blocktrans %}{{ full_name }}'s {{ application_type }} application{% endblocktrans %}{% else %}{% blocktrans %}Applying as {{ application_type }}{% endblocktrans %}{% endif %}</h1>
15+
{% if edit %}
16+
<div class="list-group rounded-3" style="margin-bottom: 10px; padding: calc(var(--bs-gutter-x) * .5);">
17+
<div class="list-group-item list-group-item-{% if request.user.is_organizer %}{{ application_form.instance.get_status_color|default:theme }}{% else %}{{ application_form.instance.get_public_status_color|default:theme }}{% endif %}" style="text-align: center">
18+
<h3 class="mb-1">{% translate 'Status' %} {% if request.user.is_organizer %}{{ application_form.instance.get_status_display }}{% else %}{{ application_form.instance.get_public_status_display }}{% endif %}</h3>
19+
<p>
20+
{{ application_form.instance.get_public_status_description }}
21+
</p>
2122
</div>
22-
{% endif %}
23-
</div>
23+
</div>
24+
{% endif %}
2425

2526

2627
<form method="post" enctype="multipart/form-data" class="mt-4">
@@ -30,15 +31,21 @@ <h3 class="mb-1">{% translate 'Status' %} {% if request.user.is_organizer %}{{ a
3031
{% include 'components/bootstrap5_form.html' with form=user_form only_form=True %}
3132
{% include 'components/bootstrap5_form.html' with form=application_form only_form=True %}
3233

33-
<div class="d-grid gap-4 d-flex justify-content-around">
34-
{% if edit %}
35-
<a href="{% url 'change_status_application' application_form.instance.get_uuid application_form.instance.STATUS_CANCELLED %}" onclick="return confirm('{% trans "Did you changed your mind? Are you sure you want to cancel this application?" %}')" class="btn btn-danger col-4">{% trans 'Remove' %}</a>
34+
<div class="row justify-content-around">
35+
{% if edit and not request.user.is_organizer %}
36+
<div class="col-12 col-lg-6 d-grid d-md-block">
37+
<a href="{% url 'change_status_application' application_form.instance.get_uuid application_form.instance.STATUS_CANCELLED %}" onclick="return confirm('{% trans "Did you changed your mind? Are you sure you want to cancel this application?" %}')" class="btn btn-danger col-12">{% trans 'Cancel my application' %}</a>
38+
</div>
3639
{% endif %}
3740
{% if not application_form.is_read_only %}
38-
<button type="submit" {% if edit and request.user.is_organizer %}onclick="return confirm_edit()"{% endif %} class="btn btn-primary col-4">{% if edit %}{% trans 'Save' %}{% else %}{% trans 'Apply' %}{% endif %}</button>
41+
<div class="col-12 col-lg-6 d-grid d-md-block mt-2 mt-lg-0">
42+
<button type="submit" {% if edit and request.user.is_organizer %}onclick="return confirm_edit()"{% endif %} class="btn btn-primary col-12">{% if edit %}{% trans 'Save' %}{% else %}{% trans 'Apply' %}{% endif %}</button>
43+
</div>
3944
{% endif %}
40-
{% if application_form.instance and application_form.instance.invited %}
41-
<a href="{% url 'change_status_application' application_form.instance.get_uuid application_form.instance.STATUS_CONFIRMED %}" onclick="return confirm('{% blocktrans %}Your {{ application_type }} invitation will be confirmed. This means that all your other applications will be cancelled. Are you sure you want to confirm this one?{% endblocktrans %}')" class="btn btn-primary col-4">{% trans 'Confirm invitation' %}</a>
45+
{% if application_form.instance and application_form.instance.invited and not request.user.is_organizer %}
46+
<div class="col-12 col-lg-6 d-grid d-md-block mt-2 mt-lg-0">
47+
<a href="{% url 'change_status_application' application_form.instance.get_uuid application_form.instance.STATUS_CONFIRMED %}" onclick="return confirm('{% blocktrans %}Your {{ application_type }} invitation will be confirmed. This means that all your other applications will be cancelled. Are you sure you want to confirm this one?{% endblocktrans %}')" class="btn btn-success col-12">{% trans 'Confirm invitation' %}</a>
48+
</div>
4249
{% endif %}
4350
</div>
4451
{% if request.user.is_organizer %}

0 commit comments

Comments
 (0)