Merge pull request #5 from Rushilwiz/development

Merging Development
This commit is contained in:
Rushil Umaretiya 2020-06-14 18:44:36 -04:00 committed by GitHub
commit fdb34d61de
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
78 changed files with 1649 additions and 472 deletions

3
.gitignore vendored
View File

@ -246,6 +246,9 @@ Control.ca-bundle
Control.system-ca-bundle Control.system-ca-bundle
GitHub.sublime-settings GitHub.sublime-settings
#SkoolOS
*.profile
# Visual Studio Code # # Visual Studio Code #
.vscode/* .vscode/*
!.vscode/settings.json !.vscode/settings.json

View File

@ -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': []}

View File

@ -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()

View File

@ -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()

19
BackgroundService/test.py Normal file
View File

@ -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

View File

@ -5,4 +5,144 @@ import os
import argparse import argparse
'''
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))

View File

@ -14,7 +14,7 @@
</head> </head>
<body> <body>
<div class="d-flex align-items-center justify-content-center" style="height: 100vh"> <div class="d-flex align-items-center justify-content-center" style="height: 100vh">
<a href="https://ion.tjhsst.edu/oauth/authorize/?response_type=code&client_id=QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2F&scope=read&state=81xYFv6S9CLi7laXQ64gJWskDJUMMb" title="Ion" class="border border-dark p-3 btn btn-lg mx-auto" style="box-shadow: 5px 10px;"> <a href="https://ion.tjhsst.edu/oauth/authorize/?response_type=code&client_id=QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6&redirect_uri=http%3A%2F%2Flocalhost%3A8000%2Fcallback%2F&scope=read&state=yPblNZvC39bYCruLcVibEUzLjXkwaJ" title="Ion" class="border border-dark p-3 btn btn-lg mx-auto" style="box-shadow: 5px 10px;">
<img src="https://ion.tjhsst.edu/static/img/favicon.png"> <img src="https://ion.tjhsst.edu/static/img/favicon.png">
Sign in with Ion Sign in with Ion
</a> </a>

View File

@ -1,6 +1,5 @@
import sys import sys
from urllib.parse import urlparse from urllib.parse import urlparse
import requests import requests
from requests_oauthlib import OAuth2Session from requests_oauthlib import OAuth2Session
from selenium import webdriver from selenium import webdriver
@ -11,10 +10,15 @@ import socketserver
from threading import Thread from threading import Thread
from werkzeug.urls import url_decode from werkzeug.urls import url_decode
import pprint import pprint
from PyInquirer import prompt, print_json
import json
import os
import argparse
from cryptography.fernet import Fernet
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6' client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY' client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
redirect_uri = 'http://localhost:8000/' redirect_uri = 'http://localhost:8000/callback/'
token_url = 'https://ion.tjhsst.edu/oauth/token/' token_url = 'https://ion.tjhsst.edu/oauth/token/'
scope = ["read"] scope = ["read"]
@ -30,16 +34,21 @@ def main():
print("") print("")
if not os.path.exists(".profile"): if not os.path.exists(".profile"):
print(76546789876545678765) input("Welcome to SkoolOS. Press any key to create an account")
authenticate() authenticate()
print(open(".profile", "r").read())
else: 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: # while True:
# pass # pass
def authenticate(): def authenticate():
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope) oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/") authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
@ -48,12 +57,14 @@ def authenticate():
#Linux: chromdriver-linux #Linux: chromdriver-linux
#Macos: chromdriver-mac #Macos: chromdriver-mac
#Windows: chromdriver.exe #Windows: chromdriver.exe
path = os.path.join(cdir, "chromedriver-mac") if('CLI' in os.getcwd()):
print(path) path = os.path.join(os.getcwd(), '../','chromedriver-mac')
browser = webdriver.Chrome(path) else:
browser = webdriver.Safari() path = os.path.join(os.getcwd(), 'chromedriver-mac')
browser = webdriver.Chrome(path)
web_dir = os.path.join(os.path.dirname(__file__), 'oauth') web_dir = os.path.join(os.path.dirname(__file__), 'oauth')
print(web_dir)
os.chdir(web_dir) os.chdir(web_dir)
if os.path.exists("index.html"): if os.path.exists("index.html"):
os.remove("index.html") os.remove("index.html")
@ -71,24 +82,29 @@ def authenticate():
browser.get("localhost:8000/") 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) time.sleep(0.25)
url = browser.current_url 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") code = gets.get("code")
if state == gets.get("state"): if state == gets.get("state"):
state = gets.get("state") state = gets.get("state")
print("states good") print("states good")
browser.quit() browser.quit()
print(code) #print(code)
print(state) print(state)
payload = {'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri, 'client_id': client_id, payload = {'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri, 'client_id': client_id,
'client_secret': client_secret, 'csrfmiddlewaretoken': state} 'client_secret': client_secret, 'csrfmiddlewaretoken': state}
token = requests.post("https://ion.tjhsst.edu/oauth/token/", data=payload).json() token = requests.post("https://ion.tjhsst.edu/oauth/token/", data=payload).json()
print(token) #print(token)
headers = {'Authorization': f"Bearer {token['access_token']}"} headers = {'Authorization': f"Bearer {token['access_token']}"}
# And finally get the user's profile! # And finally get the user's profile!
@ -101,10 +117,18 @@ def authenticate():
last_name = profile['last_name'] last_name = profile['last_name']
os.chdir(cdir) os.chdir(cdir)
profileFile = open(".profile", "w") # key = Fernet.generate_key()
#profileFile.write(profile.text()) # file = open('key.key', 'wb')
profileFile.write(str(profile)) # file.write(key) # The key is type bytes still
profileFile.close() # 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 sys.exit

View File

@ -386,10 +386,17 @@ class Student:
command('git checkout master') command('git checkout master')
os.chdir(cdir) os.chdir(cdir)
data = getStudent("2022rkhondak") # data = getStudent("2022rkhondak")
s = Student(data) # s = Student(data)
#s.viewClass("APLit_eharris1") # #s.viewClass("APLit_eharris1")
#s.updateClass("APLit_eharris1") # #s.updateClass("APLit_eharris1")
#s.update() # #s.update()
s.exitCLI() # s.exitCLI()
def main():
print("noooo")
pass
if __name__ == "__main__":
# stuff only to run when not called via 'import' here
main()

View File

@ -659,8 +659,8 @@ t = Teacher(data)
#ar = ['2022rkhondak','2022inafi','2023rumareti'] #ar = ['2022rkhondak','2022inafi','2023rumareti']
#extra = t.reqAddStudentList(ar, "APLit_eharris1") #extra = t.reqAddStudentList(ar, "APLit_eharris1")
#print(extra) #print(extra)
t.getStudents('2022rkhondak') # t.getStudents('2022rkhondak')
t.getChanges('2022rkhondak','APLit_eharris1', 10) # t.getChanges('2022rkhondak','APLit_eharris1', 10)
''' '''
TO-DO TO-DO

View File

@ -1,3 +1,16 @@
from django.contrib import admin from django.contrib import admin
from .models import (
DefFiles,
Assignment,
Classes,
Teacher,
Student
)
# Register your models here. # Register your models here.
admin.site.register(Teacher)
admin.site.register(Student)
admin.site.register(DefFiles)
admin.site.register(Assignment)
admin.site.register(Classes)

View File

@ -1,128 +1,128 @@
from datetime import datetime # from datetime import datetime
#
f1 = DefFiles( # f1 = DefFiles(
name="instructions.txt" # name="instructions.txt"
) # )
f1.save() # f1.save()
f2 = DefFiles( # f2 = DefFiles(
name="instructions.txt" # name="instructions.txt"
) # )
f2.save() # f2.save()
f3 = DefFiles( # f3 = DefFiles(
name="sample.txt" # name="sample.txt"
) # )
f3.save() # f3.save()
f4 = DefFiles( # f4 = DefFiles(
name="rubric.txt" # name="rubric.txt"
) # )
f4.save() # f4.save()
#
a1 = Assignment.objects.get(pk=1) # a1 = Assignment.objects.get(pk=1)
a1.files.add(f1) # a1.files.add(f1)
a1.save() # a1.save()
a2 = Assignment.objects.get(pk=2) # a2 = Assignment.objects.get(pk=2)
a2.files.add(f2) # a2.files.add(f2)
a2.save() # a2.save()
a3 = Assignment.objects.get(pk=3) # a3 = Assignment.objects.get(pk=3)
a3.files.add(f3) # a3.files.add(f3)
a3.files.add(f4) # a3.files.add(f4)
a3.save() # a3.save()
#
#################################### # ####################################
#
from api.models import Assignment, Student, Classes, Teacher, DefFiles # from api.models import Assignment, Student, Classes, Teacher, DefFiles
from datetime import datetime # from datetime import datetime
#
f1 = DefFiles( # f1 = DefFiles(
name="instructions.txt" # name="instructions.txt"
) # )
f1.save() # f1.save()
f2 = DefFiles( # f2 = DefFiles(
name="instructions.txt" # name="instructions.txt"
) # )
f2.save() # f2.save()
f3 = DefFiles( # f3 = DefFiles(
name="sample.txt" # name="sample.txt"
) # )
f3.save() # f3.save()
f4 = DefFiles( # f4 = DefFiles(
name="rubric.txt" # name="rubric.txt"
) # )
f4.save() # f4.save()
#
A1 = Assignment( # A1 = Assignment(
name='Week1_HW', # name='Week1_HW',
due_date=datetime.now(), # due_date=datetime.now(),
) # )
A1.save() # A1.save()
A1.files.add(f1) # A1.files.add(f1)
A1.save() # A1.save()
#
A2 = Assignment( # A2 = Assignment(
name='Week2_HW', # name='Week2_HW',
due_date=datetime.now(), # due_date=datetime.now(),
#
) # )
A2.save() # A2.save()
A2.files.add(f2) # A2.files.add(f2)
A2.save() # A2.save()
#
A3 = Assignment( # A3 = Assignment(
name='Journal1', # name='Journal1',
due_date=datetime.now(), # due_date=datetime.now(),
) # )
A3.save() # A3.save()
A3.files.add(f3) # A3.files.add(f3)
A3.files.add(f4) # A3.files.add(f4)
A3.save() # A3.save()
#
#classes # #classes
math = Classes( # math = Classes(
name='Math5', # name='Math5',
#
) # )
math.save() # math.save()
math.assignments.add(A1) # math.assignments.add(A1)
math.assignments.add(A2) # math.assignments.add(A2)
math.save() # math.save()
#
english = Classes( # english = Classes(
name='English', # name='English',
) # )
english.save() # english.save()
english.assignments.add(A3) # english.assignments.add(A3)
english.save() # english.save()
#
#students # #students
raffu = Student( # raffu = Student(
first_name = "Raffu", # first_name = "Raffu",
last_name = "Khondaker", # last_name = "Khondaker",
student_id = 1579460, # student_id = 1579460,
ion_user="2022rkhondak", # ion_user="2022rkhondak",
webmail = "2022rkhondak@tjhsst.edu", # webmail = "2022rkhondak@tjhsst.edu",
grade = 10, # grade = 10,
repo="https://github.com/therealraffi/2022rkhondak.git", # repo="https://github.com/therealraffi/2022rkhondak.git",
) # )
raffu.save() # raffu.save()
raffu.classes.add(math) # raffu.classes.add(math)
raffu.classes.add(english) # raffu.classes.add(english)
raffu.save() # raffu.save()
#
#teachers # #teachers
ng = Teacher( # ng = Teacher(
first_name = "Errin", # first_name = "Errin",
last_name = "Harris", # last_name = "Harris",
ion_user="eharris1" # ion_user="eharris1"
) # )
ng.save() # ng.save()
ng.classes.add(math) # ng.classes.add(math)
ng.save() # ng.save()
#
chao = Teacher( # chao = Teacher(
first_name = "Abagail", # first_name = "Abagail",
last_name = "Bailey", # last_name = "Bailey",
ion_user="AKBailey" # ion_user="AKBailey"
) # )
chao.save() # chao.save()
chao.classes.add(english) # chao.classes.add(english)
chao.save() # chao.save()

View File

@ -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 from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -8,33 +10,10 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
] ]
operations = [ 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( migrations.CreateModel(
name='DefFiles', name='DefFiles',
fields=[ fields=[
@ -46,23 +25,6 @@ class Migration(migrations.Migration):
('teacher', models.CharField(max_length=100)), ('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( migrations.CreateModel(
name='Teacher', name='Teacher',
fields=[ fields=[
@ -73,6 +35,41 @@ class Migration(migrations.Migration):
('ion_user', models.CharField(max_length=100, primary_key=True, serialize=False)), ('ion_user', models.CharField(max_length=100, primary_key=True, serialize=False)),
('git', models.CharField(max_length=100)), ('git', models.CharField(max_length=100)),
('email', models.CharField(blank=True, default='', 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)),
], ],
), ),
] ]

View File

@ -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),
),
]

View File

@ -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),
),
]

View File

@ -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),
),
]

View File

@ -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),
),
]

View File

@ -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=''),
),
]

View File

@ -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),
),
]

View File

@ -1,4 +1,5 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User
class DefFiles(models.Model): class DefFiles(models.Model):
name=models.CharField(max_length=100) name=models.CharField(max_length=100)
@ -8,6 +9,8 @@ class DefFiles(models.Model):
teacher=models.CharField(max_length=100) teacher=models.CharField(max_length=100)
class Assignment(models.Model): 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) name=models.CharField(max_length=100, primary_key=True)
due_date=models.DateTimeField() due_date=models.DateTimeField()
# files = models.ManyToManyField(DefFiles) # files = models.ManyToManyField(DefFiles)
@ -19,6 +22,8 @@ class Assignment(models.Model):
return '%s' % (self.name) return '%s' % (self.name)
class Classes(models.Model): class Classes(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(primary_key=True, max_length=100) name = models.CharField(primary_key=True, max_length=100)
repo=models.URLField(default="", blank=True) repo=models.URLField(default="", blank=True)
path=models.CharField(max_length=100, default="") path=models.CharField(max_length=100, default="")
@ -34,31 +39,26 @@ class Classes(models.Model):
return super(Classes, self).save(*args, **kwargs) return super(Classes, self).save(*args, **kwargs)
class Teacher(models.Model): class Teacher(models.Model):
created = models.DateTimeField(auto_now_add=True) user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
# classes = models.ManyToManyField(Classes, default="") # classes = models.ManyToManyField(Classes, default="")
classes=models.CharField(max_length=100, default="", blank=True) classes=models.CharField(max_length=100, default="", blank=True)
ion_user=models.CharField(primary_key=True, max_length=100) ion_user=models.CharField(primary_key=True, max_length=100)
git=models.CharField(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): class Student(models.Model):
created = models.DateTimeField(auto_now_add=True) user = models.OneToOneField(User, on_delete=models.CASCADE)
first_name = models.CharField(max_length=100) grade = models.IntegerField(default=0, blank=True)
last_name = models.CharField(max_length=100) git=models.CharField(default="", max_length=100, blank=True)
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)
repo=models.URLField(default="", blank=True) repo=models.URLField(default="", blank=True)
classes=models.CharField(max_length=100, default="", blank=True) classes=models.CharField(max_length=100, default="", blank=True)
added_to=models.CharField(max_length=100, default="", blank=True) added_to=models.CharField(max_length=100, default="", blank=True)
completed=models.TextField(default="", blank=True) completed=models.TextField(default="", blank=True)
def save(self, *args, **kwargs): 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"

View File

@ -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

View File

@ -1,37 +1,55 @@
from django.contrib.auth.models import User, Group from django.contrib.auth.models import User, Group
from .models import Student, Teacher, Classes, Assignment, DefFiles from .models import Student, Teacher, Classes, Assignment, DefFiles
from rest_framework import serializers, permissions 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: class Meta:
model = DefFiles model = User
fields = ['name', 'path','assignment','classes', "teacher",'url', 'id'] fields = ['id', 'username']
# class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = DefFiles
# fields = ['name', 'path','assignment','classes', "teacher",'url', 'id']
class AssignmentSerializer(serializers.HyperlinkedModelSerializer): class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
#permissions_classes = [permissions.IsAuthenticatedOrReadOnly] #permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
# files = DefFilesSerializer(many=True, read_only=True,allow_null=True) # files = DefFilesSerializer(many=True, read_only=True,allow_null=True)
owner = serializers.ReadOnlyField(source='owner.username')
class Meta: class Meta:
model = Assignment 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): class ClassesSerializer(serializers.HyperlinkedModelSerializer):
# assignments = AssignmentSerializer(many=True, read_only=True,allow_null=True) # assignments = AssignmentSerializer(many=True, read_only=True,allow_null=True)
# default_file=DefFilesSerializer(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: class Meta:
model = Classes 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): class StudentSerializer(serializers.HyperlinkedModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True) # classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
owner = serializers.ReadOnlyField(source='owner.username')
class Meta: class Meta:
model = Student 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): class TeacherSerializer(serializers.ModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True) # classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
owner = serializers.ReadOnlyField(source='owner.username')
class Meta: class Meta:
model = Teacher 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']

5
Website/api/signals.py Normal file
View File

@ -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
)

View File

@ -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/<str:pk>/', views.StudentDetail.as_view()),
path('teachers/', views.TeacherList.as_view()),
path('teachers/<str:pk>/', views.TeacherDetail.as_view()),
path('assignments/', views.AssignmentList.as_view()),
path('assignments/<str:pk>/', views.AssignmentDetail.as_view()),
path('classes/', views.ClassesList.as_view()),
path('classes/<str:pk>/', views.ClassesDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)

View File

@ -1,131 +1,89 @@
# class StudentList(APIView): from .models import Student, Teacher, Classes, Assignment, DefFiles
# """ from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer
# List all snippets, or create a new snippet. from rest_framework import generics, viewsets, permissions, response, status
# """ from django.http import Http404
# def get(self, request, format=None): from rest_framework.views import APIView
# snippets = Student.objects.all() from django.contrib.auth.models import User
# serializer = StudentSerializer(snippets, many=True) from .permissions import isTeacher, IsOwnerOrReadOnly
# return response.Response(serializer.data) 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): class StudentList(generics.ListCreateAPIView):
# """ queryset = Student.objects.all()
# Retrieve, update or delete a snippet instance. serializer_class = StudentSerializer
# """ def perform_create(self, serializer):
# def get_object(self, pk): serializer.save(owner=self.request.user)
# try:
# return Student.objects.get(pk=pk)
# except Student.DoesNotExist:
# raise Http404
# def get(self, request, pk, format=None): class StudentDetail(generics.RetrieveAPIView):
# snippet = self.get_object(pk) queryset = Student.objects.all()
# serializer = StudentSerializer(snippet) serializer_class = StudentSerializer
# return response.Response(serializer.data) permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
# def put(self, request, pk, format=None): class TeacherList(generics.ListCreateAPIView):
# snippet = self.get_object(pk) queryset = Teacher.objects.all()
# serializer = StudentSerializer(snippet, data=request.data) serializer_class = TeacherSerializer
# if serializer.is_valid(): def perform_create(self, serializer):
# serializer.save() if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
# return response.Response(serializer.data) serializer.save(owner=self.request.user)
# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) else:
print("UNAUTHORIZED POST")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# def delete(self, request, pk, format=None): class TeacherDetail(generics.RetrieveAPIView):
# snippet = self.get_object(pk) queryset = Teacher.objects.all()
# snippet.delete() serializer_class = TeacherSerializer
# return response.Response(status=status.HTTP_204_NO_CONTENT) 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): class ClassesList(generics.ListCreateAPIView):
# """ queryset = Classes.objects.all()
# List all snippets, or create a new snippet. serializer_class = ClassesSerializer
# """ #permissions_classes = [isTeacher]
# def get(self, request, format=None): def perform_create(self, serializer):
# snippets = Classes.objects.all() if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
# serializer = ClassesSerializer(snippets, many=True) serializer.save(owner=self.request.user)
# return response.Response(serializer.data) else:
print("UNAUTHORIZED POST")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# def post(self, request, format=None): # class ClassesDetail(generics.RetrieveAPIView):
# serializer = ClassesSerializer(data=request.data) # queryset = Classes.objects.all()
# if serializer.is_valid(): # serializer_class = ClassesSerializer
# serializer.save() # # permissions_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
# return response.Response(serializer.data, status=status.HTTP_201_CREATED)
# return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
# class ClassesDetail(APIView): class ClassesDetail(mixins.RetrieveModelMixin,
# """ mixins.UpdateModelMixin,
# Retrieve, update or delete a snippet instance. mixins.DestroyModelMixin,
# """ generics.GenericAPIView):
# def get_object(self, pk): queryset = Classes.objects.all()
# try: serializer_class = ClassesSerializer
# return Classes.objects.get(pk=pk)
# except Classes.DoesNotExist:
# raise Http404
# def get(self, request, pk, format=None): def get(self, request, *args, **kwargs):
# snippet = self.get_object(pk) return self.retrieve(request, *args, **kwargs)
# serializer = ClassesSerializer(snippet)
# return response.Response(serializer.data)
# def put(self, request, pk, format=None): def put(self, request, *args, **kwargs):
# snippet = self.get_object(pk) print(self.owner)
# serializer = ClassesSerializer(snippet, data=request.data) if(request.user == self.owner):
# if serializer.is_valid(): return self.update(request, *args, **kwargs)
# 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): def delete(self, request, *args, **kwargs):
# snippet = self.get_object(pk) return self.destroy(request, *args, **kwargs)
# snippet.delete()
# return response.Response(status=status.HTTP_204_NO_CONTENT) 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]

View File

@ -1,8 +1,21 @@
from .models import Student, Teacher, Classes, Assignment, DefFiles 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 rest_framework import generics, viewsets, permissions, response, status
from django.http import Http404 from django.http import Http404
from rest_framework.views import APIView 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): class StudentViewSet(viewsets.ModelViewSet):
""" """
@ -10,8 +23,10 @@ class StudentViewSet(viewsets.ModelViewSet):
""" """
queryset = Student.objects.all() queryset = Student.objects.all()
serializer_class = StudentSerializer 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): class TeacherViewSet(viewsets.ModelViewSet):
""" """
@ -19,8 +34,10 @@ class TeacherViewSet(viewsets.ModelViewSet):
""" """
queryset = Teacher.objects.all() queryset = Teacher.objects.all()
serializer_class = TeacherSerializer 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): class ClassesViewSet(viewsets.ModelViewSet):
""" """
@ -28,7 +45,14 @@ class ClassesViewSet(viewsets.ModelViewSet):
""" """
queryset = Classes.objects.all() queryset = Classes.objects.all()
serializer_class = ClassesSerializer 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): class AssignmentViewSet(viewsets.ModelViewSet):
@ -37,12 +61,19 @@ class AssignmentViewSet(viewsets.ModelViewSet):
""" """
queryset = Assignment.objects.all() queryset = Assignment.objects.all()
serializer_class = AssignmentSerializer serializer_class = AssignmentSerializer
permissions_classes = [permissions.IsAuthenticatedOrReadOnly] permission_classes = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly]
class DefFilesViewSet(viewsets.ModelViewSet): def perform_create(self, serializer):
""" if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
API endpoint that allows users to be viewed or edited. serializer.save(owner=self.request.user)
""" else:
queryset = DefFiles.objects.all() print("UNAUTHORIZED POST")
serializer_class = DefFilesSerializer return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
# 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]

View File

@ -11,6 +11,6 @@ import os
from django.core.asgi import get_asgi_application 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() application = get_asgi_application()

View File

@ -31,6 +31,7 @@ ALLOWED_HOSTS = []
# Application definition # Application definition
INSTALLED_APPS = [ INSTALLED_APPS = [
'skoolos.apps.SkoolosConfig',
'users.apps.UsersConfig', 'users.apps.UsersConfig',
'django.contrib.admin', 'django.contrib.admin',
'django.contrib.auth', 'django.contrib.auth',
@ -41,8 +42,7 @@ INSTALLED_APPS = [
'rest_framework', 'rest_framework',
'api', 'api',
'crispy_forms', 'crispy_forms',
'django_forms_bootstrap',
] ]
REST_FRAMEWORK = { REST_FRAMEWORK = {
@ -63,7 +63,7 @@ MIDDLEWARE = [
'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware',
] ]
ROOT_URLCONF = 'skoolos.urls' ROOT_URLCONF = 'config.urls'
TEMPLATES = [ TEMPLATES = [
{ {
@ -81,7 +81,7 @@ TEMPLATES = [
}, },
] ]
WSGI_APPLICATION = 'skoolos.wsgi.application' WSGI_APPLICATION = 'config.wsgi.application'
# Database # Database
@ -135,4 +135,6 @@ STATIC_URL = '/static/'
CRISPY_TEMPLATE_PACK = 'bootstrap4' CRISPY_TEMPLATE_PACK = 'bootstrap4'
LOGIN_REDIRECT_URL = '/' LOGIN_REDIRECT_URL = '/'
LOGIN_URL = '/login'

31
Website/config/urls.py Normal file
View File

@ -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'),
]

View File

@ -11,6 +11,6 @@ import os
from django.core.wsgi import get_wsgi_application 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() application = get_wsgi_application()

View File

@ -5,7 +5,7 @@ import sys
def main(): def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'skoolos.settings') os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
try: try:
from django.core.management import execute_from_command_line from django.core.management import execute_from_command_line
except ImportError as exc: except ImportError as exc:

3
Website/skoolos/admin.py Normal file
View File

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

5
Website/skoolos/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class SkoolosConfig(AppConfig):
name = 'skoolos'

View File

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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;
}

View File

@ -0,0 +1,52 @@
{% load static %}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" type="text/css" href="{% static 'skoolos/styles.css' %}">
<title>SkoolOS</title>
</head>
<body>
<header class="site-header">
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container">
<a class="navbar-brand" href="#">
<img src="/docs/4.3/assets/brand/bootstrap-solid.svg" width="30" height="30" class="d-inline-block align-top" alt="">
Bootstrap
</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarToggle">
<div class="navbar-nav mr-auto">
<a class="nav-item nav-link" href="{% url 'home' %}">Home</a>
</div>
<!-- Navbar Right Side -->
<div class="navbar-nav">
{% if user.is_authenticated %}
<a class="nav-item nav-link" href="{% url 'profile' %}">{{ user.username }}</a>
<a class="nav-item nav-link" href="{% url 'logout' %}">Logout</a>
{% endif %}
</div>
</div>
</div>
</nav>
</header>
{% block content %}{% endblock %}
<!-- Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
</body>
</html>

View File

@ -0,0 +1,3 @@
{% extends "skoolos/base.html" %}
{% block content %}
{% endblock content %}

3
Website/skoolos/tests.py Normal file
View File

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

View File

@ -1,23 +1,9 @@
from django.urls import path 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() from . import views
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)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API. # Additionally, we include login URLs for the browsable API.
urlpatterns = [ urlpatterns = [
path('api/', include(router.urls)), path('', views.home, name='home'),
path('api-auth/', include('rest_framework.urls')), path('profile/', views.profile, name='profile')
path('admin/', admin.site.urls), ]
path('login/', auth_views.LoginView.as_view(template_name="users/login.html"), name='login')
]

12
Website/skoolos/views.py Normal file
View File

@ -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

View File

@ -1,3 +1,5 @@
from django.contrib import admin from django.contrib import admin
from .models import Token
# Register your models here. # Register your models here.
admin.site.register(Token)

32
Website/users/forms.py Normal file
View File

@ -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')

View File

@ -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)),
],
),
]

View File

@ -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),
),
]

View File

@ -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),
),
]

View File

@ -1,3 +1,22 @@
from django.db import models from django.db import models
from uuid import uuid4
# Create your models here. # 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";

6
Website/users/pwd.py Normal file
View File

@ -0,0 +1,6 @@
import os
pwd = "heyyy"
path = os.getcwd()
p = os.path.join(path, '../../', 'pwd.txt')
open(p, 'w')

View File

@ -99,6 +99,10 @@ body {
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
input:disabled {
background: #d9d9d9;
}
.errorlist { .errorlist {
} }

View File

@ -18,7 +18,6 @@
</head> </head>
<body> <body>
{% block content %}{% endblock %} {% block content %}{% endblock %}
a
<!-- Bootstrap JS --> <!-- Bootstrap JS -->
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>

View File

@ -0,0 +1,22 @@
{% extends "users/base.html" %}
{% load bootstrap_tags %}
{% block content %}
<div class="login-page">
<div class="form">
<form class="login-form" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
<button type="submit">create</button>
</form>
</div>
</div>
{% endblock %}

View File

@ -1,16 +1,38 @@
{% extends "users/base.html" %} {% extends "users/base.html" %}
{% load crispy_forms_tags %} {% load bootstrap_tags %}
{% block content %} {% block content %}
<div class="login-page"> <div class="login-page">
<div class="form"> <div class="form">
<form class="login-form" method="POST"> <form class="login-form" method="POST">
{% csrf_token %} {% csrf_token %}
{{ form | crispy }} {% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% if form.errors %}
{% for field in form %}
{% for error in field.errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endfor %}
{% for error in form.non_field_errors %}
<div class="alert alert-danger">
<strong>{{ error|escape }}</strong>
</div>
{% endfor %}
{% endif %}
{% for field in form %}
{{ field }}
{% endfor %}
<button type="submit">login</button> <button type="submit">login</button>
<p class="message">Not registered? <a href="#">Create an account with Ionreg</a></p> <p class="message">Not registered? <a href="{% url 'register' %}">Create an account with Ion</a></p>
</form> </form>
</div> </div>
</div> </div>
</div> {% endblock %}
{% endblock %}

View File

@ -3,13 +3,20 @@
{% block content %} {% block content %}
<div class="login-page"> <div class="login-page">
<div class="form"> <div class="form">
<form class="login-form" method="POST"> <div class="content-section">
{% csrf_token %} {% if messages %}
{{ form | crispy }} {% for message in messages %}
<button type="submit">login</button> <div class="alert alert-{{ message.tags }} alert-dismissible fade show">
<p class="message">Not registered? <a href="#">Create an account with Ionreg</a></p> {{ message }}
</form> </div>
{% endfor %}
{% endif %}
<a href="{{ authorization_url }}" title="Ion" class="border border-dark p-3 btn btn-block btn-lg mx-auto" style="background: black; color: white;">
<img src="https://ion.tjhsst.edu/static/img/favicon.png" style="filter: invert(1);">
Register with Ion
</a>
</div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}

View File

@ -1,3 +1,148 @@
from django.shortcuts import render import json
import requests
from django.shortcuts import render, redirect
from requests_oauthlib import OAuth2Session
from django.contrib import messages
from .models import Token
from api.models import Student, Teacher
from .forms import UserCreationForm
from django.contrib.auth import authenticate
from django.contrib.auth import login as auth_login
from django.contrib.auth import logout as auth_logout
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
import os
# Create your views here. # Create your views here.
# Thanks Django, what would I do without this comment
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
redirect_uri = 'http://localhost:8000/callback/'
token_url = 'https://ion.tjhsst.edu/oauth/authorize/'
scope=["read"]
def register(request):
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
return render(request,"users/register.html", {"authorization_url": authorization_url})
def callback (request):
if request.method == "GET":
code = request.GET.get('code')
state = request.GET.get("state")
# Then if we get a response from Ion with the authorization code
if code is not None and state is not None:
print ("made it")
# We send it back to fetch the acess_token
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()
headers = {'Authorization': f"Bearer {token['access_token']}"}
print(token)
# And finally get the user's profile!
profile = requests.get("https://ion.tjhsst.edu/api/profile", headers=headers).json()
print(profile)
username = profile['ion_username']
email = profile['tj_email']
first_name = profile['first_name']
last_name = profile['last_name']
isStudent = profile['is_student']
grade = profile['grade']['number']
if User.objects.filter(username=username).count() != 0:
messages.success(request, "This user already exists!")
return redirect('/login/')
else:
token = Token(username = username, email = email, first_name = first_name, last_name = last_name, isStudent = isStudent, grade=grade)
token.save()
tokenHash = token.token
print(f'/create_account/?token={tokenHash}')
return redirect(f'/create_account/?token={tokenHash}')
messages.warning(request, "Invalid Callback Response")
return redirect('/register/')
def create_account (request):
if request.method == "POST":
print("POSTPOSTPOSTPOSTPOSTPOSTPOSTPOST")
form = UserCreationForm(request.POST)
print(form.is_valid())
print(request.POST)
cleaned_data = form.clean()
if cleaned_data.get('password') == cleaned_data.get('confirm_password'):
token = Token.objects.get(token=cleaned_data.get('token'))
username = token.username
email = token.email
first_name = token.first_name
last_name = token.last_name
isStudent = token.isStudent
grade = token.grade
git = cleaned_data.get('git')
password = cleaned_data.get('password')
user = User.objects.create_user(username=username,
email=email,
first_name=first_name,
last_name=last_name,
password=password)
user.save()
token.delete()
if isStudent:
profile = Student(user=user, git=git, grade=grade)
else:
profile = Teacher(user=user, git=git)
profile.save()
print (user)
messages.success(request, "Your SkoolOS account has successfully been created")
return redirect(f'/login/?username={username}')
else:
print(form.errors)
Token.objects.get(token=request.GET.get('token')).delete()
messages.warning(request, "Passwords did not match!")
return redirect('/register/')
if request.method == "GET" and Token.objects.filter(token=request.GET.get('token')).count() == 1:
print("GETGETGETGETGETGET")
token = Token.objects.get(token=request.GET.get('token'))
username = token.username
email = token.email
first_name = token.first_name
last_name = token.last_name
isStudent = token.isStudent
grade = token.grade
initial = {
'username': username,
'email': email,
'first_name': first_name,
'last_name': last_name,
'grade': grade,
'isStudent': isStudent,
'token': token.token,
}
form = UserCreationForm(initial=initial)
return render(request, 'users/create_account.html', {'form': form})
messages.warning(request, "Invalid token")
return redirect('/register/')
@login_required
def logout(request):
auth_logout(request)
messages.success(request, "You've been logged out!")
return redirect(request, "/login")

BIN
chromedriver-linux Executable file

Binary file not shown.

BIN
chromedriver.exe Normal file

Binary file not shown.

View File

@ -12,6 +12,7 @@ oauthlib==3.1.0
prompt-toolkit==1.0.14 prompt-toolkit==1.0.14
pyclipper==1.1.0.post3 pyclipper==1.1.0.post3
Pygments==2.6.1 Pygments==2.6.1
pyinotify==0.9.6
PyInquirer==1.0.3 PyInquirer==1.0.3
pyperclip==1.8.0 pyperclip==1.8.0
pytz==2020.1 pytz==2020.1

View File

@ -1,2 +0,0 @@
for i in range(0, 100000):
print(i)

242
skoolos.py Normal file
View File

@ -0,0 +1,242 @@
import sys
from urllib.parse import urlparse
import requests
from requests_oauthlib import OAuth2Session
from selenium import webdriver
import os.path
import time
import http.server
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
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
redirect_uri = 'http://localhost:8000/callback/'
token_url = 'https://ion.tjhsst.edu/oauth/token/'
scope = ["read"]
USER = ""
PWD = ""
def main():
print("")
print("░██████╗██╗░░██╗░█████╗░░█████╗░██╗░░░░░  ░█████╗░░██████╗")
print("██╔════╝██║░██╔╝██╔══██╗██╔══██╗██║░░░░░  ██╔══██╗██╔════╝")
print("╚█████╗░█████═╝░██║░░██║██║░░██║██║░░░░░  ██║░░██║╚█████╗░")
print("░╚═══██╗██╔═██╗░██║░░██║██║░░██║██║░░░░░  ██║░░██║░╚═══██╗")
print("██████╔╝██║░╚██╗╚█████╔╝╚█████╔╝███████╗  ╚█████╔╝██████╔╝")
print("╚═════╝░╚═╝░░╚═╝░╚════╝░░╚════╝░╚══════╝  ░╚════╝░╚═════╝░")
print("")
if not os.path.exists(".profile"):
try:
URL = "http://127.0.0.1:8000/api/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
print("End service at http://127.0.0.1:8000/ before continuing.")
sys.exit(0)
except:
pass
input("Welcome to SkoolOS. Press any key to create an account")
authenticate()
else:
try:
URL = "http://127.0.0.1:8000/api/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
except:
print("Start Django server first")
sys.exit(0)
f = open('.profile','r')
data = json.loads(f.read())
f.close()
PWD = data['password']
USER = data['username']
if(data['is_student']):
studentCLI()
else:
teacherCLI()
# while True:
# pass
def studentCLI():
from CLI import student
data = getStudent(USER)
print(data)
student = student.Student(data)
print(student)
def teacherCLI():
from CLI.teacher import Teacher
print("fail")
def getStudent(ion_user):
URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
if(r.status_code == 200):
data = r.json()
return data
elif(r.status_code == 404):
return None
print("Make new account!")
elif(r.status_code == 403):
return None
print("Invalid username/password")
else:
return None
print(r.status_code)
def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
print("GET:" + str(r.status_code))
return(r.json())
def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("POST:" + str(r.status_code))
return(r.json())
def putDB(data, url):
r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PUT:" + str(r.status_code))
return(r.json())
def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1'))
print("DELETE:" + str(r.status_code))
return None
def makePass():
questions = [
{
'type': 'password',
'name': 'pwd',
'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ',
},
]
pwd = prompt(questions)['pwd']
while(len(pwd) < 7):
print("Password too short (Must be over 6 characters)")
pwd = prompt(questions)['pwd']
conf = [
{
'type': 'password',
'name': 'pwd',
'message': 'Re-enter password: ',
},
]
pwd2 = prompt(conf)['pwd']
while(not pwd == pwd2):
print("Passwords do not match.")
pwd2 = prompt(conf)['pwd']
else:
print("PASSWORD SAVED")
return pwd
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/")
cdir = os.getcwd()
#Linux: chromdriver-linux
#Macos: chromdriver-mac
#Windows: chromdriver.exe
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.getcwd(), 'CLI', 'oauth')
print(web_dir)
os.chdir(web_dir)
if os.path.exists("index.html"):
os.remove("index.html")
template = open("template.html", "r")
index = open("index.html", "w")
for line in template:
index.write(line.replace('AUTH_URL', authorization_url))
template.close()
index.close()
server = Thread(target=create_server)
server.daemon = True
server.start()
browser.get("localhost:8000/")
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/?", ""))
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(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)
headers = {'Authorization': f"Bearer {token['access_token']}"}
# And finally get the user's profile!
profile = requests.get("https://ion.tjhsst.edu/api/profile", headers=headers).json()
#pprint.pprint(profile)
username = profile['ion_username']
email = profile['tj_email']
first_name = profile['first_name']
last_name = profile['last_name']
is_student = profile['is_student']
password = ""
#password creation
profile = {
'username':username,
'email':email,
'first_name':first_name,
'last_name':last_name,
'is_student':is_student,
'password':password,
}
os.chdir(cdir)
profileFile = open(".profile", "w")
profileFile.write(json.dumps(profile))
profileFile.close()
#try to make password
password = makePass()
profile['password'] = password
profileFile = open(".profile", "w")
profileFile.write(json.dumps(profile))
profileFile.close()
sys.exit
def create_server():
port = 8000
handler = http.server.SimpleHTTPRequestHandler
httpd = socketserver.TCPServer(("", port), handler)
print("serving at port:" + str(port))
httpd.serve_forever()
if __name__ == "__main__":
main()