diff --git a/.gitignore b/.gitignore
index e67073c..a70aeeb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -246,6 +246,9 @@ Control.ca-bundle
Control.system-ca-bundle
GitHub.sublime-settings
+#SkoolOS
+*.profile
+
# Visual Studio Code #
.vscode/*
!.vscode/settings.json
diff --git a/.profile b/.profile
deleted file mode 100644
index df779be..0000000
--- a/.profile
+++ /dev/null
@@ -1 +0,0 @@
-{'absences': 2, 'address': None, 'counselor': {'first_name': 'Sean', 'full_name': 'Sean Burke', 'id': 37, 'last_name': 'Burke', 'url': 'https://ion.tjhsst.edu/api/profile/37', 'user_type': 'counselor', 'username': 'SPBurke'}, 'display_name': 'Raffu Khondaker', 'emails': [], 'first_name': 'Raffu', 'full_name': 'Raffu Khondaker', 'grade': {'name': 'sophomore', 'number': 10}, 'graduation_year': 2022, 'id': 36508, 'ion_username': '2022rkhondak', 'is_announcements_admin': False, 'is_eighth_admin': False, 'is_student': True, 'is_teacher': False, 'last_name': 'Khondaker', 'middle_name': 'Al', 'nickname': '', 'phones': [], 'picture': 'https://ion.tjhsst.edu/api/profile/36508/picture', 'sex': 'Male', 'short_name': 'Raffu', 'title': None, 'tj_email': '2022rkhondak@tjhsst.edu', 'user_type': 'student', 'websites': []}
\ No newline at end of file
diff --git a/BackgroundService/bgservice.py b/BackgroundService/bgservice.py
new file mode 100644
index 0000000..ed26c76
--- /dev/null
+++ b/BackgroundService/bgservice.py
@@ -0,0 +1,58 @@
+import os
+import sys
+import signal
+import time
+import event_processor
+
+
+class SkoolOSDaemon:
+ """Constructor"""
+ def __init__(self, work_dir='/tmp'):
+ self.work_dir = work_dir
+ self.start_time = None
+ self.end_time = None
+ self.log_file = None
+ def __write_pid_file(self):
+ try:
+ dirName = "/tmp/skooloslogs"
+ # Create log Directory
+ os.mkdir(dirName)
+ except FileExistsError:
+ pass
+ pid = str(os.getpid())
+ file_ = open('/tmp/skoolosdaemonpid', 'w')
+ file_.write(pid)
+ file_.close()
+ def readable_time(self, input_time):
+ return time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime(input_time))
+ def start(self):
+ self.__write_pid_file()
+ self.start_time = time.time()
+ self.log_file = open('/tmp/skooloslogs/' + str(self.start_time), 'w')
+ self.log_file.write("Start time: \n" + self.readable_time(self.start_time) + "\n\n")
+ sys.stdout = self.log_file
+ event_processor.watch_dir(self.work_dir)
+ def stop(self):
+ event_processor.stop_watching()
+ self.end_time = time.time()
+ self.log_file.write("Stop time: \n" + self.readable_time(self.end_time))
+ self.log_file.write("Total work time: " +
+ time.strftime("%H:%M:%S", time.gmtime(self.end_time - self.start_time)))
+
+
+
+
+logger = None
+
+def Main():
+ def signal_handler(signum, frame):
+ logger.stop()
+ signal.signal(signal.SIGINT, signal_handler)
+ # signal.signal(signal.SIGTERM, signal_handler)
+ global logger
+ logger = SkoolOSDaemon("/tmp")
+ logger.start()
+
+
+if __name__ == "__main__":
+ Main()
diff --git a/BackgroundService/event_processor.py b/BackgroundService/event_processor.py
new file mode 100644
index 0000000..55c5e15
--- /dev/null
+++ b/BackgroundService/event_processor.py
@@ -0,0 +1,65 @@
+import time
+import pyinotify
+
+
+def readable_time(input_time):
+ return time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime(input_time))
+
+
+class EventProcessor(pyinotify.ProcessEvent):
+ _methods = ["IN_OPEN",
+ "IN_CREATE",
+ "IN_CLOSE_WRITE",
+ "IN_DELETE",
+ "IN_MOVED_TO",
+ "IN_MOVED_FROM",
+ ]
+
+
+def __method_format(method):
+ return {
+ "IN_OPEN":"Opened a file",
+ "IN_CREATE":"Created a file",
+ "IN_CLOSE_WRITE":"Wrote to a file",
+ "IN_DELETE":"Deleted a file",
+ "IN_MOVED_TO":"Moved a file or directory in from elsewhere",
+ "IN_MOVED_FROM":"Moved a file or directory elsewhere",
+ }.get(method, "Unknown event")
+
+
+def __process_generator(cls, method):
+ def _method_name(self, event):
+ description = "Event description: {}\n" \
+ "Path name: {}\n" \
+ "Event Name: {}\n" \
+ "Timestamp: {}\n".format(__method_format(method),
+ event.pathname,
+ event.maskname,
+ readable_time(time.time())
+ )
+ if "IN_DELETE" in description:
+ description += "WARNING: Unexpected file deletion\n"
+ if "IN_MOVED_TO" in description:
+ description += "WARNING: Unexpected file add to work\n"
+ if "IN_MOVED_FROM" in description:
+ description += "WARNING: Unexpected file moved out of directory\n"
+ print(description)
+ _method_name.__name__ = "process_{}".format(method)
+ setattr(cls, _method_name.__name__, _method_name)
+
+
+EVENT_NOTIFIER = None
+
+
+def watch_dir(dir_to_watch):
+ global EVENT_NOTIFIER
+ for method in EventProcessor._methods:
+ __process_generator(EventProcessor, method)
+ watch_manager = pyinotify.WatchManager()
+ EVENT_NOTIFIER = pyinotify.ThreadedNotifier(watch_manager, EventProcessor())
+ watch_manager.add_watch(dir_to_watch, pyinotify.ALL_EVENTS, rec=True)
+ EVENT_NOTIFIER.loop()
+
+
+def stop_watching():
+ EVENT_NOTIFIER.stop()
diff --git a/BackgroundService/test.py b/BackgroundService/test.py
new file mode 100644
index 0000000..b797228
--- /dev/null
+++ b/BackgroundService/test.py
@@ -0,0 +1,19 @@
+from bgservice import SkoolOSDaemon as sod
+import threading
+
+logger = sod()
+
+
+if __name__ == "__main__":
+ line=1
+ print(line)
+ line+=1
+ logger.start()
+ print(line)
+ line+=1
+ input("Enter any key when you are done modifyng the /tmp/ directory")
+ print(line)
+ line+=1
+ logger.stop()
+ print(line)
+ line+=1
diff --git a/CLI/commands.py b/CLI/commands.py
index ed1c1f3..39ed5f7 100644
--- a/CLI/commands.py
+++ b/CLI/commands.py
@@ -5,4 +5,144 @@ import os
import argparse
-
\ No newline at end of file
+'''
+my_parser = argparse.ArgumentParser(prog='skool', description='Let SkoolOS control your system', epilog="Try again")
+my_parser.add_argument('--init', action="store_true") #returns true if run argument
+args = my_parser.parse_args()
+
+update()
+outputs = vars(args)
+if(outputs['init']):
+ start()
+'''
+
+#already ccrerrated account through website, has to login
+def update():
+ #get data from database
+ return
+
+def yesorno(question):
+ questions = [
+ {
+ 'type': 'input',
+ 'name': 'response',
+ 'message': question,
+ },
+ ]
+ answers = prompt(questions)
+ if(answers["response"] == "y"):
+ return True
+ return False
+
+def login():
+ #enter username
+ #enter password
+ questions = [
+ {
+ 'type': 'input',
+ 'name': 'webmail',
+ 'message': 'What\'s TJ Webmail',
+ },
+ {
+ 'type': 'password',
+ 'name': 'password',
+ 'message': 'Password?',
+ },
+ ]
+ user = prompt(questions)
+ #reading from json of users (replace w GET to database) to check if user is registered
+ with open('users.json', 'r') as json_file:
+ data = json.load(json_file)
+ for i in range(len(data)):
+ if user["webmail"] == data[i]["webmail"]:
+ if(user["password"] == data[i]["password"]):
+ print("Logged in!")
+ return data[i]
+ else:
+ print("Password incorrect. Try again.")
+ return None
+ print("User not found. Please Try again")
+ return None
+
+#did not create account through website, has to signup/login
+def signup():
+ questions = [
+ {
+ 'type': 'input',
+ 'name': 'first-name',
+ 'message': 'What\'s your first name',
+ },
+ {
+ 'type': 'input',
+ 'name': 'last-name',
+ 'message': 'What\'s your last name?',
+ },
+ {
+ 'type': 'list',
+ 'name': 'grade',
+ 'message': 'Grade?',
+ 'choices':["9","10","11","12"]
+ },
+ {
+ 'type': 'input',
+ 'name': 'webmail',
+ 'message': 'What\'s your TJ Webmail?',
+ },
+ {
+ 'type': 'password',
+ 'name': 'password',
+ 'message': 'Password?',
+ },
+ ]
+ user = prompt(questions)
+ for i in user:
+ if user[i] == "":
+ print("Some forms were left blank. Try again.\n")
+ return None
+ if len(user["password"]) < 6:
+ print("Password is too short. Try again.")
+ return None
+ if (("@tjhsst.edu" in user['webmail']) == False):
+ print("Webmail entered was not a @tjhhsst.edu. Try again.")
+ return None
+
+ user["classes"] = []
+ with open('users.json', 'r') as json_file:
+ data = json.load(json_file)
+ data.append(user)
+ open("users.json", "w").write(str(json.dumps(data)))
+ return user
+
+def relogin():
+ questions = [
+ {
+ 'type': 'list',
+ 'name': 'choice',
+ 'message': '',
+ 'choices':["Continue as current user","Login into new user","Sign up into new account"]
+ },
+ ]
+ answer = prompt(questions)
+
+
+def setup(user):
+ #Read classes/assignenments and setup directory:
+ #SkoolOS/Math/Week1
+ for c in user["classes"]:
+ os.makedirs(c)
+ for a in user["classes"][c]:
+ os.makedirs(c + "/" + a)
+
+def start():
+ if(os.path.exists(".login.txt") == False):
+ b = yesorno("Do you have a SkoolOS account?(y/N)")
+ if(b):
+ user = login()
+ if(user != None):
+ setup(user)
+ open(".login.txt", "w").write(str(user))
+ else:
+ user = signup()
+ if(user != None):
+ open(".login.txt").write(str(user))
+
diff --git a/CLI/oauth/index.html b/CLI/oauth/index.html
index 62f3082..9ffd6ef 100644
--- a/CLI/oauth/index.html
+++ b/CLI/oauth/index.html
@@ -14,7 +14,7 @@
-
+
Sign in with Ion
diff --git a/CLI/skoolos.py b/CLI/skoolos.py
index 57f3ae3..9477806 100644
--- a/CLI/skoolos.py
+++ b/CLI/skoolos.py
@@ -1,6 +1,5 @@
import sys
from urllib.parse import urlparse
-
import requests
from requests_oauthlib import OAuth2Session
from selenium import webdriver
@@ -11,10 +10,15 @@ import socketserver
from threading import Thread
from werkzeug.urls import url_decode
import pprint
+from PyInquirer import prompt, print_json
+import json
+import os
+import argparse
+from cryptography.fernet import Fernet
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
-redirect_uri = 'http://localhost:8000/'
+redirect_uri = 'http://localhost:8000/callback/'
token_url = 'https://ion.tjhsst.edu/oauth/token/'
scope = ["read"]
@@ -30,16 +34,21 @@ def main():
print("")
if not os.path.exists(".profile"):
- print(76546789876545678765)
+ input("Welcome to SkoolOS. Press any key to create an account")
authenticate()
- print(open(".profile", "r").read())
else:
- print(open(".profile", "r").read())
+ file = open('key.key', 'rb')
+ key = file.read() # The key will be type bytes
+ file.close()
+ f = Fernet(key)
+ file = open('.profile', 'rb')
+ p = file.read() # The key will be type bytes
+ file.close()
+
# while True:
# pass
-
def authenticate():
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
@@ -48,12 +57,14 @@ def authenticate():
#Linux: chromdriver-linux
#Macos: chromdriver-mac
#Windows: chromdriver.exe
- path = os.path.join(cdir, "chromedriver-mac")
- print(path)
- browser = webdriver.Chrome(path)
- browser = webdriver.Safari()
+ if('CLI' in os.getcwd()):
+ path = os.path.join(os.getcwd(), '../','chromedriver-mac')
+ else:
+ path = os.path.join(os.getcwd(), 'chromedriver-mac')
+ browser = webdriver.Chrome(path)
web_dir = os.path.join(os.path.dirname(__file__), 'oauth')
+ print(web_dir)
os.chdir(web_dir)
if os.path.exists("index.html"):
os.remove("index.html")
@@ -71,24 +82,29 @@ def authenticate():
browser.get("localhost:8000/")
- while "http://localhost:8000/?code" not in browser.current_url:
+ while "http://localhost:8000/callback/?code" not in browser.current_url:
time.sleep(0.25)
url = browser.current_url
- gets = url_decode(url.replace("http://localhost:8000/?", ""))
+ gets = url_decode(url.replace("http://localhost:8000/callback/?", ""))
+ while "http://localhost:8000/callback/?code" not in browser.current_url:
+ time.sleep(0.25)
+
+ url = browser.current_url
+ gets = url_decode(url.replace("http://localhost:8000/callback/?", ""))
code = gets.get("code")
if state == gets.get("state"):
state = gets.get("state")
print("states good")
browser.quit()
- print(code)
+ #print(code)
print(state)
payload = {'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri, 'client_id': client_id,
'client_secret': client_secret, 'csrfmiddlewaretoken': state}
token = requests.post("https://ion.tjhsst.edu/oauth/token/", data=payload).json()
- print(token)
+ #print(token)
headers = {'Authorization': f"Bearer {token['access_token']}"}
# And finally get the user's profile!
@@ -101,10 +117,18 @@ def authenticate():
last_name = profile['last_name']
os.chdir(cdir)
- profileFile = open(".profile", "w")
- #profileFile.write(profile.text())
- profileFile.write(str(profile))
- profileFile.close()
+ # key = Fernet.generate_key()
+ # file = open('key.key', 'wb')
+ # file.write(key) # The key is type bytes still
+ # file.close()
+ # p = str(profile).encode()
+ # f = Fernet(key)
+ # encrypted = f.encrypt(p)
+
+ # profileFile = open(".profile", "wb")
+ # #profileFile.write(profile.text())
+ # profileFile.write(encrypted)
+ # profileFile.close()
sys.exit
diff --git a/CLI/s-git.py b/CLI/student.py
similarity index 97%
rename from CLI/s-git.py
rename to CLI/student.py
index 4a007af..711c99e 100644
--- a/CLI/s-git.py
+++ b/CLI/student.py
@@ -386,10 +386,17 @@ class Student:
command('git checkout master')
os.chdir(cdir)
-data = getStudent("2022rkhondak")
-s = Student(data)
-#s.viewClass("APLit_eharris1")
-#s.updateClass("APLit_eharris1")
-#s.update()
-s.exitCLI()
+# data = getStudent("2022rkhondak")
+# s = Student(data)
+# #s.viewClass("APLit_eharris1")
+# #s.updateClass("APLit_eharris1")
+# #s.update()
+# s.exitCLI()
+def main():
+ print("noooo")
+ pass
+
+if __name__ == "__main__":
+ # stuff only to run when not called via 'import' here
+ main()
diff --git a/CLI/t-git.py b/CLI/teacher.py
similarity index 99%
rename from CLI/t-git.py
rename to CLI/teacher.py
index 4e81255..d34ae79 100644
--- a/CLI/t-git.py
+++ b/CLI/teacher.py
@@ -659,8 +659,8 @@ t = Teacher(data)
#ar = ['2022rkhondak','2022inafi','2023rumareti']
#extra = t.reqAddStudentList(ar, "APLit_eharris1")
#print(extra)
-t.getStudents('2022rkhondak')
-t.getChanges('2022rkhondak','APLit_eharris1', 10)
+# t.getStudents('2022rkhondak')
+# t.getChanges('2022rkhondak','APLit_eharris1', 10)
'''
TO-DO
diff --git a/Website/api/admin.py b/Website/api/admin.py
index 8c38f3f..8446cf4 100644
--- a/Website/api/admin.py
+++ b/Website/api/admin.py
@@ -1,3 +1,16 @@
from django.contrib import admin
+from .models import (
+ DefFiles,
+ Assignment,
+ Classes,
+ Teacher,
+ Student
+)
# Register your models here.
+
+admin.site.register(Teacher)
+admin.site.register(Student)
+admin.site.register(DefFiles)
+admin.site.register(Assignment)
+admin.site.register(Classes)
diff --git a/Website/api/maker.py b/Website/api/maker.py
index dd31bb6..fb383ed 100644
--- a/Website/api/maker.py
+++ b/Website/api/maker.py
@@ -1,128 +1,128 @@
-from datetime import datetime
-
-f1 = DefFiles(
- name="instructions.txt"
-)
-f1.save()
-f2 = DefFiles(
- name="instructions.txt"
-)
-f2.save()
-f3 = DefFiles(
- name="sample.txt"
-)
-f3.save()
-f4 = DefFiles(
- name="rubric.txt"
-)
-f4.save()
-
-a1 = Assignment.objects.get(pk=1)
-a1.files.add(f1)
-a1.save()
-a2 = Assignment.objects.get(pk=2)
-a2.files.add(f2)
-a2.save()
-a3 = Assignment.objects.get(pk=3)
-a3.files.add(f3)
-a3.files.add(f4)
-a3.save()
-
-####################################
-
-from api.models import Assignment, Student, Classes, Teacher, DefFiles
-from datetime import datetime
-
-f1 = DefFiles(
- name="instructions.txt"
-)
-f1.save()
-f2 = DefFiles(
- name="instructions.txt"
-)
-f2.save()
-f3 = DefFiles(
- name="sample.txt"
-)
-f3.save()
-f4 = DefFiles(
- name="rubric.txt"
-)
-f4.save()
-
-A1 = Assignment(
- name='Week1_HW',
- due_date=datetime.now(),
-)
-A1.save()
-A1.files.add(f1)
-A1.save()
-
-A2 = Assignment(
- name='Week2_HW',
- due_date=datetime.now(),
-
-)
-A2.save()
-A2.files.add(f2)
-A2.save()
-
-A3 = Assignment(
- name='Journal1',
- due_date=datetime.now(),
-)
-A3.save()
-A3.files.add(f3)
-A3.files.add(f4)
-A3.save()
-
-#classes
-math = Classes(
- name='Math5',
-
-)
-math.save()
-math.assignments.add(A1)
-math.assignments.add(A2)
-math.save()
-
-english = Classes(
- name='English',
-)
-english.save()
-english.assignments.add(A3)
-english.save()
-
-#students
-raffu = Student(
- first_name = "Raffu",
- last_name = "Khondaker",
- student_id = 1579460,
- ion_user="2022rkhondak",
- webmail = "2022rkhondak@tjhsst.edu",
- grade = 10,
- repo="https://github.com/therealraffi/2022rkhondak.git",
-)
-raffu.save()
-raffu.classes.add(math)
-raffu.classes.add(english)
-raffu.save()
-
-#teachers
-ng = Teacher(
- first_name = "Errin",
- last_name = "Harris",
- ion_user="eharris1"
-)
-ng.save()
-ng.classes.add(math)
-ng.save()
-
-chao = Teacher(
- first_name = "Abagail",
- last_name = "Bailey",
- ion_user="AKBailey"
-)
-chao.save()
-chao.classes.add(english)
-chao.save()
+# from datetime import datetime
+#
+# f1 = DefFiles(
+# name="instructions.txt"
+# )
+# f1.save()
+# f2 = DefFiles(
+# name="instructions.txt"
+# )
+# f2.save()
+# f3 = DefFiles(
+# name="sample.txt"
+# )
+# f3.save()
+# f4 = DefFiles(
+# name="rubric.txt"
+# )
+# f4.save()
+#
+# a1 = Assignment.objects.get(pk=1)
+# a1.files.add(f1)
+# a1.save()
+# a2 = Assignment.objects.get(pk=2)
+# a2.files.add(f2)
+# a2.save()
+# a3 = Assignment.objects.get(pk=3)
+# a3.files.add(f3)
+# a3.files.add(f4)
+# a3.save()
+#
+# ####################################
+#
+# from api.models import Assignment, Student, Classes, Teacher, DefFiles
+# from datetime import datetime
+#
+# f1 = DefFiles(
+# name="instructions.txt"
+# )
+# f1.save()
+# f2 = DefFiles(
+# name="instructions.txt"
+# )
+# f2.save()
+# f3 = DefFiles(
+# name="sample.txt"
+# )
+# f3.save()
+# f4 = DefFiles(
+# name="rubric.txt"
+# )
+# f4.save()
+#
+# A1 = Assignment(
+# name='Week1_HW',
+# due_date=datetime.now(),
+# )
+# A1.save()
+# A1.files.add(f1)
+# A1.save()
+#
+# A2 = Assignment(
+# name='Week2_HW',
+# due_date=datetime.now(),
+#
+# )
+# A2.save()
+# A2.files.add(f2)
+# A2.save()
+#
+# A3 = Assignment(
+# name='Journal1',
+# due_date=datetime.now(),
+# )
+# A3.save()
+# A3.files.add(f3)
+# A3.files.add(f4)
+# A3.save()
+#
+# #classes
+# math = Classes(
+# name='Math5',
+#
+# )
+# math.save()
+# math.assignments.add(A1)
+# math.assignments.add(A2)
+# math.save()
+#
+# english = Classes(
+# name='English',
+# )
+# english.save()
+# english.assignments.add(A3)
+# english.save()
+#
+# #students
+# raffu = Student(
+# first_name = "Raffu",
+# last_name = "Khondaker",
+# student_id = 1579460,
+# ion_user="2022rkhondak",
+# webmail = "2022rkhondak@tjhsst.edu",
+# grade = 10,
+# repo="https://github.com/therealraffi/2022rkhondak.git",
+# )
+# raffu.save()
+# raffu.classes.add(math)
+# raffu.classes.add(english)
+# raffu.save()
+#
+# #teachers
+# ng = Teacher(
+# first_name = "Errin",
+# last_name = "Harris",
+# ion_user="eharris1"
+# )
+# ng.save()
+# ng.classes.add(math)
+# ng.save()
+#
+# chao = Teacher(
+# first_name = "Abagail",
+# last_name = "Bailey",
+# ion_user="AKBailey"
+# )
+# chao.save()
+# chao.classes.add(english)
+# chao.save()
diff --git a/Website/api/migrations/0001_initial.py b/Website/api/migrations/0001_initial.py
index 056367b..96b239b 100644
--- a/Website/api/migrations/0001_initial.py
+++ b/Website/api/migrations/0001_initial.py
@@ -1,6 +1,8 @@
-# Generated by Django 3.0.7 on 2020-06-12 01:34
+# Generated by Django 3.0.7 on 2020-06-14 19:14
+from django.conf import settings
from django.db import migrations, models
+import django.db.models.deletion
class Migration(migrations.Migration):
@@ -8,33 +10,10 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
+ migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
- migrations.CreateModel(
- name='Assignment',
- fields=[
- ('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
- ('due_date', models.DateTimeField()),
- ('files', models.CharField(blank=True, default='', max_length=100)),
- ('path', models.CharField(max_length=100)),
- ('classes', models.CharField(max_length=100)),
- ('teacher', models.CharField(max_length=100)),
- ],
- ),
- migrations.CreateModel(
- name='Classes',
- fields=[
- ('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
- ('repo', models.URLField(default='')),
- ('path', models.CharField(default='', max_length=100)),
- ('teacher', models.CharField(default='', max_length=100)),
- ('assignments', models.CharField(default='', max_length=100)),
- ('default_file', models.CharField(default='', max_length=100)),
- ('confirmed', models.TextField(blank=True, default='')),
- ('unconfirmed', models.TextField(blank=True, default='')),
- ],
- ),
migrations.CreateModel(
name='DefFiles',
fields=[
@@ -46,23 +25,6 @@ class Migration(migrations.Migration):
('teacher', models.CharField(max_length=100)),
],
),
- migrations.CreateModel(
- name='Student',
- fields=[
- ('created', models.DateTimeField(auto_now_add=True)),
- ('first_name', models.CharField(max_length=100)),
- ('last_name', models.CharField(max_length=100)),
- ('student_id', models.IntegerField()),
- ('ion_user', models.CharField(max_length=100, primary_key=True, serialize=False)),
- ('email', models.CharField(blank=True, default='', max_length=100)),
- ('grade', models.IntegerField()),
- ('git', models.CharField(max_length=100)),
- ('repo', models.URLField(blank=True, default='')),
- ('classes', models.CharField(blank=True, default='', max_length=100)),
- ('added_to', models.CharField(blank=True, default='', max_length=100)),
- ('completed', models.TextField(blank=True, default='')),
- ],
- ),
migrations.CreateModel(
name='Teacher',
fields=[
@@ -73,6 +35,41 @@ class Migration(migrations.Migration):
('ion_user', models.CharField(max_length=100, primary_key=True, serialize=False)),
('git', models.CharField(max_length=100)),
('email', models.CharField(blank=True, default='', max_length=100)),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Student',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('website', models.CharField(blank=True, default='https://google.com', max_length=150)),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Classes',
+ fields=[
+ ('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
+ ('repo', models.URLField(blank=True, default='')),
+ ('path', models.CharField(default='', max_length=100)),
+ ('teacher', models.CharField(default='', max_length=100)),
+ ('assignments', models.TextField(blank=True, default='')),
+ ('default_file', models.CharField(blank=True, default='', max_length=100)),
+ ('confirmed', models.TextField(blank=True, default='')),
+ ('unconfirmed', models.TextField(blank=True, default='')),
+ ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
+ ],
+ ),
+ migrations.CreateModel(
+ name='Assignment',
+ fields=[
+ ('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
+ ('due_date', models.DateTimeField()),
+ ('files', models.CharField(blank=True, default='', max_length=100)),
+ ('path', models.CharField(max_length=100)),
+ ('classes', models.CharField(max_length=100)),
+ ('teacher', models.CharField(max_length=100)),
+ ('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='assignments', to=settings.AUTH_USER_MODEL)),
],
),
]
diff --git a/Website/api/migrations/0002_auto_20200612_0135.py b/Website/api/migrations/0002_auto_20200612_0135.py
deleted file mode 100644
index 652eea2..0000000
--- a/Website/api/migrations/0002_auto_20200612_0135.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 3.0.7 on 2020-06-12 01:35
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0001_initial'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='assignment',
- name='name',
- field=models.CharField(max_length=100),
- ),
- migrations.AlterField(
- model_name='assignment',
- name='path',
- field=models.CharField(max_length=100, primary_key=True, serialize=False),
- ),
- ]
diff --git a/Website/api/migrations/0002_auto_20200614_2034.py b/Website/api/migrations/0002_auto_20200614_2034.py
new file mode 100644
index 0000000..f6c6f87
--- /dev/null
+++ b/Website/api/migrations/0002_auto_20200614_2034.py
@@ -0,0 +1,52 @@
+# Generated by Django 3.0.7 on 2020-06-14 20:34
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='student',
+ name='website',
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='added_to',
+ field=models.CharField(blank=True, default='', max_length=100),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='classes',
+ field=models.CharField(blank=True, default='', max_length=100),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='completed',
+ field=models.TextField(blank=True, default=''),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='git',
+ field=models.CharField(blank=True, default='https://github.com/', max_length=100),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='grade',
+ field=models.IntegerField(blank=True, default=9),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='repo',
+ field=models.URLField(blank=True, default=''),
+ ),
+ migrations.AddField(
+ model_name='student',
+ name='student_id',
+ field=models.IntegerField(blank=True, default=0),
+ ),
+ ]
diff --git a/Website/api/migrations/0003_auto_20200612_0135.py b/Website/api/migrations/0003_auto_20200612_0135.py
deleted file mode 100644
index 5b95bdd..0000000
--- a/Website/api/migrations/0003_auto_20200612_0135.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Generated by Django 3.0.7 on 2020-06-12 01:35
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0002_auto_20200612_0135'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='assignment',
- name='name',
- field=models.CharField(max_length=100, primary_key=True, serialize=False),
- ),
- migrations.AlterField(
- model_name='assignment',
- name='path',
- field=models.CharField(max_length=100),
- ),
- ]
diff --git a/Website/api/migrations/0003_auto_20200614_2044.py b/Website/api/migrations/0003_auto_20200614_2044.py
new file mode 100644
index 0000000..d5a7a69
--- /dev/null
+++ b/Website/api/migrations/0003_auto_20200614_2044.py
@@ -0,0 +1,43 @@
+# Generated by Django 3.0.7 on 2020-06-14 20:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0002_auto_20200614_2034'),
+ ]
+
+ operations = [
+ migrations.RemoveField(
+ model_name='student',
+ name='student_id',
+ ),
+ migrations.RemoveField(
+ model_name='teacher',
+ name='created',
+ ),
+ migrations.RemoveField(
+ model_name='teacher',
+ name='email',
+ ),
+ migrations.RemoveField(
+ model_name='teacher',
+ name='first_name',
+ ),
+ migrations.RemoveField(
+ model_name='teacher',
+ name='last_name',
+ ),
+ migrations.AlterField(
+ model_name='student',
+ name='git',
+ field=models.CharField(blank=True, default='', max_length=100),
+ ),
+ migrations.AlterField(
+ model_name='student',
+ name='grade',
+ field=models.IntegerField(blank=True),
+ ),
+ ]
diff --git a/Website/api/migrations/0004_auto_20200612_0813.py b/Website/api/migrations/0004_auto_20200612_0813.py
deleted file mode 100644
index c713dcc..0000000
--- a/Website/api/migrations/0004_auto_20200612_0813.py
+++ /dev/null
@@ -1,28 +0,0 @@
-# Generated by Django 3.0.7 on 2020-06-12 08:13
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('api', '0003_auto_20200612_0135'),
- ]
-
- operations = [
- migrations.AlterField(
- model_name='classes',
- name='assignments',
- field=models.TextField(blank=True, default=''),
- ),
- migrations.AlterField(
- model_name='classes',
- name='default_file',
- field=models.CharField(blank=True, default='', max_length=100),
- ),
- migrations.AlterField(
- model_name='classes',
- name='repo',
- field=models.URLField(blank=True, default=''),
- ),
- ]
diff --git a/Website/api/migrations/0004_auto_20200614_2107.py b/Website/api/migrations/0004_auto_20200614_2107.py
new file mode 100644
index 0000000..75e2a7c
--- /dev/null
+++ b/Website/api/migrations/0004_auto_20200614_2107.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.7 on 2020-06-14 21:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('api', '0003_auto_20200614_2044'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='student',
+ name='grade',
+ field=models.IntegerField(blank=True, default=0),
+ ),
+ ]
diff --git a/Website/api/models.py b/Website/api/models.py
index 6c8cb7d..e8bb2b3 100644
--- a/Website/api/models.py
+++ b/Website/api/models.py
@@ -1,4 +1,5 @@
from django.db import models
+from django.contrib.auth.models import User
class DefFiles(models.Model):
name=models.CharField(max_length=100)
@@ -8,6 +9,8 @@ class DefFiles(models.Model):
teacher=models.CharField(max_length=100)
class Assignment(models.Model):
+ owner = models.ForeignKey('auth.User', related_name='assignments', on_delete=models.CASCADE)
+
name=models.CharField(max_length=100, primary_key=True)
due_date=models.DateTimeField()
# files = models.ManyToManyField(DefFiles)
@@ -19,6 +22,8 @@ class Assignment(models.Model):
return '%s' % (self.name)
class Classes(models.Model):
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
+
name = models.CharField(primary_key=True, max_length=100)
repo=models.URLField(default="", blank=True)
path=models.CharField(max_length=100, default="")
@@ -34,31 +39,26 @@ class Classes(models.Model):
return super(Classes, self).save(*args, **kwargs)
class Teacher(models.Model):
- created = models.DateTimeField(auto_now_add=True)
- first_name = models.CharField(max_length=100)
- last_name = models.CharField(max_length=100)
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
# classes = models.ManyToManyField(Classes, default="")
classes=models.CharField(max_length=100, default="", blank=True)
ion_user=models.CharField(primary_key=True, max_length=100)
git=models.CharField(max_length=100)
- email=models.CharField(max_length=100, default="", blank=True)
+
+ def save(self, *args, **kwargs):
+ super(Teacher, self).save(*args, **kwargs)
class Student(models.Model):
- created = models.DateTimeField(auto_now_add=True)
- first_name = models.CharField(max_length=100)
- last_name = models.CharField(max_length=100)
- student_id = models.IntegerField()
- ion_user=models.CharField(primary_key=True, max_length=100)
- email=models.CharField(max_length=100, default="", blank=True)
- grade = models.IntegerField()
- git=models.CharField(max_length=100)
+ user = models.OneToOneField(User, on_delete=models.CASCADE)
+ grade = models.IntegerField(default=0, blank=True)
+ git=models.CharField(default="", max_length=100, blank=True)
repo=models.URLField(default="", blank=True)
classes=models.CharField(max_length=100, default="", blank=True)
added_to=models.CharField(max_length=100, default="", blank=True)
completed=models.TextField(default="", blank=True)
-
+
def save(self, *args, **kwargs):
- return super(Student, self).save(*args, **kwargs)
-
-
+ super(Student, self).save(*args, **kwargs)
+ def __str__(self):
+ return f"{self.user.username}'s Profile"
diff --git a/Website/api/permissions.py b/Website/api/permissions.py
new file mode 100644
index 0000000..2d64429
--- /dev/null
+++ b/Website/api/permissions.py
@@ -0,0 +1,25 @@
+from rest_framework import permissions
+
+
+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 or request.user.is_superuser
+
+class isTeacher(permissions.BasePermission):
+ #only teachers can make classes and assignmenst
+ def has_object_permission(self, request, view, obj):
+ if request.method in permissions.SAFE_METHODS:
+ return True
+
+ # Write permissions are only allowed to the owner of the snippet.
+ return request.user.groups.filter(name__in=['teachers']).exists() or request.user.is_superuser
diff --git a/Website/api/serializers.py b/Website/api/serializers.py
index 0ff5ae6..2a05750 100644
--- a/Website/api/serializers.py
+++ b/Website/api/serializers.py
@@ -1,37 +1,55 @@
from django.contrib.auth.models import User, Group
from .models import Student, Teacher, Classes, Assignment, DefFiles
from rest_framework import serializers, permissions
+from django.contrib.auth.models import User
+from .permissions import IsOwnerOrReadOnly,isTeacher
+
+class UserSerializer(serializers.HyperlinkedModelSerializer):
+ students = serializers.PrimaryKeyRelatedField(many=True, queryset=Student.objects.all())
+ teachers = serializers.PrimaryKeyRelatedField(many=True, queryset=Teacher.objects.all())
-class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
class Meta:
- model = DefFiles
- fields = ['name', 'path','assignment','classes', "teacher",'url', 'id']
+ model = User
+ fields = ['id', 'username']
+
+# class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
+# class Meta:
+# model = DefFiles
+# fields = ['name', 'path','assignment','classes', "teacher",'url', 'id']
class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
#permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
# files = DefFilesSerializer(many=True, read_only=True,allow_null=True)
+ owner = serializers.ReadOnlyField(source='owner.username')
+
class Meta:
model = Assignment
- fields = ['url','name', 'due_date', 'path' , "classes","teacher"]
+ # fields = ['url','name', 'due_date', 'path' , "classes","teacher",'owner']
+ fields = ['name', 'due_date', 'path' , "classes","teacher",'owner']
class ClassesSerializer(serializers.HyperlinkedModelSerializer):
# assignments = AssignmentSerializer(many=True, read_only=True,allow_null=True)
# default_file=DefFilesSerializer(many=True, read_only=True,allow_null=True)
+ owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Classes
- fields = ['url', 'name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed']
+ # fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner']
+ fields = ['name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner']
class StudentSerializer(serializers.HyperlinkedModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
+ owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Student
- fields = ['url', 'first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo']
+ # fields = ['url','first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo','owner']
+ fields = ['first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo','owner']
class TeacherSerializer(serializers.ModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
+ owner = serializers.ReadOnlyField(source='owner.username')
class Meta:
model = Teacher
- fields = ['url', 'first_name', 'last_name','git','ion_user', 'email','classes']
+ # fields = ['url','first_name', 'last_name','git','ion_user', 'email','classes','owner']
+ fields = ['first_name', 'last_name','git','ion_user', 'email','classes','owner']
diff --git a/Website/api/signals.py b/Website/api/signals.py
new file mode 100644
index 0000000..fe8deab
--- /dev/null
+++ b/Website/api/signals.py
@@ -0,0 +1,5 @@
+from django.contrib.auth.models import User
+from django.db.models.signals import post_save
+from django.dispatch import receiver
+from .models import Student, Teacher
+)
diff --git a/Website/api/urls.py b/Website/api/urls.py
index e69de29..f130d15 100644
--- a/Website/api/urls.py
+++ b/Website/api/urls.py
@@ -0,0 +1,16 @@
+from django.urls import path
+from rest_framework.urlpatterns import format_suffix_patterns
+from . import views
+
+urlpatterns = [
+ path('students/', views.StudentList.as_view()),
+ path('students/
/', views.StudentDetail.as_view()),
+ path('teachers/', views.TeacherList.as_view()),
+ path('teachers//', views.TeacherDetail.as_view()),
+ path('assignments/', views.AssignmentList.as_view()),
+ path('assignments//', views.AssignmentDetail.as_view()),
+ path('classes/', views.ClassesList.as_view()),
+ path('classes//', views.ClassesDetail.as_view()),
+]
+
+urlpatterns = format_suffix_patterns(urlpatterns)
\ No newline at end of file
diff --git a/Website/api/views-back.py b/Website/api/views-back.py
index 5c936f9..011d81a 100644
--- a/Website/api/views-back.py
+++ b/Website/api/views-back.py
@@ -1,131 +1,89 @@
-# class StudentList(APIView):
-# """
-# List all snippets, or create a new snippet.
-# """
-# def get(self, request, format=None):
-# snippets = Student.objects.all()
-# serializer = StudentSerializer(snippets, many=True)
-# return response.Response(serializer.data)
+from .models import Student, Teacher, Classes, Assignment, DefFiles
+from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer
+from rest_framework import generics, viewsets, permissions, response, status
+from django.http import Http404
+from rest_framework.views import APIView
+from django.contrib.auth.models import User
+from .permissions import isTeacher, IsOwnerOrReadOnly
+from django.shortcuts import render, redirect
+from rest_framework.parsers import JSONParser
+from django.http.response import JsonResponse
+from rest_framework.response import Response
+from rest_framework import mixins
-# def post(self, request, format=None):
-# serializer = StudentSerializer(data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data, status=status.HTTP_201_CREATED)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-# class StudentDetail(APIView):
-# """
-# Retrieve, update or delete a snippet instance.
-# """
-# def get_object(self, pk):
-# try:
-# return Student.objects.get(pk=pk)
-# except Student.DoesNotExist:
-# raise Http404
+class StudentList(generics.ListCreateAPIView):
+ queryset = Student.objects.all()
+ serializer_class = StudentSerializer
+ def perform_create(self, serializer):
+ serializer.save(owner=self.request.user)
-# def get(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = StudentSerializer(snippet)
-# return response.Response(serializer.data)
+class StudentDetail(generics.RetrieveAPIView):
+ queryset = Student.objects.all()
+ serializer_class = StudentSerializer
+ permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
-# def put(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = StudentSerializer(snippet, data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+class TeacherList(generics.ListCreateAPIView):
+ queryset = Teacher.objects.all()
+ serializer_class = TeacherSerializer
+ def perform_create(self, serializer):
+ if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
+ serializer.save(owner=self.request.user)
+ else:
+ print("UNAUTHORIZED POST")
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-# def delete(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# snippet.delete()
-# return response.Response(status=status.HTTP_204_NO_CONTENT)
+class TeacherDetail(generics.RetrieveAPIView):
+ queryset = Teacher.objects.all()
+ serializer_class = TeacherSerializer
+ permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
-# class TeacherList(APIView):
-# """
-# List all snippets, or create a new snippet.
-# """
-# def get(self, request, format=None):
-# snippets = Teacher.objects.all()
-# serializer = TeacherSerializer(snippets, many=True)
-# return response.Response(serializer.data)
-
-# def post(self, request, format=None):
-# serializer = TeacherSerializer(data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data, status=status.HTTP_201_CREATED)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-
-# class TeacherDetail(APIView):
-# """
-# Retrieve, update or delete a snippet instance.
-# """
-# def get_object(self, pk):
-# try:
-# return Teacher.objects.get(pk=pk)
-# except Teacher.DoesNotExist:
-# raise Http404
-
-# def get(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = TeacherSerializer(snippet)
-# return response.Response(serializer.data)
-
-# def put(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = TeacherSerializer(snippet, data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-
-# def delete(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# snippet.delete()
-# return response.Response(status=status.HTTP_204_NO_CONTENT)
-# class ClassesList(APIView):
-# """
-# List all snippets, or create a new snippet.
-# """
-# def get(self, request, format=None):
-# snippets = Classes.objects.all()
-# serializer = ClassesSerializer(snippets, many=True)
-# return response.Response(serializer.data)
+class ClassesList(generics.ListCreateAPIView):
+ queryset = Classes.objects.all()
+ serializer_class = ClassesSerializer
+ #permissions_classes = [isTeacher]
+ def perform_create(self, serializer):
+ if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
+ serializer.save(owner=self.request.user)
+ else:
+ print("UNAUTHORIZED POST")
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
-# def post(self, request, format=None):
-# serializer = ClassesSerializer(data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data, status=status.HTTP_201_CREATED)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+# class ClassesDetail(generics.RetrieveAPIView):
+# queryset = Classes.objects.all()
+# serializer_class = ClassesSerializer
+# # permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
-# class ClassesDetail(APIView):
-# """
-# Retrieve, update or delete a snippet instance.
-# """
-# def get_object(self, pk):
-# try:
-# return Classes.objects.get(pk=pk)
-# except Classes.DoesNotExist:
-# raise Http404
+class ClassesDetail(mixins.RetrieveModelMixin,
+ mixins.UpdateModelMixin,
+ mixins.DestroyModelMixin,
+ generics.GenericAPIView):
+ queryset = Classes.objects.all()
+ serializer_class = ClassesSerializer
-# def get(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = ClassesSerializer(snippet)
-# return response.Response(serializer.data)
+ def get(self, request, *args, **kwargs):
+ return self.retrieve(request, *args, **kwargs)
-# def put(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# serializer = ClassesSerializer(snippet, data=request.data)
-# if serializer.is_valid():
-# serializer.save()
-# return response.Response(serializer.data)
-# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+ def put(self, request, *args, **kwargs):
+ print(self.owner)
+ if(request.user == self.owner):
+ return self.update(request, *args, **kwargs)
-# def delete(self, request, pk, format=None):
-# snippet = self.get_object(pk)
-# snippet.delete()
-# return response.Response(status=status.HTTP_204_NO_CONTENT)
\ No newline at end of file
+ def delete(self, request, *args, **kwargs):
+ return self.destroy(request, *args, **kwargs)
+
+class AssignmentList(generics.ListCreateAPIView):
+ queryset = Assignment.objects.all()
+ serializer_class = AssignmentSerializer
+ def perform_create(self, serializer):
+ if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
+ serializer.save(owner=self.request.user)
+ else:
+ print("UNAUTHORIZED POST")
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+class AssignmentDetail(generics.RetrieveAPIView):
+ queryset = Assignment.objects.all()
+ serializer_class = AssignmentSerializer
+ permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
diff --git a/Website/api/views.py b/Website/api/views.py
index 439c30b..3876c0a 100644
--- a/Website/api/views.py
+++ b/Website/api/views.py
@@ -1,8 +1,21 @@
from .models import Student, Teacher, Classes, Assignment, DefFiles
-from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, DefFilesSerializer
+from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer
from rest_framework import generics, viewsets, permissions, response, status
from django.http import Http404
from rest_framework.views import APIView
+from django.contrib.auth.models import User
+from .permissions import isTeacher, IsOwnerOrReadOnly
+from django.shortcuts import render, redirect
+from rest_framework.parsers import JSONParser
+from rest_framework.response import Response
+
+
+
+class UserViewSet(viewsets.ModelViewSet):
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
+ permission_classes = [permissions.IsAuthenticated]
+
class StudentViewSet(viewsets.ModelViewSet):
"""
@@ -10,8 +23,10 @@ class StudentViewSet(viewsets.ModelViewSet):
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
+ permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
+ def perform_create(self, serializer):
+ serializer.save(owner=self.request.user)
class TeacherViewSet(viewsets.ModelViewSet):
"""
@@ -19,8 +34,10 @@ class TeacherViewSet(viewsets.ModelViewSet):
"""
queryset = Teacher.objects.all()
serializer_class = TeacherSerializer
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
+ permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
+ def perform_create(self, serializer):
+ serializer.save(owner=self.request.user)
class ClassesViewSet(viewsets.ModelViewSet):
"""
@@ -28,7 +45,14 @@ class ClassesViewSet(viewsets.ModelViewSet):
"""
queryset = Classes.objects.all()
serializer_class = ClassesSerializer
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
+ permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
+
+ def perform_create(self, serializer):
+ if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
+ serializer.save(owner=self.request.user)
+ else:
+ print("UNAUTHORIZED POST")
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class AssignmentViewSet(viewsets.ModelViewSet):
@@ -37,12 +61,19 @@ class AssignmentViewSet(viewsets.ModelViewSet):
"""
queryset = Assignment.objects.all()
serializer_class = AssignmentSerializer
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
+ permission_classes = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly]
-class DefFilesViewSet(viewsets.ModelViewSet):
- """
- API endpoint that allows users to be viewed or edited.
- """
- queryset = DefFiles.objects.all()
- serializer_class = DefFilesSerializer
- permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
+ def perform_create(self, serializer):
+ if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
+ serializer.save(owner=self.request.user)
+ else:
+ print("UNAUTHORIZED POST")
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
+
+# class DefFilesViewSet(viewsets.ModelViewSet):
+# """
+# API endpoint that allows users to be viewed or edited.
+# """
+# queryset = DefFiles.objects.all()
+# serializer_class = DefFilesSerializer
+# permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
diff --git a/CLI/.profile b/Website/config/__init__.py
similarity index 100%
rename from CLI/.profile
rename to Website/config/__init__.py
diff --git a/Website/skoolos/asgi.py b/Website/config/asgi.py
similarity index 82%
rename from Website/skoolos/asgi.py
rename to Website/config/asgi.py
index 9577b84..561756d 100644
--- a/Website/skoolos/asgi.py
+++ b/Website/config/asgi.py
@@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'skoolos.settings')
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_asgi_application()
diff --git a/Website/skoolos/settings.py b/Website/config/settings.py
similarity index 94%
rename from Website/skoolos/settings.py
rename to Website/config/settings.py
index b099675..17603a8 100644
--- a/Website/skoolos/settings.py
+++ b/Website/config/settings.py
@@ -31,6 +31,7 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
+ 'skoolos.apps.SkoolosConfig',
'users.apps.UsersConfig',
'django.contrib.admin',
'django.contrib.auth',
@@ -41,8 +42,7 @@ INSTALLED_APPS = [
'rest_framework',
'api',
'crispy_forms',
-
-
+ 'django_forms_bootstrap',
]
REST_FRAMEWORK = {
@@ -63,7 +63,7 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
-ROOT_URLCONF = 'skoolos.urls'
+ROOT_URLCONF = 'config.urls'
TEMPLATES = [
{
@@ -81,7 +81,7 @@ TEMPLATES = [
},
]
-WSGI_APPLICATION = 'skoolos.wsgi.application'
+WSGI_APPLICATION = 'config.wsgi.application'
# Database
@@ -135,4 +135,6 @@ STATIC_URL = '/static/'
CRISPY_TEMPLATE_PACK = 'bootstrap4'
-LOGIN_REDIRECT_URL = '/'
\ No newline at end of file
+LOGIN_REDIRECT_URL = '/'
+
+LOGIN_URL = '/login'
diff --git a/Website/config/urls.py b/Website/config/urls.py
new file mode 100644
index 0000000..420beb6
--- /dev/null
+++ b/Website/config/urls.py
@@ -0,0 +1,31 @@
+from django.urls import path
+from rest_framework import routers
+from api import views as api_views
+from django.contrib import admin
+from django.conf.urls import include
+from django.contrib.auth import views as auth_views
+
+router = routers.DefaultRouter()
+router.register(r'students', api_views.StudentViewSet)
+router.register(r'teachers', api_views.TeacherViewSet)
+router.register(r'assignments', api_views.AssignmentViewSet)
+router.register(r'classes', api_views.ClassesViewSet)
+# router.register(r'files', api_views.DefFilesViewSet)
+router.register(r'users', api_views.UserViewSet)
+
+from users import views as user_views
+from users.forms import LoginForm
+
+# Wire up our API using automatic URL routing.
+# Additionally, we include login URLs for the browsable API.
+urlpatterns = [
+ path('', include('skoolos.urls')),
+ path('api/', include(router.urls)),
+ path('api-auth/', include('rest_framework.urls')),
+ path('admin/', admin.site.urls),
+ path('login/', auth_views.LoginView.as_view(template_name='users/login.html', authentication_form=LoginForm), name='login'),
+ path('logout/', user_views.logout, name='logout'),
+ path('register/', user_views.register, name='register'),
+ path('create_account/', user_views.create_account, name='create_account'),
+ path('callback/', user_views.callback, name='callback'),
+]
diff --git a/Website/skoolos/wsgi.py b/Website/config/wsgi.py
similarity index 82%
rename from Website/skoolos/wsgi.py
rename to Website/config/wsgi.py
index f17107f..6b29610 100644
--- a/Website/skoolos/wsgi.py
+++ b/Website/config/wsgi.py
@@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application
-os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'skoolos.settings')
+os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_wsgi_application()
diff --git a/Website/manage.py b/Website/manage.py
index f17dda4..58c5f10 100755
--- a/Website/manage.py
+++ b/Website/manage.py
@@ -5,7 +5,7 @@ import sys
def main():
- os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'skoolos.settings')
+ os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
diff --git a/Website/skoolos/admin.py b/Website/skoolos/admin.py
new file mode 100644
index 0000000..8c38f3f
--- /dev/null
+++ b/Website/skoolos/admin.py
@@ -0,0 +1,3 @@
+from django.contrib import admin
+
+# Register your models here.
diff --git a/Website/skoolos/apps.py b/Website/skoolos/apps.py
new file mode 100644
index 0000000..6d65d67
--- /dev/null
+++ b/Website/skoolos/apps.py
@@ -0,0 +1,5 @@
+from django.apps import AppConfig
+
+
+class SkoolosConfig(AppConfig):
+ name = 'skoolos'
diff --git a/Website/skoolos/models.py b/Website/skoolos/models.py
new file mode 100644
index 0000000..71a8362
--- /dev/null
+++ b/Website/skoolos/models.py
@@ -0,0 +1,3 @@
+from django.db import models
+
+# Create your models here.
diff --git a/Website/skoolos/static/skoolos/Segoe UI Bold Italic.ttf b/Website/skoolos/static/skoolos/Segoe UI Bold Italic.ttf
new file mode 100644
index 0000000..d134de8
Binary files /dev/null and b/Website/skoolos/static/skoolos/Segoe UI Bold Italic.ttf differ
diff --git a/Website/skoolos/static/skoolos/Segoe UI Bold.ttf b/Website/skoolos/static/skoolos/Segoe UI Bold.ttf
new file mode 100644
index 0000000..5723e8b
Binary files /dev/null and b/Website/skoolos/static/skoolos/Segoe UI Bold.ttf differ
diff --git a/Website/skoolos/static/skoolos/Segoe UI Italic.ttf b/Website/skoolos/static/skoolos/Segoe UI Italic.ttf
new file mode 100644
index 0000000..07fdf85
Binary files /dev/null and b/Website/skoolos/static/skoolos/Segoe UI Italic.ttf differ
diff --git a/Website/skoolos/static/skoolos/Segoe UI.ttf b/Website/skoolos/static/skoolos/Segoe UI.ttf
new file mode 100644
index 0000000..46b3b99
Binary files /dev/null and b/Website/skoolos/static/skoolos/Segoe UI.ttf differ
diff --git a/Website/skoolos/static/skoolos/futura.ttf b/Website/skoolos/static/skoolos/futura.ttf
new file mode 100644
index 0000000..1ef199e
Binary files /dev/null and b/Website/skoolos/static/skoolos/futura.ttf differ
diff --git a/Website/skoolos/static/skoolos/styles.css b/Website/skoolos/static/skoolos/styles.css
new file mode 100644
index 0000000..8eb8163
--- /dev/null
+++ b/Website/skoolos/static/skoolos/styles.css
@@ -0,0 +1,100 @@
+@font-face {
+ font-family: Futura;
+ src: url(futura.ttf);
+}
+
+@font-face {
+ font-family: 'Segoe UI';
+ src: url('Segoe UI.ttf');
+}
+
+body {
+ background: #fafafa;
+ color: #333333;
+ margin-top: 5rem;
+ font-family: 'Segoe UI';
+}
+
+h1, h2, h3, h4, h5, h6 {
+ color: #444444;
+}
+
+ul {
+ margin: 0;
+}
+
+.bg-steel {
+ background: #3cba54;
+}
+
+.site-header .navbar-nav .nav-link {
+ color: #cbd5db;
+}
+
+.site-header .navbar-nav .nav-link:hover {
+ color: #ffffff;
+}
+
+.site-header .navbar-nav .nav-link.active {
+ font-weight: 500;
+}
+
+.content-section {
+ background: #ffffff;
+ padding: 10px 20px;
+ border: 1px solid #dddddd;
+ border-radius: 3px;
+ margin-bottom: 20px;
+}
+
+.article-title {
+ color: #444444;
+}
+
+a.article-title:hover {
+ color: #428bca;
+ text-decoration: none;
+}
+
+.article-content {
+ white-space: pre-line;
+}
+
+.article-img {
+ height: 65px;
+ width: 65px;
+ margin-right: 16px;
+}
+
+.article-metadata {
+ padding-bottom: 1px;
+ margin-bottom: 4px;
+ border-bottom: 1px solid #e3e3e3
+}
+
+.article-metadata a:hover {
+ color: #333;
+ text-decoration: none;
+}
+
+.article-svg {
+ width: 25px;
+ height: 25px;
+ vertical-align: middle;
+}
+
+.account-img {
+ height: 125px;
+ width: 125px;
+ margin-right: 20px;
+ margin-bottom: 16px;
+}
+
+.account-heading {
+ font-size: 2.5rem;
+}
+
+.nounderline {
+ text-decoration: none !important;
+ color: black !important;
+}
diff --git a/Website/skoolos/templates/skoolos/base.html b/Website/skoolos/templates/skoolos/base.html
new file mode 100644
index 0000000..ce0d628
--- /dev/null
+++ b/Website/skoolos/templates/skoolos/base.html
@@ -0,0 +1,52 @@
+{% load static %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ SkoolOS
+
+
+
+
+
+ {% block content %}{% endblock %}
+
+
+
+
+
+
diff --git a/Website/skoolos/templates/skoolos/home.html b/Website/skoolos/templates/skoolos/home.html
new file mode 100644
index 0000000..05a211e
--- /dev/null
+++ b/Website/skoolos/templates/skoolos/home.html
@@ -0,0 +1,3 @@
+{% extends "skoolos/base.html" %}
+{% block content %}
+{% endblock content %}
diff --git a/Website/skoolos/tests.py b/Website/skoolos/tests.py
new file mode 100644
index 0000000..7ce503c
--- /dev/null
+++ b/Website/skoolos/tests.py
@@ -0,0 +1,3 @@
+from django.test import TestCase
+
+# Create your tests here.
diff --git a/Website/skoolos/urls.py b/Website/skoolos/urls.py
index a1e34a3..a8ffe34 100644
--- a/Website/skoolos/urls.py
+++ b/Website/skoolos/urls.py
@@ -1,23 +1,9 @@
from django.urls import path
-from rest_framework import routers
-from api import views as api_views
-from django.contrib import admin
-from django.conf.urls import include
-from django.contrib.auth import views as auth_views
-router = routers.DefaultRouter()
-router.register(r'students', api_views.StudentViewSet)
-router.register(r'teachers', api_views.TeacherViewSet)
-router.register(r'assignments', api_views.AssignmentViewSet)
-router.register(r'classes', api_views.ClassesViewSet)
-router.register(r'files', api_views.DefFilesViewSet)
+from . import views
-
-# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
- path('api/', include(router.urls)),
- path('api-auth/', include('rest_framework.urls')),
- path('admin/', admin.site.urls),
- path('login/', auth_views.LoginView.as_view(template_name="users/login.html"), name='login')
-]
\ No newline at end of file
+ path('', views.home, name='home'),
+ path('profile/', views.profile, name='profile')
+]
diff --git a/Website/skoolos/views.py b/Website/skoolos/views.py
new file mode 100644
index 0000000..3a3409b
--- /dev/null
+++ b/Website/skoolos/views.py
@@ -0,0 +1,12 @@
+from django.shortcuts import render
+from django.contrib.auth.decorators import login_required
+
+# Create your views here.
+
+@login_required()
+def home (request):
+ return render(request, "skoolos/home.html")
+
+@login_required()
+def profile (request):
+ pass
diff --git a/Website/skoolsite/urls.py b/Website/skoolsite/urls.py
deleted file mode 100644
index e69de29..0000000
diff --git a/Website/users/admin.py b/Website/users/admin.py
index 8c38f3f..73093bd 100644
--- a/Website/users/admin.py
+++ b/Website/users/admin.py
@@ -1,3 +1,5 @@
from django.contrib import admin
+from .models import Token
# Register your models here.
+admin.site.register(Token)
diff --git a/Website/users/forms.py b/Website/users/forms.py
new file mode 100644
index 0000000..7f4a2f1
--- /dev/null
+++ b/Website/users/forms.py
@@ -0,0 +1,32 @@
+from django import forms
+from django.contrib.auth.models import User
+from django.contrib.auth.forms import AuthenticationForm
+
+
+class LoginForm(AuthenticationForm):
+ username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Username'}))
+ password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder':'Password'}))
+
+class UserCreationForm(forms.ModelForm):
+
+ username = forms.CharField(disabled=True)
+ email = forms.EmailField(disabled=True)
+ first_name = forms.CharField(disabled=True)
+ last_name = forms.CharField(disabled=True)
+ isStudent = forms.BooleanField(widget = forms.HiddenInput())
+ git = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'Git Username'}))
+ password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Password'}))
+ confirm_password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'Confirm Password'}))
+ token = forms.CharField(widget = forms.HiddenInput())
+
+ def __init__(self, *args, **kwargs):
+ super(UserCreationForm, self).__init__(*args, **kwargs)
+
+ def clean(self):
+ cleaned_data = super(UserCreationForm, self).clean()
+
+ return cleaned_data
+
+ class Meta:
+ model = User
+ fields = ('username', 'email', 'first_name', 'last_name', 'git', 'password', 'confirm_password')
diff --git a/Website/users/migrations/0001_initial.py b/Website/users/migrations/0001_initial.py
new file mode 100644
index 0000000..1c06dee
--- /dev/null
+++ b/Website/users/migrations/0001_initial.py
@@ -0,0 +1,26 @@
+# Generated by Django 3.0.7 on 2020-06-14 19:13
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ initial = True
+
+ dependencies = [
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Token',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('username', models.TextField()),
+ ('email', models.TextField()),
+ ('first_name', models.TextField()),
+ ('last_name', models.TextField()),
+ ('isStudent', models.BooleanField()),
+ ('token', models.CharField(max_length=255)),
+ ],
+ ),
+ ]
diff --git a/Website/users/migrations/0002_auto_20200614_2044.py b/Website/users/migrations/0002_auto_20200614_2044.py
new file mode 100644
index 0000000..2f6941c
--- /dev/null
+++ b/Website/users/migrations/0002_auto_20200614_2044.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.7 on 2020-06-14 20:44
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='token',
+ name='isStudent',
+ field=models.BooleanField(default=True),
+ ),
+ ]
diff --git a/Website/users/migrations/0003_token_grade.py b/Website/users/migrations/0003_token_grade.py
new file mode 100644
index 0000000..4b0788c
--- /dev/null
+++ b/Website/users/migrations/0003_token_grade.py
@@ -0,0 +1,18 @@
+# Generated by Django 3.0.7 on 2020-06-14 21:07
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('users', '0002_auto_20200614_2044'),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name='token',
+ name='grade',
+ field=models.IntegerField(default=9),
+ ),
+ ]
diff --git a/Website/users/models.py b/Website/users/models.py
index 71a8362..3dcdefa 100644
--- a/Website/users/models.py
+++ b/Website/users/models.py
@@ -1,3 +1,22 @@
from django.db import models
+from uuid import uuid4
+
# Create your models here.
+
+class Token(models.Model):
+ username = models.TextField()
+ email = models.TextField()
+ first_name = models.TextField()
+ last_name = models.TextField()
+ grade = models.IntegerField(default=9)
+ isStudent = models.BooleanField(default=True)
+ token = models.CharField(max_length=255)
+
+ def save(self, *args, **kwargs):
+ if not self.token:
+ self.token = uuid4()
+ return super(Token, self).save(*args, **kwargs)
+
+ def __str__(self):
+ return f"{self.username}'s Token";
diff --git a/Website/users/pwd.py b/Website/users/pwd.py
new file mode 100644
index 0000000..a91574a
--- /dev/null
+++ b/Website/users/pwd.py
@@ -0,0 +1,6 @@
+import os
+
+pwd = "heyyy"
+path = os.getcwd()
+p = os.path.join(path, '../../', 'pwd.txt')
+open(p, 'w')
\ No newline at end of file
diff --git a/Website/users/static/users/styles.css b/Website/users/static/users/styles.css
index 7aa3c45..f0b3e1c 100644
--- a/Website/users/static/users/styles.css
+++ b/Website/users/static/users/styles.css
@@ -99,6 +99,10 @@ body {
-moz-osx-font-smoothing: grayscale;
}
+input:disabled {
+ background: #d9d9d9;
+}
+
.errorlist {
-}
\ No newline at end of file
+}
diff --git a/Website/users/templates/users/base.html b/Website/users/templates/users/base.html
index f4dd9e6..f621b1e 100644
--- a/Website/users/templates/users/base.html
+++ b/Website/users/templates/users/base.html
@@ -18,7 +18,6 @@
{% block content %}{% endblock %}
-a
diff --git a/Website/users/templates/users/create_account.html b/Website/users/templates/users/create_account.html
new file mode 100644
index 0000000..f3f814d
--- /dev/null
+++ b/Website/users/templates/users/create_account.html
@@ -0,0 +1,22 @@
+{% extends "users/base.html" %}
+{% load bootstrap_tags %}
+
+{% block content %}
+
+{% endblock %}
diff --git a/Website/users/templates/users/login.html b/Website/users/templates/users/login.html
index 9f71406..185c43b 100644
--- a/Website/users/templates/users/login.html
+++ b/Website/users/templates/users/login.html
@@ -1,16 +1,38 @@
{% extends "users/base.html" %}
-{% load crispy_forms_tags %}
+{% load bootstrap_tags %}
{% block content %}
-
-{% endblock %}
\ No newline at end of file
+{% endblock %}
diff --git a/Website/users/templates/users/register.html b/Website/users/templates/users/register.html
index aefb3cb..2712f93 100644
--- a/Website/users/templates/users/register.html
+++ b/Website/users/templates/users/register.html
@@ -3,13 +3,20 @@
{% block content %}