diff --git a/account/tests.py b/account/tests.py
index 8e5b855f..fd073562 100644
--- a/account/tests.py
+++ b/account/tests.py
@@ -32,7 +32,7 @@ class PermissionDecoratorTest(APITestCase):
class UserLoginAPITest(APITestCase):
def setUp(self):
self.username = self.password = "test"
- self.user = self.create_user(username=self.username, password=self.password)
+ self.user = self.create_user(username=self.username, password=self.password, login=False)
self.login_url = self.reverse("user_login_api")
def _set_tfa(self):
@@ -152,7 +152,7 @@ class UserChangePasswordAPITest(CaptchaTest):
self.username = "test_user"
self.old_password = "testuserpassword"
self.new_password = "new_password"
- self.create_user(username=self.username, password=self.old_password)
+ self.create_user(username=self.username, password=self.old_password, login=False)
self.data = {"old_password": self.old_password, "new_password": self.new_password,
"captcha": self._set_captcha(self.client.session)}
@@ -178,7 +178,7 @@ class AdminUserTest(APITestCase):
def setUp(self):
self.user = self.create_super_admin(login=True)
self.username = self.password = "test"
- self.regular_user = self.create_user(username=self.username, password=self.password)
+ self.regular_user = self.create_user(username=self.username, password=self.password, login=False)
self.url = self.reverse("user_admin_api")
self.data = {"id": self.regular_user.id, "username": self.username, "real_name": "test_name",
"email": "test@qq.com", "admin_type": AdminType.REGULAR_USER,
diff --git a/account/urls/admin.py b/account/urls/admin.py
index 4af21f38..8f1b7f18 100644
--- a/account/urls/admin.py
+++ b/account/urls/admin.py
@@ -3,5 +3,5 @@ from django.conf.urls import url
from ..views.admin import UserAdminAPI
urlpatterns = [
- url(r'^user/$', UserAdminAPI.as_view(), name="user_admin_api"),
+ url(r'^user$', UserAdminAPI.as_view(), name="user_admin_api"),
]
diff --git a/account/urls/oj.py b/account/urls/oj.py
index b9fd5f5a..e7badd92 100644
--- a/account/urls/oj.py
+++ b/account/urls/oj.py
@@ -3,7 +3,7 @@ from django.conf.urls import url
from ..views.oj import UserLoginAPI, UserRegisterAPI, UserChangePasswordAPI
urlpatterns = [
- url(r'^login/$', UserLoginAPI.as_view(), name="user_login_api"),
- url(r'^register/$', UserRegisterAPI.as_view(), name="user_register_api"),
- url(r'^change_password/$', UserChangePasswordAPI.as_view(), name="user_change_password_api")
+ url(r'^login$', UserLoginAPI.as_view(), name="user_login_api"),
+ url(r'^register$', UserRegisterAPI.as_view(), name="user_register_api"),
+ url(r'^change_password$', UserChangePasswordAPI.as_view(), name="user_change_password_api")
]
diff --git a/announcement/tests.py b/announcement/tests.py
index 5de3179f..c2265974 100644
--- a/announcement/tests.py
+++ b/announcement/tests.py
@@ -3,7 +3,7 @@ from utils.api.tests import APITestCase, APIClient
class AnnouncementAdminTest(APITestCase):
def setUp(self):
- self.user = self.create_super_admin(login=True)
+ self.user = self.create_super_admin()
self.url = self.reverse("announcement_admin_api")
def test_announcement_list(self):
@@ -14,15 +14,15 @@ class AnnouncementAdminTest(APITestCase):
return self.client.post(self.url, data={"title": "test", "content": "test"})
def test_create_announcement(self):
- response = self.create_announcement()
- self.assertSuccess(response)
+ resp = self.create_announcement()
+ self.assertSuccess(resp)
def test_edit_announcement(self):
data = {"id": self.create_announcement().data["data"]["id"], "title": "ahaha", "content": "test content",
"visible": False}
- response = self.client.put(self.url, data=data)
- self.assertSuccess(response)
- resp_data = response.data["data"]
+ resp = self.client.put(self.url, data=data)
+ self.assertSuccess(resp)
+ resp_data = resp.data["data"]
self.assertEqual(resp_data["title"], "ahaha")
self.assertEqual(resp_data["content"], "test content")
self.assertEqual(resp_data["visible"], False)
diff --git a/announcement/urls/admin.py b/announcement/urls/admin.py
index 6ba28a67..c3e22033 100644
--- a/announcement/urls/admin.py
+++ b/announcement/urls/admin.py
@@ -3,5 +3,5 @@ from django.conf.urls import url
from ..views import AnnouncementAdminAPI
urlpatterns = [
- url(r'^$', AnnouncementAdminAPI.as_view(), name="announcement_admin_api"),
+ url(r'^announcement$', AnnouncementAdminAPI.as_view(), name="announcement_admin_api"),
]
diff --git a/conf/admin.py b/conf/admin.py
deleted file mode 100644
index 8c38f3f3..00000000
--- a/conf/admin.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
diff --git a/conf/migrations/0001_initial.py b/conf/migrations/0001_initial.py
new file mode 100644
index 00000000..44c393c4
--- /dev/null
+++ b/conf/migrations/0001_initial.py
@@ -0,0 +1,45 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.9.10 on 2016-11-19 05:18
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='SMTPConfig',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('server', models.CharField(max_length=128)),
+ ('port', models.IntegerField(default=25)),
+ ('email', models.CharField(max_length=128)),
+ ('password', models.CharField(max_length=128)),
+ ('tls', models.BooleanField()),
+ ],
+ options={
+ 'db_table': 'smtp_config',
+ },
+ ),
+ migrations.CreateModel(
+ name='WebsiteConfig',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('base_url', models.CharField(default='http://127.0.0.1', max_length=128)),
+ ('name', models.CharField(default='Online Judge', max_length=32)),
+ ('name_shortcut', models.CharField(default='oj', max_length=32)),
+ ('website_footer', models.TextField(default='Online Judge Footer')),
+ ('allow_register', models.BooleanField(default=True)),
+ ('submission_list_show_all', models.BooleanField(default=True)),
+ ],
+ options={
+ 'db_table': 'website_config',
+ },
+ ),
+ ]
diff --git a/conf/models.py b/conf/models.py
index 59f0dc6f..f04e759d 100644
--- a/conf/models.py
+++ b/conf/models.py
@@ -16,14 +16,14 @@ class SMTPConfig(models.Model):
class WebsiteConfig(models.Model):
- base_url = models.CharField(max_length=128, default=None)
+ base_url = models.CharField(max_length=128, default="http://127.0.0.1")
name = models.CharField(max_length=32, default="Online Judge")
name_shortcut = models.CharField(max_length=32, default="oj")
- website_footer = models.TextField(default="Online Judge")
+ website_footer = models.TextField(default="Online Judge Footer")
# allow register
allow_register = models.BooleanField(default=True)
# submission list show all user's submission
- submission_list_show_all = models.BooleanField(default=False)
+ submission_list_show_all = models.BooleanField(default=True)
class Meta:
db_table = "website_config"
diff --git a/conf/serializers.py b/conf/serializers.py
new file mode 100644
index 00000000..2d3ea975
--- /dev/null
+++ b/conf/serializers.py
@@ -0,0 +1,40 @@
+from utils.api import serializers
+
+from .models import SMTPConfig, WebsiteConfig
+
+
+class EditSMTPConfigSerializer(serializers.Serializer):
+ server = serializers.CharField(max_length=128)
+ port = serializers.IntegerField(default=25)
+ email = serializers.CharField(max_length=128)
+ password = serializers.CharField(max_length=128, required=False, allow_null=True, allow_blank=True)
+ tls = serializers.BooleanField()
+
+
+class CreateSMTPConfigSerializer(EditSMTPConfigSerializer):
+ password = serializers.CharField(max_length=128)
+
+
+class SMTPConfigSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = SMTPConfig
+ exclude = ["id", "password"]
+
+
+class TestSMTPConfigSerializer(serializers.Serializer):
+ email = serializers.EmailField()
+
+
+class CreateEditWebsiteConfigSerializer(serializers.Serializer):
+ base_url = serializers.CharField(max_length=128)
+ name = serializers.CharField(max_length=32)
+ name_shortcut = serializers.CharField(max_length=32)
+ website_footer = serializers.CharField(max_length=1024)
+ allow_register = serializers.BooleanField()
+ submission_list_show_all = serializers.BooleanField()
+
+
+class WebsiteConfigSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = WebsiteConfig
+ exclude = ["id"]
\ No newline at end of file
diff --git a/conf/tests.py b/conf/tests.py
index 7ce503c2..f0995c48 100644
--- a/conf/tests.py
+++ b/conf/tests.py
@@ -1,3 +1,75 @@
-from django.test import TestCase
+from utils.api.tests import APITestCase
-# Create your tests here.
+from .models import SMTPConfig, WebsiteConfig
+
+
+class SMTPConfigTest(APITestCase):
+ def setUp(self):
+ self.user = self.create_super_admin()
+ self.url = self.reverse("smtp_admin_api")
+ self.password = "testtest"
+
+ def test_create_smtp_config(self):
+ data = {"server": "smtp.test.com", "email": "test@test.com", "port": 465,
+ "tls": True, "password": self.password}
+ resp = self.client.post(self.url, data=data)
+ self.assertSuccess(resp)
+ self.assertTrue("password" not in resp.data)
+ return resp
+
+ def test_edit_without_password(self):
+ self.test_create_smtp_config()
+ data = {"server": "smtp1.test.com", "email": "test2@test.com", "port": 465,
+ "tls": True}
+ resp = self.client.put(self.url, data=data)
+ self.assertSuccess(resp)
+ smtp = SMTPConfig.objects.first()
+ self.assertEqual(smtp.password, self.password)
+ self.assertEqual(smtp.server, "smtp1.test.com")
+ self.assertEqual(smtp.email, "test2@test.com")
+
+ def test_edit_without_password1(self):
+ self.test_create_smtp_config()
+ data = {"server": "smtp.test.com", "email": "test@test.com", "port": 465,
+ "tls": True, "password": ""}
+ resp = self.client.put(self.url, data=data)
+ self.assertSuccess(resp)
+ self.assertEqual(SMTPConfig.objects.first().password, self.password)
+
+ def test_edit_with_password(self):
+ self.test_create_smtp_config()
+ data = {"server": "smtp1.test.com", "email": "test2@test.com", "port": 465,
+ "tls": True, "password": "newpassword"}
+ resp = self.client.put(self.url, data=data)
+ self.assertSuccess(resp)
+ smtp = SMTPConfig.objects.first()
+ self.assertEqual(smtp.password, "newpassword")
+ self.assertEqual(smtp.server, "smtp1.test.com")
+ self.assertEqual(smtp.email, "test2@test.com")
+
+
+class WebsiteConfigAPITest(APITestCase):
+ def test_create_website_config(self):
+ user = self.create_super_admin()
+ url = self.reverse("website_config_api")
+ data = {"base_url": "http://test.com", "name": "test name",
+ "name_shortcut": "test oj", "website_footer": "test",
+ "allow_register": True, "submission_list_show_all": False}
+ resp = self.client.post(url, data=data)
+ self.assertSuccess(resp)
+
+ def test_edit_website_config(self):
+ user = self.create_super_admin()
+ url = self.reverse("website_config_api")
+ data = {"base_url": "http://test.com", "name": "test name",
+ "name_shortcut": "test oj", "website_footer": "test",
+ "allow_register": True, "submission_list_show_all": False}
+ resp = self.client.post(url, data=data)
+ self.assertSuccess(resp)
+
+ def test_get_website_config(self):
+ # do not need to login
+ url = self.reverse("website_info_api")
+ resp = self.client.get(url)
+ self.assertSuccess(resp)
+ self.assertEqual(resp.data["data"]["name_shortcut"], "oj")
diff --git a/conf/urls/__init__.py b/conf/urls/__init__.py
new file mode 100644
index 00000000..e69de29b
diff --git a/conf/urls/admin.py b/conf/urls/admin.py
new file mode 100644
index 00000000..a6e8006a
--- /dev/null
+++ b/conf/urls/admin.py
@@ -0,0 +1,8 @@
+from django.conf.urls import url
+
+from ..views import WebsiteConfigAPI, SMTPAPI
+
+urlpatterns = [
+ url(r'^smtp$', SMTPAPI.as_view(), name="smtp_admin_api"),
+ url(r'^website$', WebsiteConfigAPI.as_view(), name="website_config_api"),
+]
diff --git a/conf/urls/oj.py b/conf/urls/oj.py
new file mode 100644
index 00000000..a6cee9af
--- /dev/null
+++ b/conf/urls/oj.py
@@ -0,0 +1,7 @@
+from django.conf.urls import url
+
+from ..views import WebsiteConfigAPI
+
+urlpatterns = [
+ url(r'^website$', WebsiteConfigAPI.as_view(), name="website_info_api"),
+]
diff --git a/conf/views.py b/conf/views.py
index 91ea44a2..59fce416 100644
--- a/conf/views.py
+++ b/conf/views.py
@@ -1,3 +1,65 @@
-from django.shortcuts import render
+from utils.api import APIView, validate_serializer
-# Create your views here.
+from account.decorators import super_admin_required
+
+from .models import SMTPConfig, WebsiteConfig
+from .serializers import (WebsiteConfigSerializer, CreateEditWebsiteConfigSerializer,
+ CreateSMTPConfigSerializer, EditSMTPConfigSerializer,
+ SMTPConfigSerializer, TestSMTPConfigSerializer)
+
+
+class SMTPAPI(APIView):
+ @super_admin_required
+ def get(self, request):
+ smtp = SMTPConfig.objects.first()
+ if not smtp:
+ return self.success(None)
+ return self.success(SMTPConfigSerializer(smtp).data)
+
+ @super_admin_required
+ @validate_serializer(CreateSMTPConfigSerializer)
+ def post(self, request):
+ SMTPConfig.objects.all().delete()
+ smtp = SMTPConfig.objects.create(**request.data)
+ return self.success(SMTPConfigSerializer(smtp).data)
+
+ @super_admin_required
+ @validate_serializer(EditSMTPConfigSerializer)
+ def put(self, request):
+ data = request.data
+ smtp = SMTPConfig.objects.first()
+ if not smtp:
+ return self.error("SMTP config is missing")
+ smtp.server = data["server"]
+ smtp.port = data["port"]
+ smtp.email = data["email"]
+ smtp.tls = data["tls"]
+ if data.get("password"):
+ smtp.password = data["password"]
+ smtp.save()
+ return self.success(SMTPConfigSerializer(smtp).data)
+
+
+class SMTPTestAPI(APIView):
+ @super_admin_required
+ @validate_serializer(TestSMTPConfigSerializer)
+ def post(self, request):
+ email = request.data["email"]
+ # todo: test send email
+ return self.success({"result": True})
+
+
+class WebsiteConfigAPI(APIView):
+ def get(self, request):
+ config = WebsiteConfig.objects.first()
+ if not config:
+ config = WebsiteConfig.objects.create()
+ return self.success(WebsiteConfigSerializer(config).data)
+
+ @validate_serializer(CreateEditWebsiteConfigSerializer)
+ @super_admin_required
+ def post(self, request):
+ data = request.data
+ WebsiteConfig.objects.all().delete()
+ config = WebsiteConfig.objects.create(**data)
+ return self.success(WebsiteConfigSerializer(config).data)
diff --git a/oj/settings.py b/oj/settings.py
index 697bc1fa..e25edd2a 100644
--- a/oj/settings.py
+++ b/oj/settings.py
@@ -41,6 +41,7 @@ INSTALLED_APPS = (
'account',
'announcement',
+ 'conf',
'utils',
'rest_framework',
diff --git a/oj/urls.py b/oj/urls.py
index 13351cdb..162e4392 100644
--- a/oj/urls.py
+++ b/oj/urls.py
@@ -3,6 +3,8 @@ from django.conf.urls import include, url
urlpatterns = [
url(r'^api/', include("account.urls.oj")),
- url(r'^api/admin/account/', include("account.urls.admin")),
- url(r'^api/admin/announcement/', include("announcement.urls.admin")),
+ url(r'^api/admin/', include("account.urls.admin")),
+ url(r'^api/admin/', include("announcement.urls.admin")),
+ url(r'^api/', include("conf.urls.oj")),
+ url(r'^api/admin/', include("conf.urls.admin"))
]
diff --git a/utils/api/tests.py b/utils/api/tests.py
index 44a03b0f..5cf83c68 100644
--- a/utils/api/tests.py
+++ b/utils/api/tests.py
@@ -9,7 +9,7 @@ from account.models import User, AdminType
class APITestCase(TestCase):
client_class = APIClient
- def create_user(self, username, password, admin_type=AdminType.REGULAR_USER, login=False):
+ def create_user(self, username, password, admin_type=AdminType.REGULAR_USER, login=True):
user = User.objects.create(username=username, admin_type=admin_type)
user.set_password(password)
user.save()
@@ -17,10 +17,10 @@ class APITestCase(TestCase):
self.client.login(username=username, password=password)
return user
- def create_admin(self, username="admin", password="admin", login=False):
+ def create_admin(self, username="admin", password="admin", login=True):
return self.create_user(username=username, password=password, admin_type=AdminType.ADMIN, login=login)
- def create_super_admin(self, username="root", password="root", login=False):
+ def create_super_admin(self, username="root", password="root", login=True):
return self.create_user(username=username, password=password, admin_type=AdminType.SUPER_ADMIN, login=login)
def reverse(self, url_name):