This commit is contained in:
2023-05-12 23:48:12 +03:00
parent d2e1b54d0c
commit 2d12da1bb8
21 changed files with 77 additions and 1099 deletions

View File

@ -3,5 +3,6 @@ from custom_auth import views
urlpatterns = [
path('', include('rest_framework.urls')),
path('token/', views.CustomAuthToken.as_view())
path('token/', views.CustomAuthToken.as_view()),
path('register/', views.RegisterView.as_view())
]

View File

@ -1,10 +1,13 @@
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, *args, **kwargs):
def post(self, request: Request, *args, **kwargs):
serializer = self.serializer_class(data=request.data,
context={'request': request})
serializer.is_valid(raise_exception=True)
@ -13,5 +16,40 @@ class CustomAuthToken(ObtainAuthToken):
return Response({
'token': token.key,
'user_id': user.pk,
'email': user.email
'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)

Binary file not shown.

View File

@ -1,21 +0,0 @@
from django.contrib import admin
from backend.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)

View File

@ -1,16 +0,0 @@
"""
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()

View File

@ -1,695 +0,0 @@
# Generated by Django 4.1.5 on 2023-05-01 12:33
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="backend.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

@ -1,69 +0,0 @@
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

@ -1,26 +0,0 @@
from rest_framework import permissions
from backend.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

@ -1,39 +0,0 @@
from rest_framework import serializers
from backend.models import Snippet, SnippetParticipant
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
snippets = serializers.PrimaryKeyRelatedField(many=True, queryset=Snippet.objects.all())
class Meta:
model = User
fields = ['id', 'username', 'snippets']
class SnippetSerializer(serializers.ModelSerializer):
class Meta:
model = Snippet
fields = [
"id",
"created",
"title",
"linenos",
"language",
"style",
"owner",
"access"
]
read_only_fields = ["created", "owner"]
owner = serializers.ReadOnlyField(source='owner.username')
class SnippetParticipantSerializer(serializers.ModelSerializer):
class Meta:
model = SnippetParticipant
fields = [
"id",
"user",
"snippet"
]
read_only_fields = ["id"]

View File

@ -1,125 +0,0 @@
"""
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--d$%ho@_=xo$zrj&k2=#$o&p!b6ll*vi_$l5%pv$d%du0%gh%@"
# 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",
"backend"
]
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"

View File

@ -1,12 +0,0 @@
from django.contrib import admin
from django.urls import path, include
from backend import views
urlpatterns = [
path("admin/", admin.site.urls),
path('users/', views.UserList.as_view()),
path('users/<int:pk>/', views.UserDetail.as_view()),
path("snippets/", views.SnippetList.as_view()),
path("snippet/<int:pk>", views.SnippetDetail.as_view()),
path('api-auth/', include('rest_framework.urls')),
]

View File

@ -1,41 +0,0 @@
from backend.models import Snippet, SnippetParticipant
from backend.serializers import SnippetSerializer, UserSerializer
from rest_framework import generics
from django.contrib.auth.models import User
from rest_framework import permissions
from backend.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

View File

@ -1,16 +0,0 @@
"""
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()

Binary file not shown.

View File

@ -1,22 +0,0 @@
#!/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

@ -1,18 +1,22 @@
import React from "react";
import './App.css';
import HomePage from './pages/HomePage'
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { AuthProvider } from "./context/AuthContext";
import AuthPage from './pages/AuthPage'
function App() {
return (
<Router>
<Router>
<AuthProvider>
<Routes>
<Route path="/auth" element={<AuthPage />} />
<Route path="/" element={<div className="App">
<HomePage />
</div>} />
</Routes>
</AuthProvider>
</Router>
);

View File

@ -14,10 +14,12 @@ import {
from 'mdb-react-ui-kit';
import 'mdb-react-ui-kit/dist/css/mdb.min.css';
import "@fortawesome/fontawesome-free/css/all.min.css";
import { useContext } from "react";
import AuthContext from "../context/AuthContext";
const LoginForm = () => {
const [justifyActive, setJustifyActive] = useState('tab1');;
const [justifyActive, setJustifyActive] = useState('tab1');
const handleJustifyClick = (value) => {
if (value === justifyActive) {
@ -27,6 +29,14 @@ const LoginForm = () => {
setJustifyActive(value);
};
const [username, setUsername] = useState("")
const [password, setPassword] = useState("")
const { loginUser } = useContext(AuthContext);
const handleLoginSubmit = () => {
username.length > 0 && loginUser(username, password);
};
return (
<MDBContainer className="p-3 my-5 d-flex flex-column w-50">
@ -47,14 +57,19 @@ const LoginForm = () => {
<MDBTabsPane show={justifyActive === 'tab1'}>
<MDBInput wrapperClass='mb-4' label='Username' id='form1' type='email'/>
<MDBInput wrapperClass='mb-4' label='Password' id='form2' type='password'/>
<MDBInput wrapperClass='mb-4' label='Username' id='form1' type='username' value={username} onInput={e => setUsername(e.target.value)}/>
<MDBInput wrapperClass='mb-4' label='Password' id='form2' type='password'value={password} onInput={e => setPassword(e.target.value)}/>
<div className="d-flex justify-content-between mx-4 mb-4">
<MDBCheckbox name='flexCheck' value='' id='flexCheckDefault' label='Remember me' />
</div>
<MDBBtn className="mb-4 w-100">Sign in</MDBBtn>
<MDBBtn
className="mb-4 w-100"
onClick={handleLoginSubmit}
>
Sign in
</MDBBtn>
<p className="text-center">Not a member? <a href="#!" onClick={() => handleJustifyClick('tab2')} active={justifyActive === 'tab2'}>Register</a></p>
</MDBTabsPane>

View File

@ -14,7 +14,7 @@ import {Link} from 'react-router-dom';
const MainCard = () => {
return (
<MDBCard style={{width: "80%"}}>
<MDBCard>
<MDBCardBody>
<MDBCardTitle>Welcome to CodeBox!</MDBCardTitle>
<MDBCardText>

View File

@ -1,8 +1,8 @@
import { createContext, useState, useEffect } from "react";
import jwt_decode from "jwt-decode";
import { useHistory } from "react-router-dom";
import { useNavigate } from "react-router-dom";
const AuthContext = createContext();
const AuthContext = createContext("");
export default AuthContext;
@ -19,13 +19,14 @@ export const AuthProvider = ({ children }) => {
);
const [loading, setLoading] = useState(true);
const history = useHistory();
const history = useNavigate();
const loginUser = async (username, password) => {
const response = await fetch("http://127.0.0.1:8000/api/auth/token/", {
method: "POST",
headers: {
"Content-Type": "application/json"
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: JSON.stringify({
username,
@ -35,6 +36,7 @@ export const AuthProvider = ({ children }) => {
const data = await response.json();
if (response.status === 200) {
console.log(response, data)
setAuthTokens(data);
setUser(jwt_decode(data.access));
localStorage.setItem("authTokens", JSON.stringify(data));
@ -44,16 +46,16 @@ export const AuthProvider = ({ children }) => {
}
};
const registerUser = async (username, password, password2) => {
const registerUser = async (username, password) => {
const response = await fetch("http://127.0.0.1:8000/api/auth/register/", {
method: "POST",
headers: {
"Content-Type": "application/json"
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
},
body: JSON.stringify({
username,
password,
password2
password
})
});
if (response.status === 201) {