Skip to content

Commit

Permalink
Merge pull request #11 from kaplanPRO/0.5.0
Browse files Browse the repository at this point in the history
version 0.5.0
  • Loading branch information
csengor committed Jun 27, 2023
2 parents 1d8cf0c + 8bf22b4 commit 19a980b
Show file tree
Hide file tree
Showing 23 changed files with 456 additions and 36 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3.8
FROM python:3.11

ENV PYTHONUNBUFFERED=1

Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
author = 'Kaplan'

# The full version, including alpha/beta/rc tags
release = '0.4.0'
release = '0.5.0'


# -- General configuration ---------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion kaplancloud/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.4.0'
__version__ = '0.5.0'
34 changes: 29 additions & 5 deletions kaplancloud/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@
'django.contrib.staticfiles',

'storages',
'rest_framework',
'rest_framework.authtoken',
'kaplancloudaccounts',
'kaplancloudapi',
'kaplancloudapp'
]

Expand Down Expand Up @@ -132,8 +135,6 @@

STATIC_ROOT = BASE_DIR / 'staticfiles'

STATICFILES_STORAGE = os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage')

# Default primary key field type
# https://docs.djangoproject.com/en/3.2/ref/settings/#default-auto-field

Expand All @@ -143,11 +144,20 @@

PROJECTS_DIR = 'kaplancloudapp/projects'

DEFAULT_FILE_STORAGE = os.environ.get('FILE_STORAGE', 'django.core.files.storage.FileSystemStorage')
# https://docs.djangoproject.com/en/4.2/ref/settings/#std-setting-STORAGES

STORAGES = {
'default': {
'BACKEND': os.environ.get('FILE_STORAGE', 'django.core.files.storage.FileSystemStorage'),
},
'staticfiles': {
'BACKEND': os.environ.get('STATICFILES_STORAGE', 'django.contrib.staticfiles.storage.StaticFilesStorage'),
}
}

# This will set s3 parameters only if default file storage and/or staticfiles
# storage is set to S3Boto3Storage
if DEFAULT_FILE_STORAGE == 'storages.backends.s3boto3.S3Boto3Storage' or STATICFILES_STORAGE == 'storages.backends.s3boto3.S3StaticStorage':
if STORAGES['default']['BACKEND'] == 'storages.backends.s3boto3.S3Boto3Storage' or STORAGES['staticfiles']['BACKEND'] == 'storages.backends.s3boto3.S3StaticStorage':
AWS_DEFAULT_ACL = os.environ.get('S3_DEFAULT_ACL')
AWS_S3_ACCESS_KEY_ID = os.environ.get('S3_ACCESS_KEY_ID')
AWS_S3_SECRET_ACCESS_KEY = os.environ.get('S3_SECRET_ACCESS_KEY')
Expand All @@ -163,7 +173,7 @@

# This will set GCP Cloud Storage parameters only if the default file storage
# and/or staticfiles storage is set to GoogleCloudStorage
elif 'storages.backends.gcloud.GoogleCloudStorage' in (DEFAULT_FILE_STORAGE, STATICFILES_STORAGE):
elif 'storages.backends.gcloud.GoogleCloudStorage' in (STORAGES['default']['BACKEND'], STORAGES['staticfiles']['BACKEND']):
# Environmental variable GOOGLE_APPLICATION_CREDENTIALS is to be set to the
# path of the key file
GS_BUCKET_NAME = os.environ.get('GS_PUBLIC_BUCKET_NAME')
Expand All @@ -173,3 +183,17 @@
GS_LOCATION = os.environ.get('GS_PUBLIC_BUCKET_LOCATION', 'static')
GS_PRIVATE_BUCKET_LOCATION = os.environ.get('GS_PRIVATE_BUCKET_LOCATION', '')
GS_QUERYSTRING_AUTH = os.environ.get('GS_QUERYSTRING_AUTH', 'False') == 'True'

# https://www.django-rest-framework.org/api-guide/permissions/
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAdminUser'
],
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.SessionAuthentication'
],
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 100
}
1 change: 1 addition & 0 deletions kaplancloud/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,6 @@
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('kaplancloudaccounts.urls')),
path('api/', include('kaplancloudapi.urls')),
path('', include('kaplancloudapp.urls')),
]
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</div>
</div>
<footer>
<p>v0.4.0</p>
<p>v0.5.0</p>
</footer>
</main>
{% endblock %}
2 changes: 1 addition & 1 deletion kaplancloudaccounts/templates/accounts/login.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
</div>
</div>
<footer>
<p>v0.4.0</p>
<p>v0.5.0</p>
</footer>
</main>
{% endblock %}
2 changes: 1 addition & 1 deletion kaplancloudaccounts/templates/accounts/register.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
</div>
</div>
<footer>
<p>v0.4.0</p>
<p>v0.5.0</p>
</footer>
</main>
{% endblock %}
Empty file added kaplancloudapi/__init__.py
Empty file.
7 changes: 7 additions & 0 deletions kaplancloudapi/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from django.contrib import admin

from kaplancloudapi.models import ProjectWebHook, ProjectFileWebHook

admin.site.register(ProjectWebHook)

admin.site.register(ProjectFileWebHook)
11 changes: 11 additions & 0 deletions kaplancloudapi/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from django.apps import AppConfig


class KaplancloudapiConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'kaplancloudapi'

def ready(self):
# Import the signal instances and connect them
# from myapp.signals import my_signal
import kaplancloudapi.signals
40 changes: 40 additions & 0 deletions kaplancloudapi/migrations/0001_initial.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 4.2.2 on 2023-06-25 11:29

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


class Migration(migrations.Migration):

initial = True

dependencies = [
('kaplancloudapp', '0016_add_uuid_fields'),
]

operations = [
migrations.CreateModel(
name='ProjectWebHook',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('target', models.URLField()),
('header', models.JSONField()),
('project', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='kaplancloudapp.project')),
],
options={
'abstract': False,
},
),
migrations.CreateModel(
name='ProjectFileWebHook',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('target', models.URLField()),
('header', models.JSONField()),
('project_file', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='kaplancloudapp.projectfile')),
],
options={
'abstract': False,
},
),
]
Empty file.
33 changes: 33 additions & 0 deletions kaplancloudapi/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from django.db import models

import json
import logging
import requests


class WebHook(models.Model):
target = models.URLField()
header = models.JSONField()

class Meta:
abstract = True

def fire_hook(self, body: dict):
try:
requests.post(self.target, data=json.dumps(body), headers=self.header)
except Exception as e:
logging.error(e)


class ProjectWebHook(WebHook):
project = models.ForeignKey('kaplancloudapp.Project', on_delete=models.CASCADE)

def fire_hook(self):
return super().fire_hook({'id': self.project.id, 'status': self.project.get_status()})


class ProjectFileWebHook(WebHook):
project_file = models.ForeignKey('kaplancloudapp.ProjectFile', on_delete=models.CASCADE)

def fire_hook(self):
return super().fire_hook({'id': self.project_file.id, 'status': self.project_file.get_status()})
105 changes: 105 additions & 0 deletions kaplancloudapi/serializers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
from django.contrib.auth.models import Group, User
from django.contrib.auth.hashers import make_password

from rest_framework import serializers

from kaplancloudapi.models import ProjectWebHook, ProjectFileWebHook

from kaplancloudapp.models import (
Client, LanguageProfile, Project, ProjectFile,
ProjectReferenceFile, TranslationMemory, file_statuses, project_statuses
)


class ClientSerializer(serializers.ModelSerializer):
class Meta:
model = Client
fields = ('id', 'name', 'team')


class GroupSerializer(serializers.ModelSerializer):
id = serializers.ReadOnlyField()

class Meta:
model = Group
fields = '__all__'


class LanguageProfileSerializer(serializers.ModelSerializer):
is_ltr = serializers.BooleanField(default=True, initial=True)

class Meta:
model = LanguageProfile
fields = ('id', 'name', 'iso_code', 'is_ltr')

def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user

return super().create(validated_data)


class ProjectSerializer(serializers.ModelSerializer):
status = serializers.ChoiceField(choices=project_statuses, default=0, initial=0)

class Meta:
model = Project
fields = (
'id', 'uuid', 'name', 'source_language', 'target_language', 'client',
'managed_by', 'status', 'translationmemories', 'due_by', '_are_all_files_submitted',
)

def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user

return super().create(validated_data)


class ProjectWebHookSerializer(serializers.ModelSerializer):
class Meta:
model = ProjectWebHook
fields = '__all__'


class ProjectFileSerializer(serializers.ModelSerializer):
status = serializers.ChoiceField(choices=file_statuses, default=0, initial=0)

class Meta:
model = ProjectFile
exclude = ('bilingual_file', 'source_language', 'target_language')


class ProjectFileWebHookSerializer(serializers.ModelSerializer):
class Meta:
model = ProjectFileWebHook
fields = '__all__'


class ProjectReferenceFileSerializer(serializers.ModelSerializer):
class Meta:
model = ProjectReferenceFile
fields = ('id', 'uuid', 'name', 'reference_file', 'project')


class TranslationMemorySerializer(serializers.ModelSerializer):
class Meta:
model = TranslationMemory
fields = ('id', 'uuid', 'name', 'source_language', 'target_language', 'client')

def create(self, validated_data):
validated_data['created_by'] = self.context['request'].user

return super().create(validated_data)


class UserSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True, required=False, style={'input_type': 'password'})
is_active = serializers.BooleanField(initial=True)

class Meta:
model = User
fields = ('id', 'username', 'password', 'email', 'is_active', 'groups')

def create(self, validated_data):
validated_data['password'] = make_password(validated_data.get('password'))

return super().create(validated_data)
15 changes: 15 additions & 0 deletions kaplancloudapi/signals.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django.db.models.signals import post_save
from django.dispatch import receiver

from kaplancloudapi.models import ProjectWebHook, ProjectFileWebHook
from kaplancloudapp.models import Project, ProjectFile

@receiver(post_save, sender=Project)
def on_project_saved(sender, instance, **kwargs):
for project_webhook in ProjectWebHook.objects.filter(project=instance):
project_webhook.fire_hook()

@receiver(post_save, sender=ProjectFile)
def on_project_file_saved(sender, instance, **kwargs):
for project_file_webhook in ProjectFileWebHook.objects.filter(project_file=instance):
project_file_webhook.fire_hook()
3 changes: 3 additions & 0 deletions kaplancloudapi/tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from django.test import TestCase

# Create your tests here.
20 changes: 20 additions & 0 deletions kaplancloudapi/urls.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from django.urls import include, path
from rest_framework import routers

from . import views

router = routers.DefaultRouter()
router.register(r'clients', views.ClientViewSet)
router.register(r'groups', views.GroupViewSet)
router.register(r'language-profiles', views.LanguageProfileViewSet)
router.register(r'projects', views.ProjectViewSet)
router.register(r'project-webhooks', views.ProjectWebHookViewSet)
router.register(r'project-files', views.ProjectFileViewSet)
router.register(r'project-file-webhooks', views.ProjectFileWebHookViewSet)
router.register(r'project-reference-files', views.ProjectReferenceFileViewSet)
router.register(r'translation-memories', views.TranslationMemoryViewSet)
router.register(r'users', views.UserViewSet)

urlpatterns = [
path('', include(router.urls)),
]

0 comments on commit 19a980b

Please sign in to comment.