moving to docker

This commit is contained in:
2023-05-14 20:28:29 +03:00
parent 6f7219ff7b
commit d5802fa48f
62 changed files with 87 additions and 0 deletions

View File

16
api/app/backend/asgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
ASGI config for backend project.
It exposes the ASGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/asgi/
"""
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
application = get_asgi_application()

131
api/app/backend/settings.py Normal file
View File

@ -0,0 +1,131 @@
"""
Django settings for backend project.
Generated by 'django-admin startproject' using Django 4.1.5.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""
from pathlib import Path
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "django-insecure-o27968vc7m@z*=+$ykqo!b2v+ycc)r2^d8u=)ee)gi5bas-+wm"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
'rest_framework.authtoken',
"rest_framework",
"snippets",
"custom_auth"
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "backend.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "backend.wsgi.application"
# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": BASE_DIR / "db.sqlite3",
}
}
# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "UTC"
USE_I18N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/
STATIC_URL = "static/"
# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
ACCOUNT_SIGNUP_PASSWORD_VERIFICATION = False
AUTH_PASSWORD_VALIDATORS = {}

23
api/app/backend/urls.py Normal file
View File

@ -0,0 +1,23 @@
"""backend URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/4.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path("api/admin/", admin.site.urls),
path("api/", include('snippets.urls')),
path("api/auth/", include('custom_auth.urls'))
]

16
api/app/backend/wsgi.py Normal file
View File

@ -0,0 +1,16 @@
"""
WSGI config for backend project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/4.1/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
application = get_wsgi_application()

View File

View File

@ -0,0 +1,3 @@
from django.contrib import admin
# Register your models here.

View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class AuthConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "custom_auth"

View File

@ -0,0 +1,3 @@
from django.db import models
# Create your models here.

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,8 @@
from django.urls import path, include
from custom_auth import views
urlpatterns = [
path('', include('rest_framework.urls')),
path('token/', views.CustomAuthToken.as_view()),
path('register/', views.RegisterView.as_view())
]

View File

@ -0,0 +1,55 @@
from rest_framework.authtoken.views import ObtainAuthToken
from rest_framework.authtoken.models import Token
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.views import APIView
from django.contrib.auth.models import User
class CustomAuthToken(ObtainAuthToken):
def post(self, request: Request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'username': user.username
})
class RegisterView(APIView):
def get(self, request: Request, *args, **kwargs):
username = request.data.get("username", None)
if not username:
return Response({"message": "Username must not be empty"}, status=406)
if User.objects.filter(username=username).exists():
return Response({"message": "Username already taken"}, status=409)
return Response({"message": "Username availiable"}, status=200)
def post(self, request: Request, *args, **kwargs):
username = request.data.get("username")
if not username:
return Response({"message": "Username must not be empty"}, status=406)
if User.objects.filter(username=username).exists():
return Response({"message": "Username already taken"}, status=409)
password = request.data.get("password", None)
if not password:
return Response({"message": "Password must not be empty"}, status=406)
try:
user = User.objects.create_user(
is_superuser=False,
username=username,
password=password
)
token, created = Token.objects.get_or_create(user=user)
return Response({
'token': token.key,
'user_id': user.pk,
'username': user.username
}, status=200)
except Exception as e:
return Response({"message": "Something went wrong, registration is not completed", "error": e}, status=500)

BIN
api/app/db.sqlite3 Normal file

Binary file not shown.

22
api/app/manage.py Executable file
View File

@ -0,0 +1,22 @@
#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys
def main():
"""Run administrative tasks."""
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "backend.settings")
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
if __name__ == "__main__":
main()

View File

21
api/app/snippets/admin.py Normal file
View File

@ -0,0 +1,21 @@
from django.contrib import admin
from snippets.models import Snippet, SnippetParticipant
class SnippetAdmin(admin.ModelAdmin):
list_display = ('id', 'title', 'created')
list_display_links = ('id', 'title')
search_fields = ('title',)
list_filter = ('created',)
ordering = ('-created',)
class SnippetParticipantAdmin(admin.ModelAdmin):
list_display = ('id', 'user', "snippet")
list_display_links = ('id', 'user', "snippet")
search_fields = ('user', "snippet")
list_filter = ('id',)
ordering = ('-id',)
admin.site.register(Snippet, SnippetAdmin)
admin.site.register(SnippetParticipant, SnippetParticipantAdmin)

6
api/app/snippets/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class SnippetsConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "snippets"

View File

@ -0,0 +1,695 @@
# Generated by Django 4.1.5 on 2023-05-01 12:57
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Snippet",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(auto_now_add=True)),
("title", models.CharField(blank=True, default="", max_length=100)),
("content", models.TextField()),
("linenos", models.BooleanField(default=False)),
(
"language",
models.CharField(
choices=[
("abap", "ABAP"),
("abnf", "ABNF"),
("actionscript", "ActionScript"),
("actionscript3", "ActionScript 3"),
("ada", "Ada"),
("adl", "ADL"),
("agda", "Agda"),
("aheui", "Aheui"),
("alloy", "Alloy"),
("ambienttalk", "AmbientTalk"),
("amdgpu", "AMDGPU"),
("ampl", "Ampl"),
("ansys", "ANSYS parametric design language"),
("antlr", "ANTLR"),
("antlr-actionscript", "ANTLR With ActionScript Target"),
("antlr-cpp", "ANTLR With CPP Target"),
("antlr-csharp", "ANTLR With C# Target"),
("antlr-java", "ANTLR With Java Target"),
("antlr-objc", "ANTLR With ObjectiveC Target"),
("antlr-perl", "ANTLR With Perl Target"),
("antlr-python", "ANTLR With Python Target"),
("antlr-ruby", "ANTLR With Ruby Target"),
("apacheconf", "ApacheConf"),
("apl", "APL"),
("applescript", "AppleScript"),
("arduino", "Arduino"),
("arrow", "Arrow"),
("asc", "ASCII armored"),
("aspectj", "AspectJ"),
("aspx-cs", "aspx-cs"),
("aspx-vb", "aspx-vb"),
("asymptote", "Asymptote"),
("augeas", "Augeas"),
("autohotkey", "autohotkey"),
("autoit", "AutoIt"),
("awk", "Awk"),
("bare", "BARE"),
("basemake", "Base Makefile"),
("bash", "Bash"),
("batch", "Batchfile"),
("bbcbasic", "BBC Basic"),
("bbcode", "BBCode"),
("bc", "BC"),
("bdd", "Bdd"),
("befunge", "Befunge"),
("berry", "Berry"),
("bibtex", "BibTeX"),
("blitzbasic", "BlitzBasic"),
("blitzmax", "BlitzMax"),
("bnf", "BNF"),
("boa", "Boa"),
("boo", "Boo"),
("boogie", "Boogie"),
("brainfuck", "Brainfuck"),
("bst", "BST"),
("bugs", "BUGS"),
("c", "C"),
("c-objdump", "c-objdump"),
("ca65", "ca65 assembler"),
("cadl", "cADL"),
("camkes", "CAmkES"),
("capdl", "CapDL"),
("capnp", "Cap'n Proto"),
("cbmbas", "CBM BASIC V2"),
("cddl", "CDDL"),
("ceylon", "Ceylon"),
("cfc", "Coldfusion CFC"),
("cfengine3", "CFEngine3"),
("cfm", "Coldfusion HTML"),
("cfs", "cfstatement"),
("chaiscript", "ChaiScript"),
("chapel", "Chapel"),
("charmci", "Charmci"),
("cheetah", "Cheetah"),
("cirru", "Cirru"),
("clay", "Clay"),
("clean", "Clean"),
("clojure", "Clojure"),
("clojurescript", "ClojureScript"),
("cmake", "CMake"),
("cobol", "COBOL"),
("cobolfree", "COBOLFree"),
("coffeescript", "CoffeeScript"),
("comal", "COMAL-80"),
("common-lisp", "Common Lisp"),
("componentpascal", "Component Pascal"),
("console", "Bash Session"),
("coq", "Coq"),
("cplint", "cplint"),
("cpp", "C++"),
("cpp-objdump", "cpp-objdump"),
("cpsa", "CPSA"),
("cr", "Crystal"),
("crmsh", "Crmsh"),
("croc", "Croc"),
("cryptol", "Cryptol"),
("csharp", "C#"),
("csound", "Csound Orchestra"),
("csound-document", "Csound Document"),
("csound-score", "Csound Score"),
("css", "CSS"),
("css+django", "CSS+Django/Jinja"),
("css+genshitext", "CSS+Genshi Text"),
("css+lasso", "CSS+Lasso"),
("css+mako", "CSS+Mako"),
("css+mako", "CSS+Mako"),
("css+mozpreproc", "CSS+mozpreproc"),
("css+myghty", "CSS+Myghty"),
("css+php", "CSS+PHP"),
("css+ruby", "CSS+Ruby"),
("css+smarty", "CSS+Smarty"),
("css+ul4", "CSS+UL4"),
("cuda", "CUDA"),
("cypher", "Cypher"),
("cython", "Cython"),
("d", "D"),
("d-objdump", "d-objdump"),
("dart", "Dart"),
("dasm16", "DASM16"),
("debcontrol", "Debian Control file"),
("debsources", "Debian Sourcelist"),
("delphi", "Delphi"),
("devicetree", "Devicetree"),
("dg", "dg"),
("diff", "Diff"),
("django", "Django/Jinja"),
("docker", "Docker"),
("doscon", "MSDOS Session"),
("dpatch", "Darcs Patch"),
("dtd", "DTD"),
("duel", "Duel"),
("dylan", "Dylan"),
("dylan-console", "Dylan session"),
("dylan-lid", "DylanLID"),
("earl-grey", "Earl Grey"),
("easytrieve", "Easytrieve"),
("ebnf", "EBNF"),
("ec", "eC"),
("ecl", "ECL"),
("eiffel", "Eiffel"),
("elixir", "Elixir"),
("elm", "Elm"),
("elpi", "Elpi"),
("emacs-lisp", "EmacsLisp"),
("email", "E-mail"),
("erb", "ERB"),
("erl", "Erlang erl session"),
("erlang", "Erlang"),
("evoque", "Evoque"),
("execline", "execline"),
("extempore", "xtlang"),
("ezhil", "Ezhil"),
("factor", "Factor"),
("fan", "Fantom"),
("fancy", "Fancy"),
("felix", "Felix"),
("fennel", "Fennel"),
("fish", "Fish"),
("flatline", "Flatline"),
("floscript", "FloScript"),
("forth", "Forth"),
("fortran", "Fortran"),
("fortranfixed", "FortranFixed"),
("foxpro", "FoxPro"),
("freefem", "Freefem"),
("fsharp", "F#"),
("fstar", "FStar"),
("futhark", "Futhark"),
("gap", "GAP"),
("gas", "GAS"),
("gcode", "g-code"),
("gdscript", "GDScript"),
("genshi", "Genshi"),
("genshitext", "Genshi Text"),
("gherkin", "Gherkin"),
("glsl", "GLSL"),
("gnuplot", "Gnuplot"),
("go", "Go"),
("golo", "Golo"),
("gooddata-cl", "GoodData-CL"),
("gosu", "Gosu"),
("graphviz", "Graphviz"),
("groff", "Groff"),
("groovy", "Groovy"),
("gsql", "GSQL"),
("gst", "Gosu Template"),
("haml", "Haml"),
("handlebars", "Handlebars"),
("haskell", "Haskell"),
("haxe", "Haxe"),
("haxeml", "Hxml"),
("hexdump", "Hexdump"),
("hlsl", "HLSL"),
("hsail", "HSAIL"),
("hspec", "Hspec"),
("html", "HTML"),
("html+cheetah", "HTML+Cheetah"),
("html+django", "HTML+Django/Jinja"),
("html+evoque", "HTML+Evoque"),
("html+genshi", "HTML+Genshi"),
("html+handlebars", "HTML+Handlebars"),
("html+lasso", "HTML+Lasso"),
("html+mako", "HTML+Mako"),
("html+mako", "HTML+Mako"),
("html+myghty", "HTML+Myghty"),
("html+ng2", "HTML + Angular2"),
("html+php", "HTML+PHP"),
("html+smarty", "HTML+Smarty"),
("html+twig", "HTML+Twig"),
("html+ul4", "HTML+UL4"),
("html+velocity", "HTML+Velocity"),
("http", "HTTP"),
("hybris", "Hybris"),
("hylang", "Hy"),
("i6t", "Inform 6 template"),
("icon", "Icon"),
("idl", "IDL"),
("idris", "Idris"),
("iex", "Elixir iex session"),
("igor", "Igor"),
("inform6", "Inform 6"),
("inform7", "Inform 7"),
("ini", "INI"),
("io", "Io"),
("ioke", "Ioke"),
("ipython2", "IPython"),
("ipython3", "IPython3"),
("ipythonconsole", "IPython console session"),
("irc", "IRC logs"),
("isabelle", "Isabelle"),
("j", "J"),
("jags", "JAGS"),
("jasmin", "Jasmin"),
("java", "Java"),
("javascript", "JavaScript"),
("javascript+cheetah", "JavaScript+Cheetah"),
("javascript+django", "JavaScript+Django/Jinja"),
("javascript+lasso", "JavaScript+Lasso"),
("javascript+mako", "JavaScript+Mako"),
("javascript+mozpreproc", "Javascript+mozpreproc"),
("javascript+myghty", "JavaScript+Myghty"),
("javascript+php", "JavaScript+PHP"),
("javascript+ruby", "JavaScript+Ruby"),
("javascript+smarty", "JavaScript+Smarty"),
("jcl", "JCL"),
("jlcon", "Julia console"),
("jmespath", "JMESPath"),
("js+genshitext", "JavaScript+Genshi Text"),
("js+mako", "JavaScript+Mako"),
("js+ul4", "Javascript+UL4"),
("jsgf", "JSGF"),
("jslt", "JSLT"),
("json", "JSON"),
("jsonld", "JSON-LD"),
("jsp", "Java Server Page"),
("julia", "Julia"),
("juttle", "Juttle"),
("k", "K"),
("kal", "Kal"),
("kconfig", "Kconfig"),
("kmsg", "Kernel log"),
("koka", "Koka"),
("kotlin", "Kotlin"),
("kuin", "Kuin"),
("lasso", "Lasso"),
("lean", "Lean"),
("less", "LessCss"),
("lighttpd", "Lighttpd configuration file"),
("lilypond", "LilyPond"),
("limbo", "Limbo"),
("liquid", "liquid"),
("literate-agda", "Literate Agda"),
("literate-cryptol", "Literate Cryptol"),
("literate-haskell", "Literate Haskell"),
("literate-idris", "Literate Idris"),
("livescript", "LiveScript"),
("llvm", "LLVM"),
("llvm-mir", "LLVM-MIR"),
("llvm-mir-body", "LLVM-MIR Body"),
("logos", "Logos"),
("logtalk", "Logtalk"),
("lsl", "LSL"),
("lua", "Lua"),
("macaulay2", "Macaulay2"),
("make", "Makefile"),
("mako", "Mako"),
("mako", "Mako"),
("maql", "MAQL"),
("markdown", "Markdown"),
("mask", "Mask"),
("mason", "Mason"),
("mathematica", "Mathematica"),
("matlab", "Matlab"),
("matlabsession", "Matlab session"),
("maxima", "Maxima"),
("mcfunction", "MCFunction"),
("meson", "Meson"),
("mime", "MIME"),
("minid", "MiniD"),
("miniscript", "MiniScript"),
("modelica", "Modelica"),
("modula2", "Modula-2"),
("monkey", "Monkey"),
("monte", "Monte"),
("moocode", "MOOCode"),
("moonscript", "MoonScript"),
("mosel", "Mosel"),
("mozhashpreproc", "mozhashpreproc"),
("mozpercentpreproc", "mozpercentpreproc"),
("mql", "MQL"),
("mscgen", "Mscgen"),
("mupad", "MuPAD"),
("mxml", "MXML"),
("myghty", "Myghty"),
("mysql", "MySQL"),
("nasm", "NASM"),
("ncl", "NCL"),
("nemerle", "Nemerle"),
("nesc", "nesC"),
("nestedtext", "NestedText"),
("newlisp", "NewLisp"),
("newspeak", "Newspeak"),
("ng2", "Angular2"),
("nginx", "Nginx configuration file"),
("nimrod", "Nimrod"),
("nit", "Nit"),
("nixos", "Nix"),
("nodejsrepl", "Node.js REPL console session"),
("notmuch", "Notmuch"),
("nsis", "NSIS"),
("numpy", "NumPy"),
("nusmv", "NuSMV"),
("objdump", "objdump"),
("objdump-nasm", "objdump-nasm"),
("objective-c", "Objective-C"),
("objective-c++", "Objective-C++"),
("objective-j", "Objective-J"),
("ocaml", "OCaml"),
("octave", "Octave"),
("odin", "ODIN"),
("omg-idl", "OMG Interface Definition Language"),
("ooc", "Ooc"),
("opa", "Opa"),
("openedge", "OpenEdge ABL"),
("output", "Text output"),
("pacmanconf", "PacmanConf"),
("pan", "Pan"),
("parasail", "ParaSail"),
("pawn", "Pawn"),
("peg", "PEG"),
("perl", "Perl"),
("perl6", "Perl6"),
("php", "PHP"),
("pig", "Pig"),
("pike", "Pike"),
("pkgconfig", "PkgConfig"),
("plpgsql", "PL/pgSQL"),
("pointless", "Pointless"),
("pony", "Pony"),
("postgresql", "PostgreSQL SQL dialect"),
("postscript", "PostScript"),
("pot", "Gettext Catalog"),
("pov", "POVRay"),
("powershell", "PowerShell"),
("praat", "Praat"),
("procfile", "Procfile"),
("prolog", "Prolog"),
("promql", "PromQL"),
("properties", "Properties"),
("protobuf", "Protocol Buffer"),
("psql", "PostgreSQL console (psql)"),
("psysh", "PsySH console session for PHP"),
("pug", "Pug"),
("puppet", "Puppet"),
("pwsh-session", "PowerShell Session"),
("py+ul4", "Python+UL4"),
("py2tb", "Python 2.x Traceback"),
("pycon", "Python console session"),
("pypylog", "PyPy Log"),
("pytb", "Python Traceback"),
("python", "Python"),
("python2", "Python 2.x"),
("q", "Q"),
("qbasic", "QBasic"),
("qlik", "Qlik"),
("qml", "QML"),
("qvto", "QVTO"),
("racket", "Racket"),
("ragel", "Ragel"),
("ragel-c", "Ragel in C Host"),
("ragel-cpp", "Ragel in CPP Host"),
("ragel-d", "Ragel in D Host"),
("ragel-em", "Embedded Ragel"),
("ragel-java", "Ragel in Java Host"),
("ragel-objc", "Ragel in Objective C Host"),
("ragel-ruby", "Ragel in Ruby Host"),
("rbcon", "Ruby irb session"),
("rconsole", "RConsole"),
("rd", "Rd"),
("reasonml", "ReasonML"),
("rebol", "REBOL"),
("red", "Red"),
("redcode", "Redcode"),
("registry", "reg"),
("resourcebundle", "ResourceBundle"),
("restructuredtext", "reStructuredText"),
("rexx", "Rexx"),
("rhtml", "RHTML"),
("ride", "Ride"),
("rita", "Rita"),
("rng-compact", "Relax-NG Compact"),
("roboconf-graph", "Roboconf Graph"),
("roboconf-instances", "Roboconf Instances"),
("robotframework", "RobotFramework"),
("rql", "RQL"),
("rsl", "RSL"),
("ruby", "Ruby"),
("rust", "Rust"),
("sarl", "SARL"),
("sas", "SAS"),
("sass", "Sass"),
("savi", "Savi"),
("scala", "Scala"),
("scaml", "Scaml"),
("scdoc", "scdoc"),
("scheme", "Scheme"),
("scilab", "Scilab"),
("scss", "SCSS"),
("sed", "Sed"),
("sgf", "SmartGameFormat"),
("shen", "Shen"),
("shexc", "ShExC"),
("sieve", "Sieve"),
("silver", "Silver"),
("singularity", "Singularity"),
("slash", "Slash"),
("slim", "Slim"),
("slurm", "Slurm"),
("smali", "Smali"),
("smalltalk", "Smalltalk"),
("smarty", "Smarty"),
("smithy", "Smithy"),
("sml", "Standard ML"),
("snbt", "SNBT"),
("snobol", "Snobol"),
("snowball", "Snowball"),
("solidity", "Solidity"),
("sophia", "Sophia"),
("sp", "SourcePawn"),
("sparql", "SPARQL"),
("spec", "RPMSpec"),
("spice", "Spice"),
("splus", "S"),
("sql", "SQL"),
("sql+jinja", "SQL+Jinja"),
("sqlite3", "sqlite3con"),
("squidconf", "SquidConf"),
("srcinfo", "Srcinfo"),
("ssp", "Scalate Server Page"),
("stan", "Stan"),
("stata", "Stata"),
("supercollider", "SuperCollider"),
("swift", "Swift"),
("swig", "SWIG"),
("systemverilog", "systemverilog"),
("tads3", "TADS 3"),
("tal", "Tal"),
("tap", "TAP"),
("tasm", "TASM"),
("tcl", "Tcl"),
("tcsh", "Tcsh"),
("tcshcon", "Tcsh Session"),
("tea", "Tea"),
("teal", "teal"),
("teratermmacro", "Tera Term macro"),
("termcap", "Termcap"),
("terminfo", "Terminfo"),
("terraform", "Terraform"),
("tex", "TeX"),
("text", "Text only"),
("thrift", "Thrift"),
("ti", "ThingsDB"),
("tid", "tiddler"),
("tnt", "Typographic Number Theory"),
("todotxt", "Todotxt"),
("toml", "TOML"),
("trac-wiki", "MoinMoin/Trac Wiki markup"),
("trafficscript", "TrafficScript"),
("treetop", "Treetop"),
("tsql", "Transact-SQL"),
("turtle", "Turtle"),
("twig", "Twig"),
("typescript", "TypeScript"),
("typoscript", "TypoScript"),
("typoscriptcssdata", "TypoScriptCssData"),
("typoscripthtmldata", "TypoScriptHtmlData"),
("ucode", "ucode"),
("ul4", "UL4"),
("unicon", "Unicon"),
("unixconfig", "Unix/Linux config files"),
("urbiscript", "UrbiScript"),
("usd", "USD"),
("vala", "Vala"),
("vb.net", "VB.net"),
("vbscript", "VBScript"),
("vcl", "VCL"),
("vclsnippets", "VCLSnippets"),
("vctreestatus", "VCTreeStatus"),
("velocity", "Velocity"),
("verilog", "verilog"),
("vgl", "VGL"),
("vhdl", "vhdl"),
("vim", "VimL"),
("wast", "WebAssembly"),
("wdiff", "WDiff"),
("webidl", "Web IDL"),
("whiley", "Whiley"),
("x10", "X10"),
("xml", "XML"),
("xml+cheetah", "XML+Cheetah"),
("xml+django", "XML+Django/Jinja"),
("xml+evoque", "XML+Evoque"),
("xml+lasso", "XML+Lasso"),
("xml+mako", "XML+Mako"),
("xml+mako", "XML+Mako"),
("xml+myghty", "XML+Myghty"),
("xml+php", "XML+PHP"),
("xml+ruby", "XML+Ruby"),
("xml+smarty", "XML+Smarty"),
("xml+ul4", "XML+UL4"),
("xml+velocity", "XML+Velocity"),
("xorg.conf", "Xorg"),
("xquery", "XQuery"),
("xslt", "XSLT"),
("xtend", "Xtend"),
("xul+mozpreproc", "XUL+mozpreproc"),
("yaml", "YAML"),
("yaml+jinja", "YAML+Jinja"),
("yang", "YANG"),
("zeek", "Zeek"),
("zephir", "Zephir"),
("zig", "Zig"),
],
default="python",
max_length=100,
),
),
(
"style",
models.CharField(
choices=[
("abap", "abap"),
("algol", "algol"),
("algol_nu", "algol_nu"),
("arduino", "arduino"),
("autumn", "autumn"),
("borland", "borland"),
("bw", "bw"),
("colorful", "colorful"),
("default", "default"),
("dracula", "dracula"),
("emacs", "emacs"),
("friendly", "friendly"),
("friendly_grayscale", "friendly_grayscale"),
("fruity", "fruity"),
("github-dark", "github-dark"),
("gruvbox-dark", "gruvbox-dark"),
("gruvbox-light", "gruvbox-light"),
("igor", "igor"),
("inkpot", "inkpot"),
("lilypond", "lilypond"),
("lovelace", "lovelace"),
("manni", "manni"),
("material", "material"),
("monokai", "monokai"),
("murphy", "murphy"),
("native", "native"),
("nord", "nord"),
("nord-darker", "nord-darker"),
("one-dark", "one-dark"),
("paraiso-dark", "paraiso-dark"),
("paraiso-light", "paraiso-light"),
("pastie", "pastie"),
("perldoc", "perldoc"),
("rainbow_dash", "rainbow_dash"),
("rrt", "rrt"),
("sas", "sas"),
("solarized-dark", "solarized-dark"),
("solarized-light", "solarized-light"),
("staroffice", "staroffice"),
("stata", "stata"),
("stata-dark", "stata-dark"),
("stata-light", "stata-light"),
("tango", "tango"),
("trac", "trac"),
("vim", "vim"),
("vs", "vs"),
("xcode", "xcode"),
("zenburn", "zenburn"),
],
default="friendly",
max_length=100,
),
),
("highlighted", models.TextField()),
(
"access",
models.CharField(
choices=[
("public", "Public"),
("private", "Private"),
("owner-only", "Owner only"),
],
default="private",
max_length=20,
verbose_name="Access type",
),
),
(
"owner",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
verbose_name="Snippet owner",
),
),
],
options={
"ordering": ["created"],
},
),
migrations.CreateModel(
name="SnippetParticipant",
fields=[
(
"id",
models.IntegerField(
primary_key=True, serialize=False, verbose_name="ID"
),
),
(
"snippet",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="snippets.snippet",
verbose_name="Associated Snippet",
),
),
(
"user",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to=settings.AUTH_USER_MODEL,
verbose_name="Associated User",
),
),
],
),
]

View File

View File

@ -0,0 +1,69 @@
from django.db import models
from pygments.lexers import get_all_lexers
from pygments.styles import get_all_styles
from pygments.lexers import get_lexer_by_name
from pygments.formatters.html import HtmlFormatter
from pygments import highlight
LEXERS = [item for item in get_all_lexers() if item[1]]
LANGUAGE_CHOICES = sorted([(item[1][0], item[0]) for item in LEXERS])
STYLE_CHOICES = sorted([(item, item) for item in get_all_styles()])
ACCESS_TYPES = (("public", "Public"), ("private", "Private"), ("owner-only", "Owner only"))
class Snippet(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
content = models.TextField()
linenos = models.BooleanField(default=False)
language = models.CharField(choices=LANGUAGE_CHOICES, default='python', max_length=100)
style = models.CharField(choices=STYLE_CHOICES, default='friendly', max_length=100)
highlighted = models.TextField()
owner = models.ForeignKey(
verbose_name="Snippet owner",
to="auth.User",
on_delete=models.CASCADE
)
access = models.CharField(
verbose_name="Access type",
choices=ACCESS_TYPES,
default="private",
max_length=20
)
def save(self, *args, **kwargs):
"""
Use the `pygments` library to create a highlighted HTML
representation of the code snippet.
"""
lexer = get_lexer_by_name(self.language)
linenos = 'table' if self.linenos else False
options = {'title': self.title} if self.title else {}
formatter = HtmlFormatter(
style=self.style,
linenos=linenos,
full=True,
**options
)
self.highlighted = highlight(self.content, lexer, formatter)
super().save(*args, **kwargs)
class Meta:
ordering = ['created']
class SnippetParticipant(models.Model):
id = models.IntegerField(
verbose_name="ID",
primary_key=True
)
user = models.ForeignKey(
verbose_name="Associated User",
to="auth.User",
on_delete=models.CASCADE
)
snippet = models.ForeignKey(
verbose_name="Associated Snippet",
to=Snippet,
on_delete=models.CASCADE
)

View File

@ -0,0 +1,26 @@
from rest_framework import permissions
from snippets.models import SnippetParticipant
class IsOwnerOrReadOnly(permissions.BasePermission):
"""
Custom permission to only allow owners of an object to edit it.
"""
def has_object_permission(self, request, view, obj):
# Read permissions are allowed to any request,
# so we'll always allow GET, HEAD or OPTIONS requests.
if request.method in permissions.SAFE_METHODS:
return True
# Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user
class IsAccessedOrDeny(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
if obj.owner == request.user:
return True
allowed_users = SnippetParticipant.objects.filter(snippet=obj)
return request.user in [i.user for i in allowed_users]

View File

@ -0,0 +1,46 @@
from rest_framework import serializers
from snippets.models import Snippet, SnippetParticipant
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username']
class SnippetSerializer(serializers.ModelSerializer):
def get_allowed_users(self, obj) -> list[str]:
query = SnippetParticipant.objects.filter(snippet=obj)
return [ele.username for ele in query]
class Meta:
model = Snippet
fields = [
"id",
"created",
"title",
"contetns",
"linenos",
"language",
"style",
"owner",
"access",
]
read_only_fields = ["created", "owner"]
owner = serializers.ReadOnlyField(source='owner.username')
allowed_users = serializers.SerializerMethodField(read_only=True)
#
# class SnippetParticipantSerializer(serializers.ModelSerializer):
# class Meta:
# model = SnippetParticipant
# fields = [
# "id",
# "user",
# "snippet"
# ]
# read_only_fields = ["id"]

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

9
api/app/snippets/urls.py Normal file
View File

@ -0,0 +1,9 @@
from django.urls import path
from snippets import views
urlpatterns = [
path('users/', views.UserList.as_view()),
path('users/<int:pk>/', views.UserDetail.as_view()),
path("snippets/", views.SnippetList.as_view()),
path("snippets/<int:pk>", views.SnippetDetail.as_view()),
]

41
api/app/snippets/views.py Normal file
View File

@ -0,0 +1,41 @@
from snippets.models import Snippet, SnippetParticipant
from snippets.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics
from django.contrib.auth.models import User
from rest_framework import permissions
from snippets.permissions import IsAccessedOrDeny
class UserList(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class UserDetail(generics.RetrieveAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
permission_classes = [permissions.IsAuthenticatedOrReadOnly, IsAccessedOrDeny]
class SnippetParticipantList(generics.ListCreateAPIView):
queryset = SnippetParticipant.objects.all()
serializer_class = SnippetSerializer
class SnippetParticipantDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = SnippetParticipant.objects.all()
serializer_class = SnippetSerializer