Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1fa1d0c019 | |||
| 4419f1cf2c | |||
| 6e74548206 | |||
| 5b9b4021d3 | |||
| 05279ae900 | |||
| 9b450f94a5 | |||
| 7ffce4e929 | |||
| ca8937d9f6 | |||
| 92f744f39c | |||
| 7c9a627d41 | |||
| a35b86af43 | |||
| 9651725bb3 | |||
| ac017bfb82 | |||
| f923511a72 | |||
| 78092ce734 | |||
| ae136aebae | |||
| 1eb5e7e10c | |||
| 74d0765eb2 | |||
| 1cab37dbcf | |||
| cf673c32c5 | |||
| a2e6a4754e | |||
| 6ccb1d01cf | |||
| cd708a469d | |||
| 831f15d0ff |
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 3.2.15 on 2022-08-06 14:33
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.utils.timezone
|
||||||
|
import webapp.utils
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0082_delete_baserole"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefeed",
|
||||||
|
name="base_autohide",
|
||||||
|
field=models.DateTimeField(default=webapp.utils.month_from_now),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefeed",
|
||||||
|
name="base_autohide_enabled",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefeed",
|
||||||
|
name="base_deleted",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basefeed",
|
||||||
|
name="base_publish_time",
|
||||||
|
field=models.DateTimeField(default=django.utils.timezone.now),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 18:12
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def copyOldDataToNewFields(apps, schema_editor):
|
||||||
|
Event = apps.get_model("webapp", "Event")
|
||||||
|
Feed = apps.get_model("webapp", "Feed")
|
||||||
|
for event in Event.objects.all():
|
||||||
|
event.base_deleted = event.deleted
|
||||||
|
event.save()
|
||||||
|
|
||||||
|
for post in Feed.objects.all():
|
||||||
|
post.base_deleted = post.deleted
|
||||||
|
post.base_publish_time = post.publish_time
|
||||||
|
post.base_autohide = post.autohide
|
||||||
|
post.base_autohide_enabled = post.autohide_enabled
|
||||||
|
post.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0083_auto_20220806_1733"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
copyOldDataToNewFields, reverse_code=migrations.RunPython.noop
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 18:28
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0084_auto_20220726_2112"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="event",
|
||||||
|
old_name="deleted",
|
||||||
|
new_name="old_deleted",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="feed",
|
||||||
|
old_name="autohide",
|
||||||
|
new_name="old_autohide",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="feed",
|
||||||
|
old_name="autohide_enabled",
|
||||||
|
new_name="old_autohide_enabled",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="feed",
|
||||||
|
old_name="deleted",
|
||||||
|
new_name="old_deleted",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="feed",
|
||||||
|
old_name="publish_time",
|
||||||
|
new_name="old_publish_time",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="base_autohide",
|
||||||
|
new_name="autohide",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="base_autohide_enabled",
|
||||||
|
new_name="autohide_enabled",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="base_deleted",
|
||||||
|
new_name="deleted",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="base_publish_time",
|
||||||
|
new_name="publish_time",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 18:29
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0085_auto_20220726_2128"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="event",
|
||||||
|
name="old_deleted",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="feed",
|
||||||
|
name="old_autohide",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="feed",
|
||||||
|
name="old_autohide_enabled",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="feed",
|
||||||
|
name="old_deleted",
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="feed",
|
||||||
|
name="old_publish_time",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 19:26
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0086_auto_20220726_2129"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameModel(
|
||||||
|
old_name="JobAd",
|
||||||
|
new_name="RemoveJobAd",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 19:49
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django.utils.timezone
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0087_auto_20220726_2226"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="JobAd",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"basefeed_ptr",
|
||||||
|
models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="webapp.BaseFeed",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("created_at", models.DateTimeField(default=django.utils.timezone.now)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"verbose_name": "JobAd",
|
||||||
|
"verbose_name_plural": "JobAds",
|
||||||
|
},
|
||||||
|
bases=("webapp.basefeed",),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 19:29
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
def copyOldDataToNewFields(apps, schema_editor):
|
||||||
|
Old = apps.get_model("webapp", "RemoveJobAd")
|
||||||
|
New = apps.get_model("webapp", "JobAd")
|
||||||
|
for jobAd in Old.objects.all():
|
||||||
|
New.objects.create(
|
||||||
|
id=jobAd.id,
|
||||||
|
title=jobAd.title,
|
||||||
|
tags=jobAd.tags,
|
||||||
|
visible=jobAd.visible,
|
||||||
|
deleted=jobAd.deleted,
|
||||||
|
publish_time=jobAd.publish_time,
|
||||||
|
autohide=jobAd.autohide_at,
|
||||||
|
autohide_enabled=jobAd.autohide_enabled,
|
||||||
|
description=jobAd.description,
|
||||||
|
content=jobAd.content,
|
||||||
|
created_at=jobAd.created_at,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0088_jobad"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
copyOldDataToNewFields, reverse_code=migrations.RunPython.noop
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 19:52
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0089_auto_20220726_2229"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.DeleteModel(
|
||||||
|
name="RemoveJobAd",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 20:11
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0090_delete_removejobad"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name="jobad",
|
||||||
|
name="created_at",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 21:16
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0091_remove_jobad_created_at"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="autohide_enabled",
|
||||||
|
new_name="autoUnpublish",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="visible",
|
||||||
|
new_name="isPublished",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="publish_time",
|
||||||
|
new_name="publishAt",
|
||||||
|
),
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name="basefeed",
|
||||||
|
old_name="autohide",
|
||||||
|
new_name="unpublishAt",
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 2.2.28 on 2022-07-26 21:17
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0092_auto_20220727_0016"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="basefeed",
|
||||||
|
name="isPublished",
|
||||||
|
field=models.BooleanField(default=False),
|
||||||
|
),
|
||||||
|
]
|
||||||
+77
-122
@@ -24,15 +24,15 @@ EMAIL_REGEX = r"(^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$)"
|
|||||||
class Tag(models.Model):
|
class Tag(models.Model):
|
||||||
"""Model for tag."""
|
"""Model for tag."""
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Tag")
|
|
||||||
verbose_name_plural = _("Tags")
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
slug = models.SlugField(unique=True)
|
slug = models.SlugField(unique=True)
|
||||||
name = models.CharField(max_length=127)
|
name = models.CharField(max_length=127)
|
||||||
icon = models.ImageField()
|
icon = models.ImageField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Tag")
|
||||||
|
verbose_name_plural = _("Tags")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Tag: {}").format(self.slug)
|
return _("Tag: {}").format(self.slug)
|
||||||
|
|
||||||
@@ -41,89 +41,85 @@ class BaseFeed(models.Model):
|
|||||||
"""Model containing something showing on some info feed."""
|
"""Model containing something showing on some info feed."""
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
tags = models.ManyToManyField(Tag, related_name="feeds", blank=True)
|
deleted = models.BooleanField(default=False)
|
||||||
visible = models.BooleanField(default=True)
|
|
||||||
title = models.CharField(max_length=255)
|
title = models.CharField(max_length=255)
|
||||||
description = models.CharField(max_length=255)
|
description = models.CharField(max_length=255)
|
||||||
content = models.TextField()
|
content = models.TextField()
|
||||||
image = models.ImageField(blank=True, null=True)
|
image = models.ImageField(blank=True, null=True)
|
||||||
|
tags = models.ManyToManyField(Tag, related_name="feeds", blank=True)
|
||||||
|
|
||||||
|
# Require explicit publishing from creator
|
||||||
|
isPublished = models.BooleanField(default=False)
|
||||||
|
# Automatically publish after this time, unless still in draft (!isPublished)
|
||||||
|
publishAt = models.DateTimeField(default=timezone.now)
|
||||||
|
autoUnpublish = models.BooleanField(default=False)
|
||||||
|
# Automatically unpublish after this if auto_unpublish==True
|
||||||
|
unpublishAt = models.DateTimeField(default=month_from_now)
|
||||||
|
|
||||||
|
webhookUrl = ""
|
||||||
|
hookType = ""
|
||||||
|
wasPublishedBefore = False
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(BaseFeed, self).__init__(*args, **kwargs)
|
||||||
|
self.wasPublishedBefore = self.isPublished
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
delete_str = _("Deleted: ") if self.deleted else ""
|
||||||
|
return _("{}{}: {}").format(delete_str, self._meta.verbose_name, self.title)
|
||||||
|
|
||||||
|
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
||||||
|
created = self.pk is None
|
||||||
|
super(BaseFeed, self).save(force_insert, force_update, *args, **kwargs)
|
||||||
|
|
||||||
|
if self.isPublished and (created or not self.wasPublishedBefore):
|
||||||
|
self.refresh_from_db() # Fetch so we can use primary key
|
||||||
|
url = f"{self.webhookUrl}/{self.pk}"
|
||||||
|
processHooks(
|
||||||
|
message=generateMessage(
|
||||||
|
f"Uusi {self._meta.verbose_name}", self.title, self.description, url
|
||||||
|
),
|
||||||
|
eventType=self.hookType,
|
||||||
|
)
|
||||||
|
self.wasPublishedBefore = self.isPublished
|
||||||
|
|
||||||
|
|
||||||
class Feed(BaseFeed):
|
class Feed(BaseFeed):
|
||||||
"""Model representing feed."""
|
"""Model representing feed."""
|
||||||
|
|
||||||
|
webhookUrl = f"https://{FRONTEND_URL}/feed"
|
||||||
|
hookType = "feed"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Feed")
|
verbose_name = _("Feed")
|
||||||
verbose_name_plural = _("Feeds")
|
verbose_name_plural = _("Feeds")
|
||||||
|
|
||||||
publish_time = models.DateTimeField(default=timezone.now)
|
|
||||||
autohide = models.DateTimeField(default=month_from_now)
|
|
||||||
autohide_enabled = models.BooleanField(default=False)
|
|
||||||
deleted = models.BooleanField(default=False)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
delete_str = _("Deleted: ") if self.deleted else ""
|
|
||||||
return _("{}Feed: {}").format(delete_str, self.title)
|
|
||||||
|
|
||||||
__previousVisible = False
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(Feed, self).__init__(*args, **kwargs)
|
|
||||||
self.__previousVisible = self.visible
|
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
|
||||||
created = self.pk is None
|
|
||||||
super(Feed, self).save(force_insert, force_update, *args, **kwargs)
|
|
||||||
|
|
||||||
if self.visible and (created or not self.__previousVisible):
|
|
||||||
self.refresh_from_db() # Fetch so we can use primary key
|
|
||||||
url = f"https://{FRONTEND_URL}/feed/{self.pk}"
|
|
||||||
processHooks(
|
|
||||||
message=generateMessage(
|
|
||||||
"Uusi uutinen", self.title, self.description, url
|
|
||||||
),
|
|
||||||
eventType="feed",
|
|
||||||
)
|
|
||||||
self.__previousVisible = self.visible
|
|
||||||
|
|
||||||
|
|
||||||
class Event(BaseFeed):
|
class Event(BaseFeed):
|
||||||
"""Model for event in guild calendar"""
|
"""Model for event in guild calendar"""
|
||||||
|
|
||||||
|
start_time = models.DateTimeField(default=timezone.now)
|
||||||
|
end_time = models.DateTimeField(default=timezone.now)
|
||||||
|
location = models.CharField(max_length=255, blank=True)
|
||||||
|
signupForm = models.ManyToManyField("SignupForm", blank=True, related_name="event")
|
||||||
|
|
||||||
|
webhookUrl = f"https://{FRONTEND_URL}/events"
|
||||||
|
hookType = "event"
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
verbose_name = _("Event")
|
verbose_name = _("Event")
|
||||||
verbose_name_plural = _("Events")
|
verbose_name_plural = _("Events")
|
||||||
|
|
||||||
start_time = models.DateTimeField(default=timezone.now)
|
|
||||||
end_time = models.DateTimeField(default=timezone.now)
|
|
||||||
signupForm = models.ManyToManyField("SignupForm", blank=True, related_name="event")
|
|
||||||
location = models.CharField(max_length=255, blank=True)
|
|
||||||
deleted = models.BooleanField(default=False)
|
|
||||||
|
|
||||||
def __str__(self):
|
class JobAd(BaseFeed):
|
||||||
delete_str = _("Deleted: ") if self.deleted else ""
|
"""Job advertisements shown on Corporate relations page"""
|
||||||
return _("{}Event: {}").format(delete_str, self.title)
|
|
||||||
|
|
||||||
__previousVisible = False
|
webhookUrl = f"https://{FRONTEND_URL}/jobads"
|
||||||
|
hookType = "jobad"
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
class Meta:
|
||||||
super(Event, self).__init__(*args, **kwargs)
|
verbose_name = _("JobAd")
|
||||||
self.__previousVisible = self.visible
|
verbose_name_plural = _("JobAds")
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
|
||||||
created = self.pk is None
|
|
||||||
super(Event, self).save(force_insert, force_update, *args, **kwargs)
|
|
||||||
|
|
||||||
if self.visible and (created or not self.__previousVisible):
|
|
||||||
self.refresh_from_db() # Fetch so we can use primary key
|
|
||||||
url = f"https://{FRONTEND_URL}/events/{self.pk}"
|
|
||||||
processHooks(
|
|
||||||
message=generateMessage(
|
|
||||||
"Uusi tapahtuma", self.title, self.description, url
|
|
||||||
),
|
|
||||||
eventType="event",
|
|
||||||
)
|
|
||||||
self.__previousVisible = self.visible
|
|
||||||
|
|
||||||
|
|
||||||
class TemplateQuestion(models.Model):
|
class TemplateQuestion(models.Model):
|
||||||
@@ -131,15 +127,15 @@ class TemplateQuestion(models.Model):
|
|||||||
Stores template questions for signup forms as JSON format. Used in signup form creation.
|
Stores template questions for signup forms as JSON format. Used in signup form creation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Template question")
|
|
||||||
verbose_name_plural = _("Template questions")
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
name = models.CharField(max_length=255)
|
name = models.CharField(max_length=255)
|
||||||
questions = JSONField()
|
questions = JSONField()
|
||||||
deleted = models.BooleanField(default=False)
|
deleted = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Template question")
|
||||||
|
verbose_name_plural = _("Template questions")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return _("Template questions: {}").format(self.name)
|
return _("Template questions: {}").format(self.name)
|
||||||
|
|
||||||
@@ -147,20 +143,20 @@ class TemplateQuestion(models.Model):
|
|||||||
class SignupForm(models.Model):
|
class SignupForm(models.Model):
|
||||||
"""Model for event signup form. Stores questions in JSON format."""
|
"""Model for event signup form. Stores questions in JSON format."""
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Signup form")
|
|
||||||
verbose_name_plural = _("Signup forms")
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
title = models.CharField(max_length=255)
|
title = models.CharField(max_length=255)
|
||||||
|
deleted = models.BooleanField(default=False)
|
||||||
|
visible = models.BooleanField(default=True)
|
||||||
start_time = models.DateTimeField(default=timezone.now)
|
start_time = models.DateTimeField(default=timezone.now)
|
||||||
end_time = models.DateTimeField(default=timezone.now)
|
end_time = models.DateTimeField(default=timezone.now)
|
||||||
questions = JSONField()
|
questions = JSONField()
|
||||||
schema = JSONField()
|
schema = JSONField()
|
||||||
visible = models.BooleanField(default=True)
|
|
||||||
quota = models.PositiveIntegerField(blank=True, null=True)
|
quota = models.PositiveIntegerField(blank=True, null=True)
|
||||||
email_content = models.TextField(blank=True)
|
email_content = models.TextField(blank=True)
|
||||||
deleted = models.BooleanField(default=False)
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Signup form")
|
||||||
|
verbose_name_plural = _("Signup forms")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
delete_str = _("Deleted: ") if self.deleted else ""
|
delete_str = _("Deleted: ") if self.deleted else ""
|
||||||
@@ -181,12 +177,9 @@ class Signup(models.Model):
|
|||||||
Actual signup into any SignupForm. Deletes are soft.
|
Actual signup into any SignupForm. Deletes are soft.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("Sign-up")
|
|
||||||
verbose_name_plural = _("Sign-ups")
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
id = models.AutoField(primary_key=True)
|
||||||
signupForm = models.ForeignKey("SignupForm", on_delete=models.CASCADE)
|
signupForm = models.ForeignKey("SignupForm", on_delete=models.CASCADE)
|
||||||
|
deleted = models.BooleanField(default=False)
|
||||||
time = models.DateTimeField(default=timezone.now)
|
time = models.DateTimeField(default=timezone.now)
|
||||||
answer = JSONField()
|
answer = JSONField()
|
||||||
# Answer we use in signupForm signups field. Frontend uses first questions answer as this value.
|
# Answer we use in signupForm signups field. Frontend uses first questions answer as this value.
|
||||||
@@ -195,7 +188,11 @@ class Signup(models.Model):
|
|||||||
email = models.EmailField(blank=True, null=True)
|
email = models.EmailField(blank=True, null=True)
|
||||||
# Random unique identifier. Used for signup editing by the user.
|
# Random unique identifier. Used for signup editing by the user.
|
||||||
uuid = models.UUIDField(default=uuid4, editable=False)
|
uuid = models.UUIDField(default=uuid4, editable=False)
|
||||||
deleted = models.BooleanField(default=False)
|
signupForm = models.ForeignKey("SignupForm", on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
verbose_name = _("Sign-up")
|
||||||
|
verbose_name_plural = _("Sign-ups")
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
delete_str = _("Deleted: ") if self.deleted else ""
|
delete_str = _("Deleted: ") if self.deleted else ""
|
||||||
@@ -222,49 +219,6 @@ def email_on_signup(sender, instance, created, **kwargs):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class JobAd(models.Model):
|
|
||||||
"""Job advertisements shown on Corporate relations page"""
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
verbose_name = _("JobAd")
|
|
||||||
verbose_name_plural = _("JobAds")
|
|
||||||
|
|
||||||
id = models.AutoField(primary_key=True)
|
|
||||||
title = models.CharField(max_length=255)
|
|
||||||
description = models.CharField(max_length=255)
|
|
||||||
content = models.TextField()
|
|
||||||
visible = models.BooleanField(default=True)
|
|
||||||
created_at = models.DateTimeField(default=timezone.now)
|
|
||||||
autohide_at = models.DateTimeField(default=month_from_now)
|
|
||||||
autohide_enabled = models.BooleanField(default=False)
|
|
||||||
deleted = models.BooleanField(default=False)
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
delete_str = _("Deleted: ") if self.deleted else ""
|
|
||||||
return f"{delete_str}{self.title}"
|
|
||||||
|
|
||||||
__previousVisible = False
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(JobAd, self).__init__(*args, **kwargs)
|
|
||||||
self.__previousVisible = self.visible
|
|
||||||
|
|
||||||
def save(self, force_insert=False, force_update=False, *args, **kwargs):
|
|
||||||
created = self.pk is None
|
|
||||||
super(JobAd, self).save(force_insert, force_update, *args, **kwargs)
|
|
||||||
|
|
||||||
if self.visible and (created or not self.__previousVisible):
|
|
||||||
self.refresh_from_db() # Fetch so we can use primary key
|
|
||||||
url = f"https://{FRONTEND_URL}/jobads/{self.pk}"
|
|
||||||
processHooks(
|
|
||||||
message=generateMessage(
|
|
||||||
"Uusi työpaikkailmoitus", self.title, self.description, url
|
|
||||||
),
|
|
||||||
eventType="jobad",
|
|
||||||
)
|
|
||||||
self.__previousVisible = self.visible
|
|
||||||
|
|
||||||
|
|
||||||
def generateMessage(heading: str, title: str, description: str, url: str):
|
def generateMessage(heading: str, title: str, description: str, url: str):
|
||||||
return render_to_string(
|
return render_to_string(
|
||||||
"webapp/tg_message.tpl",
|
"webapp/tg_message.tpl",
|
||||||
@@ -347,8 +301,9 @@ class TelegramHook(BaseWebhook):
|
|||||||
auditlog.register(Tag)
|
auditlog.register(Tag)
|
||||||
auditlog.register(Feed)
|
auditlog.register(Feed)
|
||||||
auditlog.register(Event)
|
auditlog.register(Event)
|
||||||
|
auditlog.register(JobAd)
|
||||||
|
auditlog.register(TemplateQuestion)
|
||||||
auditlog.register(SignupForm)
|
auditlog.register(SignupForm)
|
||||||
auditlog.register(Signup)
|
auditlog.register(Signup)
|
||||||
auditlog.register(JobAd)
|
|
||||||
auditlog.register(GenericWebhook)
|
auditlog.register(GenericWebhook)
|
||||||
auditlog.register(TelegramHook)
|
auditlog.register(TelegramHook)
|
||||||
|
|||||||
+72
-64
@@ -2,6 +2,14 @@ from rest_framework import serializers
|
|||||||
from webapp.models import *
|
from webapp.models import *
|
||||||
|
|
||||||
|
|
||||||
|
class SavedQuestionsSerializer(serializers.ModelSerializer):
|
||||||
|
questions = serializers.JSONField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = TemplateQuestion
|
||||||
|
fields = ("id", "name", "questions")
|
||||||
|
|
||||||
|
|
||||||
class SignupSerializer(serializers.ModelSerializer):
|
class SignupSerializer(serializers.ModelSerializer):
|
||||||
signupForm_id = serializers.PrimaryKeyRelatedField(
|
signupForm_id = serializers.PrimaryKeyRelatedField(
|
||||||
source="signupForm", queryset=SignupForm.objects.all()
|
source="signupForm", queryset=SignupForm.objects.all()
|
||||||
@@ -68,11 +76,54 @@ class SignupFormSerializer(serializers.ModelSerializer):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class EventSerializer(serializers.ModelSerializer):
|
class TagSerializer(serializers.ModelSerializer):
|
||||||
signupForm = SignupFormSerializer(
|
class Meta:
|
||||||
source="filtered_signup_forms",
|
model = Tag
|
||||||
|
fields = ("id", "slug", "name_fi", "name_en", "icon")
|
||||||
|
|
||||||
|
|
||||||
|
class FeedSerializer(serializers.ModelSerializer):
|
||||||
|
tagId = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=Tag.objects.all(),
|
||||||
many=True,
|
many=True,
|
||||||
read_only=True,
|
write_only=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Feed
|
||||||
|
fields = (
|
||||||
|
"id",
|
||||||
|
"title_fi",
|
||||||
|
"title_en",
|
||||||
|
"description_fi",
|
||||||
|
"description_en",
|
||||||
|
"content_fi",
|
||||||
|
"content_en",
|
||||||
|
"image",
|
||||||
|
"tags",
|
||||||
|
"tagId",
|
||||||
|
"isPublished",
|
||||||
|
"publishAt",
|
||||||
|
"autoUnpublish",
|
||||||
|
"unpublishAt",
|
||||||
|
)
|
||||||
|
read_only_fields = ["tags"]
|
||||||
|
depth = 1
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
tags_data = validated_data.pop("tagId")
|
||||||
|
feed = Feed.objects.create(**validated_data)
|
||||||
|
for tag in tags_data:
|
||||||
|
feed.tags.add(tag)
|
||||||
|
feed.save()
|
||||||
|
return feed
|
||||||
|
|
||||||
|
|
||||||
|
class EventSerializer(serializers.ModelSerializer):
|
||||||
|
tagId = serializers.PrimaryKeyRelatedField(
|
||||||
|
queryset=Tag.objects.all(),
|
||||||
|
many=True,
|
||||||
|
write_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
signup_id = serializers.PrimaryKeyRelatedField(
|
signup_id = serializers.PrimaryKeyRelatedField(
|
||||||
@@ -80,26 +131,30 @@ class EventSerializer(serializers.ModelSerializer):
|
|||||||
many=True,
|
many=True,
|
||||||
write_only=True,
|
write_only=True,
|
||||||
)
|
)
|
||||||
tag_id = serializers.PrimaryKeyRelatedField(
|
|
||||||
queryset=Tag.objects.all(),
|
signupForm = SignupFormSerializer(
|
||||||
|
source="filtered_signup_forms",
|
||||||
many=True,
|
many=True,
|
||||||
write_only=True,
|
read_only=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Event
|
model = Event
|
||||||
fields = (
|
fields = (
|
||||||
"id",
|
"id",
|
||||||
"tag_id",
|
|
||||||
"tags",
|
|
||||||
"visible",
|
|
||||||
"image",
|
|
||||||
"title_fi",
|
"title_fi",
|
||||||
"title_en",
|
"title_en",
|
||||||
"description_fi",
|
"description_fi",
|
||||||
"description_en",
|
"description_en",
|
||||||
"content_fi",
|
"content_fi",
|
||||||
"content_en",
|
"content_en",
|
||||||
|
"image",
|
||||||
|
"tags",
|
||||||
|
"tagId",
|
||||||
|
"isPublished",
|
||||||
|
"publishAt",
|
||||||
|
"autoUnpublish",
|
||||||
|
"unpublishAt",
|
||||||
"start_time",
|
"start_time",
|
||||||
"end_time",
|
"end_time",
|
||||||
"location_fi",
|
"location_fi",
|
||||||
@@ -112,7 +167,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
def create(self, validated_data):
|
def create(self, validated_data):
|
||||||
signupForms = validated_data.pop("signup_id", [])
|
signupForms = validated_data.pop("signup_id", [])
|
||||||
tags = validated_data.pop("tag_id")
|
tags = validated_data.pop("tagId")
|
||||||
event = Event.objects.create(**validated_data)
|
event = Event.objects.create(**validated_data)
|
||||||
for form in signupForms:
|
for form in signupForms:
|
||||||
event.signupForm.add(form)
|
event.signupForm.add(form)
|
||||||
@@ -123,7 +178,7 @@ class EventSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
def update(self, instance, validated_data):
|
def update(self, instance, validated_data):
|
||||||
signupForms = validated_data.pop("signup_id", [])
|
signupForms = validated_data.pop("signup_id", [])
|
||||||
tags = validated_data.pop("tag_id")
|
tags = validated_data.pop("tagId")
|
||||||
instance.signupForm.clear()
|
instance.signupForm.clear()
|
||||||
instance.tags.clear()
|
instance.tags.clear()
|
||||||
for form in signupForms:
|
for form in signupForms:
|
||||||
@@ -134,54 +189,6 @@ class EventSerializer(serializers.ModelSerializer):
|
|||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
|
||||||
class SavedQuestionsSerializer(serializers.ModelSerializer):
|
|
||||||
questions = serializers.JSONField()
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = TemplateQuestion
|
|
||||||
fields = ("id", "name", "questions")
|
|
||||||
|
|
||||||
|
|
||||||
class TagSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Tag
|
|
||||||
fields = ("id", "slug", "name_fi", "name_en", "icon")
|
|
||||||
|
|
||||||
|
|
||||||
class FeedSerializer(serializers.ModelSerializer):
|
|
||||||
tag_id = serializers.PrimaryKeyRelatedField(
|
|
||||||
many=True, source="tags", queryset=Tag.objects.all()
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Feed
|
|
||||||
fields = (
|
|
||||||
"id",
|
|
||||||
"tags",
|
|
||||||
"tag_id",
|
|
||||||
"visible",
|
|
||||||
"image",
|
|
||||||
"title_fi",
|
|
||||||
"title_en",
|
|
||||||
"description_fi",
|
|
||||||
"description_en",
|
|
||||||
"content_fi",
|
|
||||||
"content_en",
|
|
||||||
"publish_time",
|
|
||||||
"autohide",
|
|
||||||
"autohide_enabled",
|
|
||||||
)
|
|
||||||
depth = 1
|
|
||||||
|
|
||||||
def create(self, validated_data):
|
|
||||||
tags_data = validated_data.pop("tags")
|
|
||||||
feed = Feed.objects.create(**validated_data)
|
|
||||||
for tag in tags_data:
|
|
||||||
feed.tags.add(tag)
|
|
||||||
feed.save()
|
|
||||||
return feed
|
|
||||||
|
|
||||||
|
|
||||||
class JobAdSerializer(serializers.ModelSerializer):
|
class JobAdSerializer(serializers.ModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = JobAd
|
model = JobAd
|
||||||
@@ -193,7 +200,8 @@ class JobAdSerializer(serializers.ModelSerializer):
|
|||||||
"description_en",
|
"description_en",
|
||||||
"content_fi",
|
"content_fi",
|
||||||
"content_en",
|
"content_en",
|
||||||
"visible",
|
"isPublished",
|
||||||
"autohide_at",
|
"publishAt",
|
||||||
"autohide_enabled",
|
"autoUnpublish",
|
||||||
|
"unpublishAt",
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ from webapp.utils import month_from_now
|
|||||||
|
|
||||||
def createEventObject(
|
def createEventObject(
|
||||||
name="Testitapahtuma1",
|
name="Testitapahtuma1",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
start_time=timezone.now(),
|
start_time=timezone.now(),
|
||||||
end_time=month_from_now(),
|
end_time=month_from_now(),
|
||||||
tag_id=[],
|
tag_id=[],
|
||||||
@@ -14,7 +14,7 @@ def createEventObject(
|
|||||||
return Event.objects.create(
|
return Event.objects.create(
|
||||||
title_fi=name,
|
title_fi=name,
|
||||||
title_en=f"title_en {name}",
|
title_en=f"title_en {name}",
|
||||||
visible=visible,
|
isPublished=isPublished,
|
||||||
description_fi=f"desc_fi {name}",
|
description_fi=f"desc_fi {name}",
|
||||||
description_en=f"desc_en {name}",
|
description_en=f"desc_en {name}",
|
||||||
content_fi=f"content_fi {name}",
|
content_fi=f"content_fi {name}",
|
||||||
@@ -27,15 +27,15 @@ def createEventObject(
|
|||||||
|
|
||||||
def createEventJSON(
|
def createEventJSON(
|
||||||
name="POST1",
|
name="POST1",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
start_time=timezone.now(),
|
start_time=timezone.now(),
|
||||||
end_time=month_from_now(),
|
end_time=month_from_now(),
|
||||||
tag_id=[],
|
tagId=[],
|
||||||
signup_id=[],
|
signup_id=[],
|
||||||
):
|
):
|
||||||
return {
|
return {
|
||||||
"tag_id": tag_id,
|
"tagId": tagId,
|
||||||
"visible": visible,
|
"visible": isPublished,
|
||||||
"title_fi": f"title_fi {name}",
|
"title_fi": f"title_fi {name}",
|
||||||
"title_en": f"title_en {name}",
|
"title_en": f"title_en {name}",
|
||||||
"description_fi": f"desc_fi {name}",
|
"description_fi": f"desc_fi {name}",
|
||||||
|
|||||||
@@ -21,20 +21,20 @@ class EventTestCase(APITestCase):
|
|||||||
# Invisible but relevant
|
# Invisible but relevant
|
||||||
createEventObject(
|
createEventObject(
|
||||||
"Testitapahtuma2",
|
"Testitapahtuma2",
|
||||||
visible=False,
|
isPublished=False,
|
||||||
start_time=timezone.datetime(2018, 11, 9, 12, 0, 0),
|
start_time=timezone.datetime(2018, 11, 9, 12, 0, 0),
|
||||||
)
|
)
|
||||||
# Visible but unrelevant
|
# Visible but unrelevant
|
||||||
test2 = createEventObject(
|
test2 = createEventObject(
|
||||||
"Testitapahtuma3",
|
"Testitapahtuma3",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0),
|
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0),
|
||||||
end_time=timezone.datetime(2018, 12, 9, 13, 0, 0),
|
end_time=timezone.datetime(2018, 12, 9, 13, 0, 0),
|
||||||
)
|
)
|
||||||
# Visible and relevant
|
# Visible and relevant
|
||||||
createEventObject(
|
createEventObject(
|
||||||
"Testitapahtuma4",
|
"Testitapahtuma4",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0),
|
start_time=timezone.datetime(2018, 12, 9, 12, 0, 0),
|
||||||
)
|
)
|
||||||
# Add some tags
|
# Add some tags
|
||||||
@@ -122,7 +122,7 @@ class EventTestCase(APITestCase):
|
|||||||
self.client.force_authenticate(user=self.authClient)
|
self.client.force_authenticate(user=self.authClient)
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
URL,
|
URL,
|
||||||
createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]),
|
createEventJSON(tagId=[self.testTagId], signup_id=[self.signupFormId]),
|
||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -132,7 +132,7 @@ class EventTestCase(APITestCase):
|
|||||||
def test_post_event_unauth(self):
|
def test_post_event_unauth(self):
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
URL,
|
URL,
|
||||||
createEventJSON(tag_id=[self.testTagId], signup_id=[self.signupFormId]),
|
createEventJSON(tagId=[self.testTagId], signup_id=[self.signupFormId]),
|
||||||
format="json",
|
format="json",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ class FeedTestCase(APITestCase):
|
|||||||
|
|
||||||
feed = Feed.objects.create(
|
feed = Feed.objects.create(
|
||||||
title="TestFeed",
|
title="TestFeed",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
description="diidadaapa",
|
description="diidadaapa",
|
||||||
content="lorem ipsum",
|
content="lorem ipsum",
|
||||||
)
|
)
|
||||||
@@ -51,10 +51,10 @@ class FeedTestCase(APITestCase):
|
|||||||
tag2_id = tagBuilder("test2").id
|
tag2_id = tagBuilder("test2").id
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"tag_id": [tag1_id, tag2_id],
|
"tagId": [tag1_id, tag2_id],
|
||||||
"title_fi": "testtitle",
|
"title_fi": "testtitle",
|
||||||
"title_en": "testtitle",
|
"title_en": "testtitle",
|
||||||
"visible": "True",
|
"isPublished": "True",
|
||||||
"description_fi": "liirumlaarum",
|
"description_fi": "liirumlaarum",
|
||||||
"description_en": "liirumlaarum",
|
"description_en": "liirumlaarum",
|
||||||
"content_fi": "lorem ipsum",
|
"content_fi": "lorem ipsum",
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class JobAdTestCase(APITestCase):
|
|||||||
self.prefilled_jobad = JobAd.objects.create(
|
self.prefilled_jobad = JobAd.objects.create(
|
||||||
title_fi="ABB Test",
|
title_fi="ABB Test",
|
||||||
title_en="ABB Test",
|
title_en="ABB Test",
|
||||||
visible=True,
|
isPublished=True,
|
||||||
description_fi="desc",
|
description_fi="desc",
|
||||||
description_en="desc",
|
description_en="desc",
|
||||||
content_fi="lorem",
|
content_fi="lorem",
|
||||||
@@ -35,12 +35,12 @@ class JobAdTestCase(APITestCase):
|
|||||||
data = {
|
data = {
|
||||||
"title_fi": "testtitle",
|
"title_fi": "testtitle",
|
||||||
"title_en": "testtitle",
|
"title_en": "testtitle",
|
||||||
"visible": "True",
|
"isPublished": "True",
|
||||||
"description_fi": "liirumlaarum",
|
"description_fi": "liirumlaarum",
|
||||||
"description_en": "liirumlaarum",
|
"description_en": "liirumlaarum",
|
||||||
"content_fi": "lorem ipsum",
|
"content_fi": "lorem ipsum",
|
||||||
"content_en": "lorem ipsum",
|
"content_en": "lorem ipsum",
|
||||||
"autohide_enabled": "True",
|
"autoUnpublish": "True",
|
||||||
}
|
}
|
||||||
|
|
||||||
# Try post without authentication
|
# Try post without authentication
|
||||||
|
|||||||
+23
-23
@@ -4,28 +4,37 @@ from modeltranslation.translator import register, TranslationOptions
|
|||||||
from webapp.models import *
|
from webapp.models import *
|
||||||
|
|
||||||
|
|
||||||
@register(BaseFeed)
|
|
||||||
class BaseFeedTranslationOptions(TranslationOptions):
|
|
||||||
fields = ("title", "description", "content")
|
|
||||||
|
|
||||||
|
|
||||||
@register(Feed)
|
|
||||||
class FeedTranslationOptions(TranslationOptions):
|
|
||||||
fields = ()
|
|
||||||
|
|
||||||
|
|
||||||
@register(Tag)
|
@register(Tag)
|
||||||
class TagTranslationOptions(TranslationOptions):
|
class TagTranslationOptions(TranslationOptions):
|
||||||
fields = ("name",)
|
fields = ("name",)
|
||||||
|
|
||||||
|
|
||||||
|
@register(BaseFeed)
|
||||||
|
class BaseFeedTranslationOptions(TranslationOptions):
|
||||||
|
fields = (
|
||||||
|
"title",
|
||||||
|
"description",
|
||||||
|
"content",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register(Feed)
|
||||||
|
class FeedTranslationOptions(TranslationOptions):
|
||||||
|
fields = ()
|
||||||
|
|
||||||
|
|
||||||
@register(Event)
|
@register(Event)
|
||||||
class EventTranslationOptions(TranslationOptions):
|
class EventTranslationOptions(TranslationOptions):
|
||||||
fields = ("location",)
|
fields = ("location",)
|
||||||
|
|
||||||
|
|
||||||
@register(Signup)
|
@register(JobAd)
|
||||||
class SignupTranslationOptions(TranslationOptions):
|
class JobAdTranslationOptions(TranslationOptions):
|
||||||
|
fields = ()
|
||||||
|
|
||||||
|
|
||||||
|
@register(TemplateQuestion)
|
||||||
|
class TemplateQuestionTranslationOptions(TranslationOptions):
|
||||||
fields = ()
|
fields = ()
|
||||||
|
|
||||||
|
|
||||||
@@ -34,20 +43,11 @@ class SignupFormTranslationOptions(TranslationOptions):
|
|||||||
fields = ("title",)
|
fields = ("title",)
|
||||||
|
|
||||||
|
|
||||||
@register(TemplateQuestion)
|
@register(Signup)
|
||||||
class TemplateQuestionTranslationOptions(TranslationOptions):
|
class SignupTranslationOptions(TranslationOptions):
|
||||||
fields = ()
|
fields = ()
|
||||||
|
|
||||||
|
|
||||||
@register(JobAd)
|
|
||||||
class JobAdTranslationOptions(TranslationOptions):
|
|
||||||
fields = (
|
|
||||||
"title",
|
|
||||||
"description",
|
|
||||||
"content",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
@register(BaseWebhook)
|
@register(BaseWebhook)
|
||||||
class BaseWebhookOptions(TranslationOptions):
|
class BaseWebhookOptions(TranslationOptions):
|
||||||
fields = ()
|
fields = ()
|
||||||
|
|||||||
+101
-112
@@ -9,7 +9,7 @@ from django.http import HttpResponse, JsonResponse
|
|||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.views.decorators.http import require_http_methods
|
from django.views.decorators.http import require_http_methods
|
||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch, Q
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
@@ -46,23 +46,58 @@ class RootView(routers.APIRootView):
|
|||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
|
||||||
|
class TagsViewSet(ReadOnlyModelViewSet):
|
||||||
|
queryset = Tag.objects.all()
|
||||||
|
serializer_class = TagSerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
|
||||||
|
class FeedViewSet(ModelViewSet):
|
||||||
|
queryset = Feed.objects.filter(deleted=False)
|
||||||
|
serializer_class = FeedSerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
||||||
|
filter_fields = ("id", "tags", "isPublished")
|
||||||
|
search_fields = ("id", "tags", "isPublished")
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
# If admin page...
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
# Return all objects expect those that are (soft) deleted
|
||||||
|
# Soft deleted objects can be edited (and completely deleted) via Django admin (for superadmins)
|
||||||
|
return Feed.objects.filter(deleted=False).order_by("-publishAt")
|
||||||
|
|
||||||
|
now = timezone.now()
|
||||||
|
# Hide deleted and unpublished objects...
|
||||||
|
query = Q(deleted=False, isPublished=True, publishAt__lte=now)
|
||||||
|
# and hide objects that are automatically unpublished
|
||||||
|
hideQuery = Q(autoUnpublish=False) | Q(unpublishAt__gt=now)
|
||||||
|
query.add(hideQuery, Q.AND)
|
||||||
|
|
||||||
|
return Feed.objects.filter(query).order_by("-publishAt")
|
||||||
|
|
||||||
|
def destroy(self, request, pk=None, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
post = self.get_object()
|
||||||
|
post.deleted = True
|
||||||
|
post.save()
|
||||||
|
return JsonResponse(status=200, data={"message": "OK"})
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return JsonResponse(status=404, data={"error": f"Post {pk} not found"})
|
||||||
|
|
||||||
|
|
||||||
class EventViewSet(ModelViewSet):
|
class EventViewSet(ModelViewSet):
|
||||||
queryset = Event.objects.filter(deleted=False)
|
queryset = Event.objects.filter(deleted=False)
|
||||||
ordering = ["start_time"]
|
ordering = ["start_time"]
|
||||||
serializer_class = EventSerializer
|
serializer_class = EventSerializer
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
||||||
filter_fields = ("id", "tags", "visible", "signupForm")
|
filter_fields = ("id", "tags", "isPublished", "signupForm")
|
||||||
search_fields = ("id", "tags", "visible", "signupForm")
|
search_fields = ("id", "tags", "isPublished", "signupForm")
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
# TODO: For create and update, this returns old data in signupForm field (prefetched at the start of request)...
|
||||||
# TODO: For create and update, this return old data in signupForm field (prefetched)...
|
if self.request.user.is_authenticated:
|
||||||
if (
|
|
||||||
self.request.user.is_authenticated
|
|
||||||
or self.request.method == "POST"
|
|
||||||
or self.request.method == "PUT"
|
|
||||||
):
|
|
||||||
return Event.objects.filter(deleted=False).prefetch_related(
|
return Event.objects.filter(deleted=False).prefetch_related(
|
||||||
Prefetch(
|
Prefetch(
|
||||||
"signupForm",
|
"signupForm",
|
||||||
@@ -71,32 +106,26 @@ class EventViewSet(ModelViewSet):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
now = timezone.now()
|
||||||
|
# Hide deleted and unpublished objects...
|
||||||
|
query = Q(deleted=False, isPublished=True, publishAt__lte=now)
|
||||||
|
# and hide objects that are automatically unpublished
|
||||||
|
hideQuery = Q(autoUnpublish=False) | Q(unpublishAt__gt=timezone.now())
|
||||||
|
query.add(hideQuery, Q.AND)
|
||||||
|
|
||||||
since = self.request.query_params.get("since", None)
|
since = self.request.query_params.get("since", None)
|
||||||
if since:
|
if since:
|
||||||
return (
|
query.add(Q(end_time__gt=since), Q.AND)
|
||||||
Event.objects.filter(deleted=False, visible=True, end_time__gt=since)
|
else:
|
||||||
.order_by("start_time")
|
query.add(Q(end_time__gt=now), Q.AND)
|
||||||
.prefetch_related(
|
|
||||||
|
return Event.objects.filter(query).prefetch_related(
|
||||||
Prefetch(
|
Prefetch(
|
||||||
"signupForm",
|
"signupForm",
|
||||||
queryset=SignupForm.objects.filter(deleted=False, visible=True),
|
queryset=SignupForm.objects.filter(deleted=False, visible=True),
|
||||||
to_attr="filtered_signup_forms",
|
to_attr="filtered_signup_forms",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return (
|
|
||||||
Event.objects.filter(
|
|
||||||
deleted=False, visible=True, end_time__gt=timezone.now()
|
|
||||||
)
|
|
||||||
.order_by("start_time")
|
|
||||||
.prefetch_related(
|
|
||||||
Prefetch(
|
|
||||||
"signupForm",
|
|
||||||
queryset=SignupForm.objects.filter(deleted=False, visible=True),
|
|
||||||
to_attr="filtered_signup_forms",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
raw_image = request.data.get("image", None)
|
raw_image = request.data.get("image", None)
|
||||||
@@ -122,6 +151,48 @@ class EventViewSet(ModelViewSet):
|
|||||||
return JsonResponse(status=404, data={"error": f"Event {pk} not found"})
|
return JsonResponse(status=404, data={"error": f"Event {pk} not found"})
|
||||||
|
|
||||||
|
|
||||||
|
class JobAdViewSet(ModelViewSet):
|
||||||
|
queryset = JobAd.objects.filter(deleted=False)
|
||||||
|
serializer_class = JobAdSerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
if self.request.user.is_authenticated:
|
||||||
|
return JobAd.objects.filter(deleted=False).order_by("-publishAt")
|
||||||
|
|
||||||
|
now = timezone.now()
|
||||||
|
query = Q(deleted=False, isPublished=True, publishAt__lte=now)
|
||||||
|
hideQuery = Q(autoUnpublish=False) | Q(unpublishAt__gt=timezone.now())
|
||||||
|
query.add(hideQuery, Q.AND)
|
||||||
|
return JobAd.objects.filter(query).order_by("-publishAt")
|
||||||
|
|
||||||
|
def destroy(self, request, pk=None, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
ad = self.get_object()
|
||||||
|
ad.deleted = True
|
||||||
|
ad.save()
|
||||||
|
return JsonResponse(status=200, data={"message": "OK"})
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return JsonResponse(status=404, data={"error": f"Job Ad {pk} not found"})
|
||||||
|
|
||||||
|
|
||||||
|
class SavedQuestionsViewSet(ModelViewSet):
|
||||||
|
queryset = TemplateQuestion.objects.filter(deleted=False)
|
||||||
|
serializer_class = SavedQuestionsSerializer
|
||||||
|
permission_classes = [IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
|
def destroy(self, request, pk=None, *args, **kwargs):
|
||||||
|
try:
|
||||||
|
question = self.get_object()
|
||||||
|
question.deleted = True
|
||||||
|
question.save()
|
||||||
|
return JsonResponse(status=200, data={"message": "OK"})
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
return JsonResponse(
|
||||||
|
status=404, data={"error": f"Template question {pk} not found"}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class SignupFormViewSet(ModelViewSet):
|
class SignupFormViewSet(ModelViewSet):
|
||||||
queryset = SignupForm.objects.filter(deleted=False)
|
queryset = SignupForm.objects.filter(deleted=False)
|
||||||
ordering = ["start_time"]
|
ordering = ["start_time"]
|
||||||
@@ -264,99 +335,17 @@ class SignupViewSet(ModelViewSet):
|
|||||||
return JsonResponse(status=404, data={"error": f"Signup {pk} not found"})
|
return JsonResponse(status=404, data={"error": f"Signup {pk} not found"})
|
||||||
|
|
||||||
|
|
||||||
class SavedQuestionsViewSet(ModelViewSet):
|
|
||||||
queryset = TemplateQuestion.objects.filter(deleted=False)
|
|
||||||
serializer_class = SavedQuestionsSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
|
||||||
|
|
||||||
def destroy(self, request, pk=None, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
question = self.get_object()
|
|
||||||
question.deleted = True
|
|
||||||
question.save()
|
|
||||||
return JsonResponse(status=200, data={"message": "OK"})
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
return JsonResponse(
|
|
||||||
status=404, data={"error": f"Template question {pk} not found"}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class FeedViewSet(ModelViewSet):
|
|
||||||
queryset = Feed.objects.filter(deleted=False)
|
|
||||||
serializer_class = FeedSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
|
||||||
filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
|
|
||||||
filter_fields = ("id", "tags", "visible")
|
|
||||||
search_fields = ("id", "tags", "visible")
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if self.request.user.is_authenticated:
|
|
||||||
return Feed.objects.filter(deleted=False).order_by("-publish_time")
|
|
||||||
else:
|
|
||||||
objs = Feed.objects.filter(deleted=False, visible=True).order_by(
|
|
||||||
"-publish_time"
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: Bad filtering. Rewrite!
|
|
||||||
result_ids = []
|
|
||||||
for obj in objs:
|
|
||||||
if obj.autohide_enabled:
|
|
||||||
if obj.autohide > timezone.now():
|
|
||||||
result_ids.append(obj.id)
|
|
||||||
else:
|
|
||||||
result_ids.append(obj.id)
|
|
||||||
|
|
||||||
return Feed.objects.filter(id__in=result_ids).order_by("-publish_time")
|
|
||||||
|
|
||||||
def destroy(self, request, pk=None, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
post = self.get_object()
|
|
||||||
post.deleted = True
|
|
||||||
post.save()
|
|
||||||
return JsonResponse(status=200, data={"message": "OK"})
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
return JsonResponse(status=404, data={"error": f"Post {pk} not found"})
|
|
||||||
|
|
||||||
|
|
||||||
class TagsViewSet(ReadOnlyModelViewSet):
|
|
||||||
queryset = Tag.objects.all()
|
|
||||||
serializer_class = TagSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
|
||||||
|
|
||||||
|
|
||||||
class JobAdViewSet(ModelViewSet):
|
|
||||||
queryset = JobAd.objects.filter(deleted=False)
|
|
||||||
serializer_class = JobAdSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrReadOnly]
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
if self.request.user.is_authenticated:
|
|
||||||
return JobAd.objects.filter(deleted=False)
|
|
||||||
return JobAd.objects.filter(
|
|
||||||
deleted=False, visible=True, autohide_at__gt=timezone.now()
|
|
||||||
)
|
|
||||||
|
|
||||||
def destroy(self, request, pk=None, *args, **kwargs):
|
|
||||||
try:
|
|
||||||
ad = self.get_object()
|
|
||||||
ad.deleted = True
|
|
||||||
ad.save()
|
|
||||||
return JsonResponse(status=200, data={"message": "OK"})
|
|
||||||
except ObjectDoesNotExist:
|
|
||||||
return JsonResponse(status=404, data={"error": f"Job Ad {pk} not found"})
|
|
||||||
|
|
||||||
|
|
||||||
@require_http_methods(["GET"])
|
@require_http_methods(["GET"])
|
||||||
def nginx_jwt_resp(request, *args, **kwargs):
|
def nginx_jwt_resp(request, *args, **kwargs):
|
||||||
accessKey = request.COOKIES.get("jwt_access", None)
|
accessKey = request.COOKIES.get("jwt_access", None)
|
||||||
if not accessKey:
|
if not accessKey:
|
||||||
return HttpResponse("", status=401)
|
return HttpResponse("No valid access token", status=401)
|
||||||
try:
|
try:
|
||||||
# This also verifies the signature.
|
# This also verifies the signature.
|
||||||
# See https://pyjwt.readthedocs.io/en/latest/usage.html#reading-the-claimset-without-validation
|
# See https://pyjwt.readthedocs.io/en/latest/usage.html#reading-the-claimset-without-validation
|
||||||
token = decode(accessKey, settings.SECRET_KEY, algorithms=["HS256"])
|
token = decode(accessKey, settings.SECRET_KEY, algorithms=["HS256"])
|
||||||
except InvalidTokenError:
|
except InvalidTokenError:
|
||||||
return HttpResponse("", status=403)
|
return HttpResponse("Invalid access token", status=401)
|
||||||
user = "admin" if token.get("username", "") == "admin" else "moderator"
|
user = "admin" if token.get("username", "") == "admin" else "moderator"
|
||||||
resp = HttpResponse("", status=200)
|
resp = HttpResponse("", status=200)
|
||||||
resp["X-FBrowser-User"] = user
|
resp["X-FBrowser-User"] = user
|
||||||
|
|||||||
Reference in New Issue
Block a user