Skip to content

Commit

Permalink
Release 1.11.1
Browse files Browse the repository at this point in the history
  • Loading branch information
albertoleoncio committed Nov 7, 2024
2 parents 2a13de2 + 7e90b49 commit 2b855c7
Show file tree
Hide file tree
Showing 16 changed files with 520 additions and 217 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/django.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ jobs:
echo "SOCIAL_AUTH_MEDIAWIKI_KEY = 'key'" >> CapX/settings_local.py
echo "SOCIAL_AUTH_MEDIAWIKI_URL = 'https://localhost:8000/w/api.php'" >> CapX/settings_local.py
echo "SOCIAL_AUTH_MEDIAWIKI_SECRET = 'text'" >> CapX/settings_local.py
echo "EMAIL_HOST = 'localhost'" >> CapX/settings_local.py
echo "EMAIL_PORT = 25" >> CapX/settings_local.py
echo "SERVER_EMAIL = 'root@localhost'" >> CapX/settings_local.py
echo "ADMINS = []" >> CapX/settings_local.py
echo " CapX/tests/test_settings_local.py" >> .coveragerc
- name: Coverage report
run: |
Expand Down
2 changes: 1 addition & 1 deletion CapX/settings_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def configure_settings():
else:
debug = True
hosts = ['127.0.0.1']
callback = 'http://127.0.0.1:8000/oauth/complete/mediawiki/'
callback = 'http://127.0.0.1:8000/oauth/'
message = 'You are running in local mode, please make sure to set up the replica.my.cnf file to run in production mode'
email_host = 'localhost'
email_port = 25
Expand Down
2 changes: 1 addition & 1 deletion CapX/tests/test_settings_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def test_os_path_exists_false(self):
# Your assertions when os.path.exists returns False
self.assertFalse(os.path.exists('/some/path')) # This will be False
self.assertListEqual(settings['ALLOWED_HOSTS'], ['127.0.0.1'])
self.assertEqual(settings['SOCIAL_AUTH_MEDIAWIKI_CALLBACK'], 'http://127.0.0.1:8000/oauth/complete/mediawiki/')
self.assertEqual(settings['SOCIAL_AUTH_MEDIAWIKI_CALLBACK'], 'http://127.0.0.1:8000/oauth/')
self.assertEqual(settings['DATABASES']['default']['ENGINE'], 'django.db.backends.sqlite3')
self.assertEqual(settings['MESSAGE'], 'You are running in local mode, please make sure to set up the replica.my.cnf file to run in production mode')

Expand Down
18 changes: 5 additions & 13 deletions CapX/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf.urls.static import static
from rest_framework.routers import DefaultRouter
from skills.views import SkillViewSet, ListSkillViewSet, SkillByTypeViewSet
from skills.views import SkillViewSet, SkillByTypeViewSet
from users.views import (
ProfileViewSet, UsersViewSet, ListTerritoryViewSet,
ListLanguageViewSet, ListWikimediaProjectViewSet,
UsersBySkillViewSet, UsersByTagViewSet, TerritoryViewSet
ProfileViewSet, UsersViewSet, QuickListViewSet,
UsersBySkillViewSet, UsersByTagViewSet, TerritoryViewSet,
)
from bugs.views import BugViewSet, AttachmentViewSet
from orgs.views import OrganizationViewSet, ListOrganizationViewSet, OrganizationTypeViewSet
from orgs.views import OrganizationViewSet, OrganizationTypeViewSet
from events.views import EventViewSet, EventParticipantViewSet, EventOrganizationsViewSet
from drf_spectacular.views import SpectacularAPIView, SpectacularSwaggerView

Expand All @@ -46,14 +45,7 @@
router.register('events', EventViewSet)
router.register('events_participants', EventParticipantViewSet)
router.register('events_organizations', EventOrganizationsViewSet)

# Alternative version of views, read-only and only returns the __str__ with the id as the key
router.register('list_language', ListLanguageViewSet, basename='list_language')
router.register('list_affiliation', ListOrganizationViewSet, basename='list_affiliation')
router.register('list_skills', ListSkillViewSet, basename='list_skills')
router.register('list_territory', ListTerritoryViewSet, basename='list_territory')
router.register('list_wikimedia_project', ListWikimediaProjectViewSet, basename='list_wikimedia_project')

router.register('list', QuickListViewSet, basename='list')

urlpatterns = [
path('admin/', admin.site.urls),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.2.11 on 2024-10-24 19:25

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('bugs', '0002_alter_bug_bug_type_alter_bug_status'),
]

operations = [
migrations.AlterField(
model_name='bug',
name='bug_type',
field=models.CharField(blank=True, choices=[('error', 'Error'), ('new_feature', 'New Feature'), ('improvement', 'Improvement'), ('test_case', 'Test Case')], default='error', help_text='Type of the bug.', max_length=20),
),
migrations.AlterField(
model_name='bug',
name='description',
field=models.TextField(help_text='Description of the bug.', max_length=1000),
),
migrations.AlterField(
model_name='bug',
name='status',
field=models.CharField(blank=True, choices=[('to_do', 'To Do'), ('assigned', 'Assigned'), ('in_progress', 'In Progress'), ('under_review', 'Under Review'), ('done', 'Done')], default='to_do', help_text='Status of the bug (to be set by the staff).', max_length=20),
),
migrations.AlterField(
model_name='bug',
name='title',
field=models.CharField(help_text='Title of the bug.', max_length=200),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# Generated by Django 4.2.11 on 2024-10-24 19:25

from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('orgs', '0005_alter_organization_territory'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('skills', '0004_alter_skill_skill_type_and_more'),
('events', '0003_alter_eventorganizations_organization_and_more'),
]

operations = [
migrations.AlterField(
model_name='eventorganizations',
name='confirmed_organization',
field=models.BooleanField(default=False, help_text='Is the participation confirmed by the organization?'),
),
migrations.AlterField(
model_name='eventorganizations',
name='confirmed_organizer',
field=models.BooleanField(default=False, help_text='Is the participation confirmed by the organizer?'),
),
migrations.AlterField(
model_name='eventorganizations',
name='created_at',
field=models.DateTimeField(auto_now_add=True, help_text='Time when the participation was created.'),
),
migrations.AlterField(
model_name='eventorganizations',
name='event',
field=models.ForeignKey(help_text='Event where the organization is part of.', on_delete=django.db.models.deletion.CASCADE, to='events.events'),
),
migrations.AlterField(
model_name='eventorganizations',
name='organization',
field=models.ForeignKey(help_text='Organization which is part of the event.', on_delete=django.db.models.deletion.CASCADE, to='orgs.organization'),
),
migrations.AlterField(
model_name='eventorganizations',
name='role',
field=models.CharField(choices=[('organizer', 'Organizer'), ('sponsor', 'Sponsor'), ('supporter', 'Supporter')], help_text='Role of the organization.', max_length=20),
),
migrations.AlterField(
model_name='eventorganizations',
name='updated_at',
field=models.DateTimeField(auto_now=True, help_text='Time when the participation was last updated.'),
),
migrations.AlterField(
model_name='eventparticipant',
name='confirmed_organizer',
field=models.BooleanField(default=False, help_text='Is the participation confirmed by the organizer?'),
),
migrations.AlterField(
model_name='eventparticipant',
name='confirmed_participant',
field=models.BooleanField(default=False, help_text='Is the participation confirmed by the participant?'),
),
migrations.AlterField(
model_name='eventparticipant',
name='created_at',
field=models.DateTimeField(auto_now_add=True, help_text='Time when the participation was created.'),
),
migrations.AlterField(
model_name='eventparticipant',
name='event',
field=models.ForeignKey(help_text='Event of the participant.', on_delete=django.db.models.deletion.CASCADE, to='events.events'),
),
migrations.AlterField(
model_name='eventparticipant',
name='participant',
field=models.ForeignKey(help_text='Account of the participant.', on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='eventparticipant',
name='role',
field=models.CharField(choices=[('organizer', 'Organizer'), ('committee', 'Committee'), ('volunteer', 'Volunteer')], help_text='Role of the participant.', max_length=20),
),
migrations.AlterField(
model_name='eventparticipant',
name='updated_at',
field=models.DateTimeField(auto_now=True, help_text='Time when the participation was last updated.'),
),
migrations.AlterField(
model_name='events',
name='created_at',
field=models.DateTimeField(auto_now_add=True, help_text='Time when the event was created.', verbose_name='Created At'),
),
migrations.AlterField(
model_name='events',
name='creator',
field=models.ForeignKey(help_text='Creator of the event.', null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='events_created', to=settings.AUTH_USER_MODEL, verbose_name='Event Creator'),
),
migrations.AlterField(
model_name='events',
name='name',
field=models.CharField(help_text='Name of the event.', max_length=128, verbose_name='Event Name'),
),
migrations.AlterField(
model_name='events',
name='openstreetmap_id',
field=models.URLField(blank=True, help_text='OpenStreetMap ID of the event location.', validators=[django.core.validators.RegexValidator(message='Invalid OpenStreetMap ID format. The format should be https://www.openstreetmap.org/(way|node|relation)/12345', regex='^https://www\\.openstreetmap\\.org/(node|way|relation)/\\d+$')], verbose_name='OpenStreetMap ID'),
),
migrations.AlterField(
model_name='events',
name='organizations',
field=models.ManyToManyField(help_text='Organizations of the event.', through='events.EventOrganizations', to='orgs.organization', verbose_name='Event Organizations'),
),
migrations.AlterField(
model_name='events',
name='related_skills',
field=models.ManyToManyField(blank=True, help_text='Skills related to the event.', to='skills.skill', verbose_name='Related Skills'),
),
migrations.AlterField(
model_name='events',
name='team',
field=models.ManyToManyField(help_text='Team members of the event.', related_name='team_members', through='events.EventParticipant', to=settings.AUTH_USER_MODEL, verbose_name='Event Team'),
),
migrations.AlterField(
model_name='events',
name='time_begin',
field=models.DateTimeField(help_text='Start time of the event.', verbose_name='Start Time'),
),
migrations.AlterField(
model_name='events',
name='time_end',
field=models.DateTimeField(help_text='End time of the event.', verbose_name='End Time'),
),
migrations.AlterField(
model_name='events',
name='type_of_location',
field=models.CharField(choices=[('virtual', 'Virtual'), ('in_person', 'In Person'), ('hybrid', 'Hybrid')], help_text='Type of location of the event.', max_length=20, verbose_name='Type of Location'),
),
migrations.AlterField(
model_name='events',
name='updated_at',
field=models.DateTimeField(auto_now=True, help_text='Time when the event was last updated.', verbose_name='Updated At'),
),
migrations.AlterField(
model_name='events',
name='url',
field=models.URLField(blank=True, help_text='URL of the event.', verbose_name='Event URL'),
),
migrations.AlterField(
model_name='events',
name='wikidata_qid',
field=models.CharField(blank=True, help_text='Wikidata Qid of the event.', max_length=10, validators=[django.core.validators.RegexValidator(message='Invalid Wikidata Qid format. The format should be Q12345', regex='^Q[1-9]\\d*$')], verbose_name='Wikidata Qid'),
),
]
58 changes: 58 additions & 0 deletions orgs/migrations/0006_alter_organization_acronym_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Generated by Django 4.2.11 on 2024-10-24 19:25

from django.conf import settings
import django.core.validators
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('users', '0010_language_language_autonym'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('orgs', '0005_alter_organization_territory'),
]

operations = [
migrations.AlterField(
model_name='organization',
name='acronym',
field=models.CharField(help_text='The acronym of the organization (if any).', max_length=10, unique=True),
),
migrations.AlterField(
model_name='organization',
name='display_name',
field=models.CharField(help_text='The full name of the organization.', max_length=255),
),
migrations.AlterField(
model_name='organization',
name='home_project',
field=models.URLField(blank=True, help_text='The URL of the home project of the organization on Wikimedia (e.g. https://xx.wikimedia.org/).', null=True, validators=[django.core.validators.RegexValidator(message='Invalid URL format. The format should be https://xx.wikimedia.org/', regex='^https:\\/\\/[\\w-]+\\.wikimedia\\.org\\/$')]),
),
migrations.AlterField(
model_name='organization',
name='managers',
field=models.ManyToManyField(blank=True, help_text='ID of users who are managers of the organization on the platform.', related_name='managers', to=settings.AUTH_USER_MODEL),
),
migrations.AlterField(
model_name='organization',
name='meta_page',
field=models.URLField(blank=True, help_text='The URL of the organization page on Meta-Wiki.', null=True, validators=[django.core.validators.RegexValidator(message='Invalid URL format. The format should be https://meta.wikimedia.org/wiki/PageName', regex='^https:\\/\\/meta\\.wikimedia\\.org\\/wiki\\/.*?$')]),
),
migrations.AlterField(
model_name='organization',
name='profile_image',
field=models.URLField(blank=True, help_text='The URL of the organization profile image on Wikimedia Commons.', null=True, validators=[django.core.validators.RegexValidator(message='Invalid URL format. The format should be https://commons.wikimedia.org/wiki/File:filename.ext', regex='^https:\\/\\/commons\\.wikimedia\\.org\\/wiki\\/File:.*?\\.[\\w]+$')]),
),
migrations.AlterField(
model_name='organization',
name='territory',
field=models.ManyToManyField(blank=True, help_text='The territories where the organization is active.', related_name='territory', to='users.territory'),
),
migrations.AlterField(
model_name='organization',
name='type',
field=models.ForeignKey(help_text='The type of the organization as defined in the OrganizationType model.', null=True, on_delete=django.db.models.deletion.RESTRICT, to='orgs.organizationtype'),
),
]
64 changes: 0 additions & 64 deletions orgs/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,67 +187,3 @@ def test_delete_org(self):
self.user.is_staff = True
response = self.client.delete('/organizations/1/')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)

class ListOrganizationsViewSetTestCase(APITestCase):
def setUp(self):
self.user = CustomUser.objects.create_user(username='test', password=str(secrets.randbits(16)))
self.client = APIClient()
OrganizationType.objects.create(type_name='Type 1', type_code='TYPE1')
Territory.objects.create(territory_name='Territory 1')

def test_list_orgs_unauthenticated(self):
response = self.client.get('/list_affiliation/')
self.assertEqual(response.status_code, status.HTTP_401_UNAUTHORIZED)

def test_list_orgs_authenticated(self):
self.client.force_authenticate(self.user)
response = self.client.get('/list_affiliation/')
self.assertEqual(response.status_code, status.HTTP_200_OK)

organization = Organization.objects.create(
display_name='New Organization',
acronym='NO',
type=OrganizationType.objects.get(pk=1),
)
organization.territory.set([Territory.objects.get(pk=1)])
response = self.client.get('/list_affiliation/')
self.assertEqual(len(response.data), 1)
expected = {
1: 'New Organization (NO)',
}
self.assertEqual(response.data, expected)

Organization.objects.create(
display_name='New Organization 2',
acronym='NO2',
type=OrganizationType.objects.get(pk=1),
)
organization.territory.set([Territory.objects.get(pk=1)])
organization.managers.set([self.user])
response = self.client.get('/list_affiliation/')
self.assertEqual(len(response.data), 2)
expected = {
1: 'New Organization (NO)',
2: 'New Organization 2 (NO2)',
}
self.assertEqual(response.data, expected)

response = self.client.get('/list_affiliation/1/')
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)

def test_list_orgs_staff(self):
self.user.is_staff = True
self.client.force_authenticate(self.user)
response = self.client.get('/list_affiliation/')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 0)

org_data = {
'display_name': 'New Organization',
'acronym': 'NO',
'type': '1',
'territory': '1',
}
self.client.post('/organizations/', org_data)
response = self.client.get('/list_affiliation/')
self.assertEqual(len(response.data), 1)
Loading

0 comments on commit 2b855c7

Please sign in to comment.