Merge pull request #6 from Rushilwiz/development

Development
This commit is contained in:
Rushil Umaretiya 2020-06-16 00:19:39 -04:00 committed by GitHub
commit 0c33eb47ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
41 changed files with 1024 additions and 774 deletions

4
.gitignore vendored
View File

@ -60,6 +60,10 @@ coverage.xml
local_settings.py local_settings.py
db.sqlite3 db.sqlite3
db.sqlite3-journal db.sqlite3-journal
migrations/
*/migrations/
**/**/migrations
**/migrations
# Flask stuff: # Flask stuff:
instance/ instance/

View File

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

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

View File

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

@ -1,23 +0,0 @@
<html>
<head>
<title>Sign into Ion</title>
<style>
body {
background: #5ac8fb;
background: -webkit-linear-gradient(to left, #52edc7, #5ac8fb);
background: linear-gradient(to left, #52edc7, #5ac8fb);
}
</style>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
</head>
<body>
<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%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">
Sign in with Ion
</a>
</div>
</body>
</html>

View File

@ -43,6 +43,11 @@ def putDB(data, url):
print("PUT:" + str(r.status_code)) print("PUT:" + str(r.status_code))
return(r.json()) return(r.json())
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PATH:" + str(r.status_code))
return(r.json())
def delDB(url): def delDB(url):
r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1'))
print("DELETE:" + str(r.status_code)) print("DELETE:" + str(r.status_code))
@ -66,15 +71,12 @@ class Student:
def __init__(self, data): def __init__(self, data):
# teacher info already stored in API # teacher info already stored in API
# intitialze fields after GET request # intitialze fields after GET request
self.first_name=data['first_name']
self.last_name=data['last_name']
self.git=data['git'] self.git=data['git']
self.username=data['ion_user'] self.username=data['ion_user']
self.url= "http://127.0.0.1:8000/api/students/" + self.username + "/" self.url= "http://127.0.0.1:8000/api/students/" + self.username + "/"
self.email = data['email']
self.grade = data['grade'] self.grade = data['grade']
self.student_id=data['student_id']
self.completed = data['completed'] self.completed = data['completed']
self.user = data['user']
#classes in id form (Example: 4,5) #classes in id form (Example: 4,5)
#storing actual classes #storing actual classes
cid=data['classes'].split(",") cid=data['classes'].split(",")
@ -132,20 +134,9 @@ class Student:
os.chdir(cdir) os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git' self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={ data={
'first_name':self.first_name,
'last_name':self.last_name,
'git':self.git,
'ion_user':self.username,
'student_id':self.student_id,
'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'email':self.email,
'grade':self.grade,
'completed':self.completed,
'repo':self.repo 'repo':self.repo
} }
print(putDB(data, self.url)) print(patchDB(data, self.url))
print("Synced to " + self.username) print("Synced to " + self.username)
def getClasses(self): def getClasses(self):
@ -169,7 +160,7 @@ class Student:
zero = datetime.timedelta(0,0) zero = datetime.timedelta(0,0)
#check due ddate is in span range is now past date (- timdelta) #check due ddate is in span range is now past date (- timdelta)
if(diff < span and diff > zero): if(diff < span and diff > zero):
print((now-due)) print(a + " due in:" + str(now-due))
except Exception as e: except Exception as e:
print(e) print(e)
@ -284,20 +275,11 @@ class Student:
#update teacher instance in db, classes field #update teacher instance in db, classes field
data={ data={
'first_name':self.first_name, 'user':self.user,
'last_name':self.last_name,
'git':self.git,
'ion_user':self.username,
'student_id':self.student_id,
'added_to':self.snew, 'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'email':self.email,
'grade':self.grade,
'completed':self.completed
} }
print(self.url) print(self.url)
print(putDB(data, self.url)) print(patchDB(data, self.url))
return data return data
def submit(self, path): def submit(self, path):
@ -327,15 +309,13 @@ class Student:
command("git push -u origin " + self.username + " --tags") command("git push -u origin " + self.username + " --tags")
self.completed = self.completed + "," + parts[1] + "/" + parts[2] self.completed = self.completed + "," + parts[1] + "/" + parts[2]
data={ data={
'first_name':self.first_name, 'user':self.user,
'last_name':self.last_name,
'git':self.git, 'git':self.git,
'ion_user':self.username, 'ion_user':self.username,
'student_id':self.student_id, 'student_id':self.student_id,
'added_to':self.snew, 'added_to':self.snew,
'url':self.url, 'url':self.url,
'classes':self.sclass, 'classes':self.sclass,
'email':self.email,
'grade':self.grade, 'grade':self.grade,
'completed':self.completed 'completed':self.completed
} }

View File

@ -9,7 +9,18 @@ import time
import pyperclip import pyperclip
from distutils.dir_util import copy_tree from distutils.dir_util import copy_tree
from datetime import datetime from datetime import datetime
# from django.conf import settings
# import django
# from Website.config.settings import DATABASES, INSTALLED_APPS
# INSTALLED_APPS.remove('users.apps.UsersConfig')
# INSTALLED_APPS.remove('api')
# INSTALLED_APPS.remove('skoolos.apps.SkoolosConfig')
# INSTALLED_APPS.append('Website.api')
# settings.configure(DATABASES=DATABASES, INSTALLED_APPS=INSTALLED_APPS)
# django.setup()
# from ..Website.api.models import *
#git clone student directory ==> <student-id>/classes/assignments #git clone student directory ==> <student-id>/classes/assignments
#get teacher info from api #get teacher info from api
@ -33,6 +44,10 @@ def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
print("GET:" + str(r.status_code)) print("GET:" + str(r.status_code))
return(r.json()) return(r.json())
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PATCH:" + str(r.status_code))
return(r.json())
def postDB(data, url): def postDB(data, url):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
@ -66,30 +81,14 @@ class Teacher:
def __init__(self, data): def __init__(self, data):
# teacher info already stored in API # teacher info already stored in API
# intitialze fields after GET request # intitialze fields after GET request
self.first_name=data['first_name']
self.last_name=data['last_name']
self.git=data['git'] self.git=data['git']
self.username=data['ion_user'] self.username=data['ion_user']
self.url= "http://127.0.0.1:8000/api/teachers/" + self.username + "/" self.url= "http://127.0.0.1:8000/api/teachers/" + self.username + "/"
self.email = data['email'] self.id = data['user']
#classes in id form (Example: 4,5) #classes in id form (Example: 4,5)
cid=data['classes'].split(",") #array
try: self.classes=data['classes']
cid.remove('')
except:
pass
try:
cid.remove("")
except:
pass
classes=[]
for c in cid:
url = "http://127.0.0.1:8000/api/classes/" + str(c) + "/"
classes.append(getDB(url))
self.classes = classes
self.sclass=str(data['classes'])
if(os.path.isdir(self.username + "/Students")): if(os.path.isdir(self.username + "/Students")):
print("Synced to " + self.username) print("Synced to " + self.username)
else: else:
@ -151,44 +150,31 @@ class Teacher:
#make class from existing directory, add to git and api #make class from existing directory, add to git and api
def addClass(self, path): def addClass(self, path):
cname = path.split("/")
cname = cname[len(cname)-1]
for c in self.classes:
if c == cname:
print(cname + " already exists.")
return
if (self.checkClass(path)): if (self.checkClass(path)):
cname = path.split("/")
cname = cname[len(cname)-1]
cpath = self.username + "/" + cname cpath = self.username + "/" + cname
data = { data = {
"name": cname, "name": cname,
"repo": "", "repo": "",
"path": cpath, "path": cpath,
"teacher": self.username, "teacher": self.username,
"assignments": "", "owner":self.id
"default_file": "",
"confirmed": "",
"unconfirmed": ""
} }
#make class instance in db #make class instance in db
data = postDB(data, 'http://127.0.0.1:8000/api/classes/') postDB(data, 'http://127.0.0.1:8000/api/classes/')
self.classes.append(cname)
#add to instance #add to instance
#upate self.classes #upate self.classes
self.classes.append(data) data = {
if(len(self.sclass)==0): 'classes':self.classes
self.sclass = data['name']
else:
self.sclass = self.sclass + "," + str(data['name'])
#update teacher instance in db, classes field
teacher={
'first_name':self.first_name,
'last_name':self.last_name,
'git':self.git,
'ion_user':self.username,
'url':self.url,
'classes':self.sclass,
'email':self.email
} }
putDB(teacher, self.url) print(self.username)
print(patchDB(data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/"))
return teacher
#make a new class from scratch #make a new class from scratch
#subject: string, assignments: list #subject: string, assignments: list
@ -224,8 +210,7 @@ class Teacher:
# f.close() # f.close()
# os.chdir(cdir) # os.chdir(cdir)
data = self.addClass(path) self.addClass(path)
return data
def deleteClass(self, path): def deleteClass(self, path):
if(os.path.exists(path) == False): if(os.path.exists(path) == False):
@ -240,25 +225,12 @@ class Teacher:
print("DELETE: " + self.classes[i]['name']) print("DELETE: " + self.classes[i]['name'])
for i in range(len(self.classes)): for i in range(len(self.classes)):
c = self.classes[i] c = self.classes[i]
if(c['name'] == cname): if(c == cname):
del self.classes[i] del self.classes[i]
s="" # data={
#recreate sclass field, using ids # 'classes':self.classes,
for c in self.classes: # }
s = s + str(c['name']) + "," # print(patchDB(data, self.url))
print(s)
s = s[:-1]
print(s)
data={
'first_name':self.first_name,
'last_name':self.last_name,
'git':self.git,
'ion_user':self.username,
'url':self.url,
'classes':s,
'email':self.email
}
print(putDB(data, self.url))
delDB("http://127.0.0.1:8000/api/classes/" + cname + "/") delDB("http://127.0.0.1:8000/api/classes/" + cname + "/")
break break
@ -282,53 +254,37 @@ class Teacher:
print(sname + " does not exist.") print(sname + " does not exist.")
return False return False
course = getDB("http://127.0.0.1:8000/api/classes/" + cname) course = getDB("http://127.0.0.1:8000/api/classes/" + cname)
if(sname in course['unconfirmed']): # if(sname in str(course['unconfirmed'])):
print (sname + " already requested.") # print (sname + " already requested.")
return True # return True
if(sname in course['confirmed']): # if(sname in str(course['confirmed'])):
print (sname + " alredy enrolled.") # print (sname + " alredy enrolled.")
return False # return False
student = getDB("http://127.0.0.1:8000/api/students/" + sname) # student = getDB("http://127.0.0.1:8000/api/students/" + sname)
try: # try:
if(student['added_to']==""): # if(student['added_to']==""):
student['added_to']=course['name'] # student['added_to']=course['name']
else: # else:
student['added_to']=student['added_to']+ "," + course['name'] # student['added_to']=student['added_to']+ "," + course['name']
except: # except:
print(sname + " does not exist.") # print(sname + " does not exist.")
return False # return False
print(student['added_to']) # print(student['added_to'])
s={ # data={
'first_name':student["first_name"], # 'added_to':student['added_to'],
'last_name':student["last_name"], # }
'git':student["git"], # student = patchDB(data, "http://localhost:8000/api/students/" + student['ion_user'] + "/")
'ion_user':student["ion_user"], student = getDB( "http://localhost:8000/api/students/" + (sname)+ "/")
'student_id':student["student_id"], if(course['unconfirmed']==[]):
'added_to':student['added_to'],
'classes':student["classes"],
'email':student["email"],
'grade':student["grade"],
'completed':student["completed"],
'repo':student["repo"]
}
student = putDB(s, student['url'])
if(course['unconfirmed']==""):
course['unconfirmed']=student['ion_user'] course['unconfirmed']=student['ion_user']
else: else:
course['unconfirmed']=course['unconfirmed']+ "," + student['ion_user'] course['unconfirmed']=course['unconfirmed'].append(student['ion_user'])
cinfo = { cinfo = {
"name": course['name'],
"repo": "",
"path": self.username + "/" + course['name'],
"teacher": self.username,
"assignments": course['assignments'],
"default_file": "",
"confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed'] "unconfirmed": course['unconfirmed']
} }
print(putDB(cinfo, course['url'])) print(cinfo)
patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/")
return True return True
#Student should have confirmed on their endd, but class had not been updated yet #Student should have confirmed on their endd, but class had not been updated yet
@ -390,16 +346,10 @@ class Teacher:
course['unconfirmed']= course['unconfirmed'].replace(student['ion_user']+",", "") course['unconfirmed']= course['unconfirmed'].replace(student['ion_user']+",", "")
cinfo = { cinfo = {
"name": course['name'],
"repo": "",
"path": course['path'],
"teacher": self.username,
"assignments": course['assignments'],
"default_file": "",
"confirmed": course["confirmed"], "confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed'] "unconfirmed": course['unconfirmed']
} }
print(putDB(cinfo, course['url'])) print(patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/"))
return True return True
#goes through list of studennts, tries to add, then request, return unconfirmed students #goes through list of studennts, tries to add, then request, return unconfirmed students
@ -417,10 +367,10 @@ class Teacher:
parts = path.split("/") parts = path.split("/")
aname = parts[len(parts)-1] aname = parts[len(parts)-1]
if(os.path.isdir(path) == 0 or len(parts) < 3) or aname in self.sclass: if(os.path.isdir(path) == 0 or len(parts) < 3) or aname in str(self.classes):
print("Not valid path.") print("Not valid path.")
return False return False
if((parts[1] in self.sclass) == False): if((parts[1] in str(self.classes)) == False):
print("Not in valid class directory") print("Not in valid class directory")
return False return False
#parts of assignment name (Essay1, APLit) #parts of assignment name (Essay1, APLit)
@ -445,7 +395,7 @@ class Teacher:
return False return False
course = getDB("http://127.0.0.1:8000/api/classes/" + course) course = getDB("http://127.0.0.1:8000/api/classes/" + course)
if(aname in course['assignments']): if(aname in str(course['assignments'])):
print("Assignment name already taken.") print("Assignment name already taken.")
return False return False
@ -459,7 +409,7 @@ class Teacher:
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name']) slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd() cdir = os.getcwd()
for st in slist: for st in slist:
if st in course['confirmed']: if st in str(course['confirmed']):
spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st) spath = os.path.join(os.getcwd() + "/" + self.username + "/Students/" + course['name'], st)
if(os.path.exists(spath + "/" + aname) == False): if(os.path.exists(spath + "/" + aname) == False):
os.mkdir(spath + "/" + aname) os.mkdir(spath + "/" + aname)
@ -487,21 +437,14 @@ class Teacher:
} }
postDB(ass, 'http://127.0.0.1:8000/api/assignments/') postDB(ass, 'http://127.0.0.1:8000/api/assignments/')
if(course['assignments'] == ""): if(course['assignments'] == ""):
course['assignments'] = aname course['assignments'] = ass
else: else:
course['assignments'] = course['assignments'] + "," + aname course['assignments'] = course['assignments'].append(ass)
cinfo = { cinfo = {
"name": course['name'],
"repo": "",
"path": course['path'],
"teacher": "eharris1",
"assignments": course['assignments'], "assignments": course['assignments'],
"default_file": "",
"confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed']
} }
putDB(cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/") patchDB(cinfo, "http://127.0.0.1:8000/api/classes/" + course['name'] + "/")
return True return True
else: else:
print("Assignment already addedd") print("Assignment already addedd")
@ -510,18 +453,22 @@ class Teacher:
#try to avoid #try to avoid
#copy modified assignments to student directories #copy modified assignments to student directories
def updateAssignment(self, path, course, due): def updateAssignment(self, path, course, due):
parts = path.split("/")
aname = parts[len(parts)-1]
if(os.path.isdir(path) == False): if(os.path.isdir(path) == False):
print(path + " is not an assignment.") print(path + " is not an assignment.")
return return
try: try:
if(due != None or due == ""): if(due != None or due == ""):
datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f') datetime.strptime(due, '%Y-%m-%d %H:%M:%S.%f')
d = {
'due_date':due,
}
patchDB(d, 'http://localhost:8000/api/assignments/' + aname + "/")
print("Due-date changed " + due)
except: except:
print("Due-date format is incorrect") print("Due-date is the same")
return
input() input()
parts = path.split("/")
aname = parts[len(parts)-1]
course = getDB("http://127.0.0.1:8000/api/classes/" + course) course = getDB("http://127.0.0.1:8000/api/classes/" + course)
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name']) slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd() cdir = os.getcwd()
@ -654,12 +601,12 @@ class Teacher:
data = getTeacher("eharris1") data = getTeacher("eharris1")
t = Teacher(data) t = Teacher(data)
# t.makeClass("APLit_eharris1") #t.addClass("eharris1/APLit_eharris1")
#t.addAssignment("eharris1/APLit_eharris1/Lab3_APLit_eharris1", "APLit_eharris1", '2020-08-11 16:58:33.383124') #t.addAssignment("eharris1/APLit_eharris1/Essay1_eharris1", "APLit_eharris1", '2020-08-11 16:58:33.383124')
#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.reqStudent('2022rkhondak', 'APLit_eharris1')
# t.getChanges('2022rkhondak','APLit_eharris1', 10) # t.getChanges('2022rkhondak','APLit_eharris1', 10)
''' '''

View File

@ -2,7 +2,7 @@ from django.contrib import admin
from .models import ( from .models import (
DefFiles, DefFiles,
Assignment, Assignment,
Classes, Class,
Teacher, Teacher,
Student Student
) )
@ -13,4 +13,4 @@ admin.site.register(Teacher)
admin.site.register(Student) admin.site.register(Student)
admin.site.register(DefFiles) admin.site.register(DefFiles)
admin.site.register(Assignment) admin.site.register(Assignment)
admin.site.register(Classes) admin.site.register(Class)

View File

@ -1,3 +1,7 @@
from django.contrib.auth.models import Group
g, created = Group.objects.get_or_create(name='teachers')
# from datetime import datetime # from datetime import datetime
# #
# f1 = DefFiles( # f1 = DefFiles(
@ -30,7 +34,7 @@
# #
# #################################### # ####################################
# #
# from api.models import Assignment, Student, Classes, Teacher, DefFiles # from api.models import Assignment, Student, Class, Teacher, DefFiles
# from datetime import datetime # from datetime import datetime
# #
# f1 = DefFiles( # f1 = DefFiles(
@ -76,8 +80,8 @@
# A3.files.add(f4) # A3.files.add(f4)
# A3.save() # A3.save()
# #
# #classes # #Class
# math = Classes( # math = Class(
# name='Math5', # name='Math5',
# #
# ) # )
@ -86,7 +90,7 @@
# math.assignments.add(A2) # math.assignments.add(A2)
# math.save() # math.save()
# #
# english = Classes( # english = Class(
# name='English', # name='English',
# ) # )
# english.save() # english.save()
@ -104,8 +108,8 @@
# repo="https://github.com/therealraffi/2022rkhondak.git", # repo="https://github.com/therealraffi/2022rkhondak.git",
# ) # )
# raffu.save() # raffu.save()
# raffu.classes.add(math) # raffu.Class.add(math)
# raffu.classes.add(english) # raffu.Class.add(english)
# raffu.save() # raffu.save()
# #
# #teachers # #teachers
@ -115,7 +119,7 @@
# ion_user="eharris1" # ion_user="eharris1"
# ) # )
# ng.save() # ng.save()
# ng.classes.add(math) # ng.Class.add(math)
# ng.save() # ng.save()
# #
# chao = Teacher( # chao = Teacher(
@ -124,5 +128,5 @@
# ion_user="AKBailey" # ion_user="AKBailey"
# ) # )
# chao.save() # chao.save()
# chao.classes.add(english) # chao.Class.add(english)
# chao.save() # chao.save()

View File

@ -1,75 +0,0 @@
# 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):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='DefFiles',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=100)),
('path', models.CharField(max_length=100)),
('assignment', models.CharField(default='', max_length=100)),
('classes', models.CharField(max_length=100)),
('teacher', models.CharField(max_length=100)),
],
),
migrations.CreateModel(
name='Teacher',
fields=[
('created', models.DateTimeField(auto_now_add=True)),
('first_name', models.CharField(max_length=100)),
('last_name', models.CharField(max_length=100)),
('classes', models.CharField(blank=True, default='', max_length=100)),
('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)),
],
),
]

View File

@ -1,52 +0,0 @@
# 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,43 +0,0 @@
# 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,18 +0,0 @@
# 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,12 +1,24 @@
from django.db import models from django.db import models
from django.contrib.auth.models import User from django.contrib.auth.models import User
import secrets
class DefFiles(models.Model):
name=models.CharField(max_length=100)
path=models.CharField(max_length=100) class Student(models.Model):
assignment=models.CharField(max_length=100, default="") user = models.OneToOneField(User, on_delete=models.CASCADE)
classes=models.CharField(max_length=100) ion_user = models.CharField(max_length=100, primary_key=True)
teacher=models.CharField(max_length=100) 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):
super(Student, self).save(*args, **kwargs)
def __str__(self):
return f"{self.user.username}'s Profile"
class Assignment(models.Model): class Assignment(models.Model):
owner = models.ForeignKey('auth.User', related_name='assignments', on_delete=models.CASCADE) owner = models.ForeignKey('auth.User', related_name='assignments', on_delete=models.CASCADE)
@ -21,44 +33,59 @@ class Assignment(models.Model):
def __str__(self): def __str__(self):
return '%s' % (self.name) return '%s' % (self.name)
class Classes(models.Model): class Class(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) owner = models.ForeignKey('auth.User', related_name='classes', on_delete=models.CASCADE)
teacher = models.CharField(max_length=100)
name = models.CharField(primary_key=True, max_length=100) name = models.CharField(primary_key=True, max_length=100)
id = models.CharField(max_length=8, blank=True, null=True)
description = models.CharField(default="Class Description", max_length=500)
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="")
teacher=models.CharField(max_length=100, default="") assignments=models.ManyToManyField(Assignment, blank=True)
assignments=models.TextField(default="", blank=True)
default_file=models.CharField(max_length=100, default="", blank=True) default_file=models.CharField(max_length=100, default="", blank=True)
confirmed=models.TextField(default="", blank=True) confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed')
unconfirmed=models.TextField(default="", blank=True) unconfirmed=models.ManyToManyField(Student, blank=True, related_name='unconfirmed')
# assignments = models.ManyToManyField(Assignment, default="") # assignments = models.ManyToManyField(Assignment, default="")
# default_file = models.ManyToManyField(DefFiles) # default_file = models.ManyToManyField(DefFiles)
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
return super(Classes, self).save(*args, **kwargs) id = self.id
if not id:
id = secrets.token_urlsafe()[:8].lower()
while Class.objects.filter(id=id).exclude(pk=self.pk).exists():
id = sercrets.token_urlsafe()[:8].lower()
self.id = id
return super(Class, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Teacher(models.Model): class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) user = models.OneToOneField(User, on_delete=models.CASCADE)
# classes = models.ManyToManyField(Classes, default="") classes=models.ManyToManyField(Class, blank=True, related_name='classes')
classes=models.CharField(max_length=100, default="", blank=True) git=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)
def __str__(self):
return f"{self.user.username}'s Profile"
def save(self, *args, **kwargs): def save(self, *args, **kwargs):
super(Teacher, self).save(*args, **kwargs) super(Teacher, self).save(*args, **kwargs)
class Student(models.Model): # class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE) # user = models.OneToOneField(User, on_delete=models.CASCADE)
grade = models.IntegerField(default=0, blank=True) # ion_user=models.CharField(primary_key=True, max_length=100)
git=models.CharField(default="", max_length=100, blank=True) # grade = models.IntegerField(default=0, blank=True)
repo=models.URLField(default="", blank=True) # git=models.CharField(default="", max_length=100, blank=True)
classes=models.CharField(max_length=100, default="", blank=True) # repo=models.URLField(default="", blank=True)
added_to=models.CharField(max_length=100, default="", blank=True) # classes=models.CharField(max_length=100, default="", blank=True)
completed=models.TextField(default="", blank=True) # added_to=models.CharField(max_length=100, default="", blank=True)
# completed=models.TextField(default="", blank=True)
def save(self, *args, **kwargs):
super(Student, self).save(*args, **kwargs)
def __str__(self): class DefFiles(models.Model):
return f"{self.user.username}'s Profile" name=models.CharField(max_length=100)
path=models.CharField(max_length=100)
assignment=models.CharField(max_length=100, default="")
classes=models.CharField(max_length=100)
teacher=models.CharField(max_length=100)

View File

@ -13,7 +13,7 @@ class IsOwnerOrReadOnly(permissions.BasePermission):
return True return True
# Write permissions are only allowed to the owner of the snippet. # Write permissions are only allowed to the owner of the snippet.
return obj.owner == request.user or request.user.is_superuser return obj.user == request.user or request.user.is_superuser
class isTeacher(permissions.BasePermission): class isTeacher(permissions.BasePermission):
#only teachers can make classes and assignmenst #only teachers can make classes and assignmenst

View File

@ -1,12 +1,12 @@
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, Class, Assignment, DefFiles
from rest_framework import serializers, permissions from rest_framework import serializers, permissions
from django.contrib.auth.models import User from django.contrib.auth.models import User
from .permissions import IsOwnerOrReadOnly,isTeacher from .permissions import IsOwnerOrReadOnly,isTeacher
class UserSerializer(serializers.HyperlinkedModelSerializer): class UserSerializer(serializers.HyperlinkedModelSerializer):
students = serializers.PrimaryKeyRelatedField(many=True, queryset=Student.objects.all()) # students = serializers.PrimaryKeyRelatedField(many=True, queryset=Student.objects.all())
teachers = serializers.PrimaryKeyRelatedField(many=True, queryset=Teacher.objects.all()) # teachers = serializers.PrimaryKeyRelatedField(many=True, queryset=Teacher.objects.all())
class Meta: class Meta:
model = User model = User
@ -15,41 +15,38 @@ class UserSerializer(serializers.HyperlinkedModelSerializer):
# class DefFilesSerializer(serializers.HyperlinkedModelSerializer): # class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
# class Meta: # class Meta:
# model = DefFiles # model = DefFiles
# fields = ['name', 'path','assignment','classes', "teacher",'url', 'id'] # fields = ['name', 'path','assignment','Class', "teacher",'url', 'id']
class AssignmentSerializer(serializers.HyperlinkedModelSerializer): class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
#permissions_classes = [permissions.IsAuthenticatedOrReadOnly] #permissions_Class = [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') owner = serializers.ReadOnlyField(source='owner.username')
class Meta: class Meta:
model = Assignment model = Assignment
# fields = ['url','name', 'due_date', 'path' , "classes","teacher",'owner'] # fields = ['url','name', 'due_date', 'path' , "Class","teacher",'owner']
fields = ['name', 'due_date', 'path' , "classes","teacher",'owner'] fields = ['name', 'due_date', 'path' ,"teacher",'owner']
class ClassesSerializer(serializers.HyperlinkedModelSerializer): class ClassSerializer(serializers.ModelSerializer):
# 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') #owner = serializers.ReadOnlyField(source='owner.username')
class Meta: class Meta:
model = Classes model = Class
# fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner'] # fields = ['url','name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner']
fields = ['name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner'] fields = ['name', 'repo','path','assignments',"teacher","default_file", 'confirmed', 'unconfirmed','owner']
class StudentSerializer(serializers.HyperlinkedModelSerializer): class StudentSerializer(serializers.ModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True) # Class = ClassSerializer(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','owner'] # fields = ['url','first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','Class','added_to','completed', 'repo','owner']
fields = ['first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo','owner'] fields = ['url','grade', 'ion_user','git','user','classes','added_to','completed', 'repo']
class TeacherSerializer(serializers.ModelSerializer): class TeacherSerializer(serializers.ModelSerializer):
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True) #classes = ClassSerializer(many=True, read_only=True,allow_null=True)
owner = serializers.ReadOnlyField(source='owner.username') #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','owner'] # fields = ['url','first_name', 'last_name','git','ion_user', 'email','Class','owner']
fields = ['first_name', 'last_name','git','ion_user', 'email','classes','owner'] fields = ['git','ion_user','classes','user']

View File

@ -9,8 +9,8 @@ urlpatterns = [
path('teachers/<str:pk>/', views.TeacherDetail.as_view()), path('teachers/<str:pk>/', views.TeacherDetail.as_view()),
path('assignments/', views.AssignmentList.as_view()), path('assignments/', views.AssignmentList.as_view()),
path('assignments/<str:pk>/', views.AssignmentDetail.as_view()), path('assignments/<str:pk>/', views.AssignmentDetail.as_view()),
path('classes/', views.ClassesList.as_view()), path('classes/', views.ClassList.as_view()),
path('classes/<str:pk>/', views.ClassesDetail.as_view()), path('classes/<str:pk>/', views.ClassDetail.as_view()),
] ]
urlpatterns = format_suffix_patterns(urlpatterns) urlpatterns = format_suffix_patterns(urlpatterns)

View File

@ -1,5 +1,5 @@
from .models import Student, Teacher, Classes, Assignment, DefFiles from .models import Student, Teacher, Class, Assignment, DefFiles
from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer from .serializers import StudentSerializer, TeacherSerializer, ClassSerializer, 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
@ -8,13 +8,13 @@ from .permissions import isTeacher, IsOwnerOrReadOnly
from django.shortcuts import render, redirect from django.shortcuts import render, redirect
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser
from rest_framework.response import Response from rest_framework.response import Response
from django.contrib.auth.models import Group
class UserViewSet(viewsets.ModelViewSet): class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all() queryset = User.objects.all()
serializer_class = UserSerializer serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated] permission_Class = [permissions.IsAuthenticated]
class StudentViewSet(viewsets.ModelViewSet): class StudentViewSet(viewsets.ModelViewSet):
@ -23,10 +23,10 @@ class StudentViewSet(viewsets.ModelViewSet):
""" """
queryset = Student.objects.all() queryset = Student.objects.all()
serializer_class = StudentSerializer serializer_class = StudentSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly] permission_Class = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(owner=self.request.user) serializer.save(user=self.request.user)
class TeacherViewSet(viewsets.ModelViewSet): class TeacherViewSet(viewsets.ModelViewSet):
""" """
@ -34,25 +34,25 @@ class TeacherViewSet(viewsets.ModelViewSet):
""" """
queryset = Teacher.objects.all() queryset = Teacher.objects.all()
serializer_class = TeacherSerializer serializer_class = TeacherSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly] permission_Class = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(owner=self.request.user) serializer.save(user=self.request.user)
class ClassesViewSet(viewsets.ModelViewSet): class ClassViewSet(viewsets.ModelViewSet):
""" """
API endpoint that allows users to be viewed or edited. API endpoint that allows users to be viewed or edited.
""" """
queryset = Classes.objects.all() queryset = Class.objects.all()
serializer_class = ClassesSerializer serializer_class = ClassSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly] permission_Class = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
def perform_create(self, serializer): # def perform_create(self, serializer):
if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser): # if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
serializer.save(owner=self.request.user) # serializer.save(owner=self.request.user)
else: # else:
print("UNAUTHORIZED POST") # print("UNAUTHORIZED POST")
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class AssignmentViewSet(viewsets.ModelViewSet): class AssignmentViewSet(viewsets.ModelViewSet):
@ -61,7 +61,7 @@ class AssignmentViewSet(viewsets.ModelViewSet):
""" """
queryset = Assignment.objects.all() queryset = Assignment.objects.all()
serializer_class = AssignmentSerializer serializer_class = AssignmentSerializer
permission_classes = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly] permission_Class = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly]
def perform_create(self, serializer): def perform_create(self, serializer):
if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser): if(self.request.user.groups.filter(name__in=['teachers']).exists() or self.request.user.is_superuser):
@ -76,4 +76,4 @@ class AssignmentViewSet(viewsets.ModelViewSet):
# """ # """
# queryset = DefFiles.objects.all() # queryset = DefFiles.objects.all()
# serializer_class = DefFilesSerializer # serializer_class = DefFilesSerializer
# permissions_classes = [permissions.IsAuthenticatedOrReadOnly] # permissions_Class = [permissions.IsAuthenticatedOrReadOnly]

View File

@ -9,7 +9,7 @@ router = routers.DefaultRouter()
router.register(r'students', api_views.StudentViewSet) router.register(r'students', api_views.StudentViewSet)
router.register(r'teachers', api_views.TeacherViewSet) router.register(r'teachers', api_views.TeacherViewSet)
router.register(r'assignments', api_views.AssignmentViewSet) router.register(r'assignments', api_views.AssignmentViewSet)
router.register(r'classes', api_views.ClassesViewSet) router.register(r'classes', api_views.ClassViewSet)
# router.register(r'files', api_views.DefFilesViewSet) # router.register(r'files', api_views.DefFilesViewSet)
router.register(r'users', api_views.UserViewSet) router.register(r'users', api_views.UserViewSet)

28
Website/skoolos/forms.py Normal file
View File

@ -0,0 +1,28 @@
from django import forms
from django.contrib.auth.models import User
from api.models import Student, Teacher
import re
class UserUpdateForm(forms.ModelForm):
username = forms.CharField(max_length=50, disabled=True)
first_name = forms.CharField(max_length=50, disabled=True)
last_name = forms.CharField(max_length=50, disabled=True)
email = forms.EmailField()
def __init__(self, *args, **kwargs):
super(UserUpdateForm, self).__init__(*args, **kwargs)
class Meta:
model = User
fields = ['username','first_name','last_name','email']
class StudentUpdateForm(forms.ModelForm):
class Meta:
model = Student
fields = ['git']
class TeacherUpdateForm(forms.ModelForm):
class Meta:
model = Teacher
fields = ['git']

View File

@ -13,22 +13,20 @@ body {
color: #333333; color: #333333;
margin-top: 5rem; margin-top: 5rem;
font-family: 'Segoe UI'; font-family: 'Segoe UI';
margin-left: 2.5rem;
margin-right: 2.5rem;
} }
h1, h2, h3, h4, h5, h6 { h1, h2, h3, h4, h5, h6 {
color: #444444; color: #444444;
} }
ul {
margin: 0;
}
.bg-steel { .bg-steel {
background: #3cba54; background: #3cba54;
} }
.site-header .navbar-nav .nav-link { .site-header .navbar-nav .nav-link {
color: #cbd5db; color: #e1e1e1;
} }
.site-header .navbar-nav .nav-link:hover { .site-header .navbar-nav .nav-link:hover {
@ -69,7 +67,8 @@ a.article-title:hover {
.article-metadata { .article-metadata {
padding-bottom: 1px; padding-bottom: 1px;
margin-bottom: 4px; margin-bottom: 4px;
border-bottom: 1px solid #e3e3e3 border-bottom: 1px solid #e3e3e3;
font-size: 1.5em;
} }
.article-metadata a:hover { .article-metadata a:hover {
@ -93,8 +92,3 @@ a.article-title:hover {
.account-heading { .account-heading {
font-size: 2.5rem; font-size: 2.5rem;
} }
.nounderline {
text-decoration: none !important;
color: black !important;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -21,8 +21,8 @@
<nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top"> <nav class="navbar navbar-expand-md navbar-dark bg-steel fixed-top">
<div class="container"> <div class="container">
<a class="navbar-brand" href="#"> <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=""> <img src="{% static 'skoolos/tj_trans.png' %}" width="30" height="30" class="d-inline-block align-top" alt="">
Bootstrap SkoolOS
</a> </a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarToggle" aria-controls="navbarToggle" aria-expanded="false" aria-label="Toggle navigation"> <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> <span class="navbar-toggler-icon"></span>
@ -43,6 +43,16 @@
</nav> </nav>
</header> </header>
{% if messages %}
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show">
{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
{% endif %}
{% block content %}{% endblock %} {% block content %}{% endblock %}
<!-- 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>

View File

@ -0,0 +1,28 @@
{% extends "skoolos/base.html" %}
{% block content %}
<div class="row">
<div class="col-md-8">
<h4>Assignments:</h4>
<hr>
{% for assignment in assignments %}
<article class="media content-section">
<div class="media-body">
<a class="mr-2" href="#">{{ assignment }}</a>
<small class="text-muted">Due: {{ assignment.due_date|date:"F d, Y" }}</small>
</div>
</article>
{% endfor %}
</div>
<div class="col-md-4 content-section">
<h3>{{ class.name }}</h3>
<p>Teachers:</p>
<ul>
{% for teacher in teachers %}
<li>{{ teacher.user.first_name }} {{ teacher.user.last_name }} ({{teacher.ion_user}})</li>
{% endfor %}
</ul>
</div>
</div>
</div>
{% endblock content %}

View File

@ -1,3 +1,15 @@
{% extends "skoolos/base.html" %} {% extends "skoolos/base.html" %}
{% block content %} {% block content %}
<div class="content-section">
{% for class in classes %}
<div class="card-columns">
<a class="card" href="/class/{{ class.id }}" style="text-decoration: none;">
<div class="card-body">
<h5 class="card-title">{{ class.name }}</h5>
<p class="card-text">{{ class.description }}</p>
</div>
</a>
</div>
{% endfor %}
</div>
{% endblock content %} {% endblock content %}

View File

@ -0,0 +1,34 @@
{% extends "skoolos/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary">
{{ user.email }}
<a href="https://github.com/{{ user.student.git }}" target="_blank">GitHub</a>
</p>
</div>
</div>
<legend class="border-bottom mb-4">Classes</legend>
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Your profile </legend>
{{ userForm|crispy}}
{{ profileForm|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-outline-info">Update</button>
</div>
</form>
</div>
</div>
{% endblock content %}

View File

@ -0,0 +1,34 @@
{% extends "skoolos/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<div class="content-section">
<div class="media">
<div class="media-body">
<h2 class="account-heading">{{ user.username }}</h2>
<large>{{ user.first_name }} {{ user.last_name }}</large>
<p class="text-secondary">
{{ user.email }}
<a href="https://github.com/{{ user.student.git }}" target="_blank">GitHub</a>
</p>
</div>
</div>
<legend class="border-bottom mb-4">Classes</legend>
<ul>
{% for class in classes %}
<li>{{ class.name }}</li>
{% endfor %}
</ul>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4"> Your profile </legend>
{{ userForm|crispy}}
{{ profileForm|crispy }}
</fieldset>
<div class="form-group">
<button type="submit" class="btn btn-outline-info">Update</button>
</div>
</form>
</div>
</div>
{% endblock content %}

View File

@ -5,5 +5,6 @@ from . import views
# Additionally, we include login URLs for the browsable API. # Additionally, we include login URLs for the browsable API.
urlpatterns = [ urlpatterns = [
path('', views.home, name='home'), path('', views.home, name='home'),
path('profile/', views.profile, name='profile') path('profile/', views.profile, name='profile'),
path("class/<str:id>", views.classDetail, name="class"),
] ]

View File

@ -1,12 +1,119 @@
from django.shortcuts import render from django.shortcuts import render, redirect
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.views.generic import ListView
from django.contrib import messages
from django.contrib.auth.models import User
from .forms import UserUpdateForm, StudentUpdateForm, TeacherUpdateForm
from api.models import Student, Teacher, Class, Assignment
# Create your views here. # Create your views here.
@login_required() @login_required()
def home (request): def home (request):
try:
student = Student.objects.get(user=request.user)
return render(request, "skoolos/home.html", {'classes': student.confirmed.all()})
except Student.DoesNotExist:
pass
try:
teacher = Teacher.objects.get(user=request.user)
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()})
except Teacher.DoesNotExist:
pass
return render(request, "skoolos/home.html") return render(request, "skoolos/home.html")
@login_required() @login_required()
def profile (request): def profile (request):
pass pass
@login_required()
def classDetail (request, id):
classObj = Class.objects.get(id=id)
try:
student = Student.objects.get(user=request.user)
except Student.DoesNotExist:
pass
else:
if classObj.confirmed.filter(user=student.user).count() != 1:
return redirect('/')
else:
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()})
try:
teacher = Teacher.objects.get(user=request.user)
return render(request, "skoolos/home.html", {'classes': teacher.classes.all()})
except Teacher.DoesNotExist:
pass
else:
if classObj.confirmed.filter(user=student.user).count() != 1:
return redirect('/')
else:
return render(request, "skoolos/class_detail.html", {'class': classObj,'assignments': classObj.assignments.all(), 'teachers': classObj.classes.all()})
return redirect('/')
@login_required()
def profile (request):
try:
student = Student.objects.get(user=request.user)
return student_profile(request)
except Student.DoesNotExist:
pass
try:
teacher = Teacher.objects.get(user=request.user)
return teacher_profile(request)
except Teacher.DoesNotExist:
pass
return redirect("/")
def student_profile (request):
if request.method == "POST":
userForm = UserUpdateForm(request.POST, instance=request.user)
profileForm = StudentUpdateForm(request.POST,
instance=request.user.student)
if userForm.is_valid() and profileForm.is_valid():
userForm.save()
profileForm.save()
messages.success(request, "Your account has been updated!")
return redirect('profile')
else:
userForm = UserUpdateForm(instance=request.user)
profileForm = StudentUpdateForm(instance=request.user.student)
context = {
'userForm': userForm,
'profileForm': profileForm,
'classes': request.user.student.confirmed.all()
}
return render(request, 'skoolos/profile_student.html', context)
def teacher_profile (request):
if request.method == "POST":
userForm = UserUpdateForm(request.POST, instance=request.user)
profileForm = TeacherUpdateForm(request.POST,
instance=request.user.student)
if userForm.is_valid() and profileForm.is_valid():
userForm.save()
profileForm.save()
messages.success(request, "Your account has been updated!")
return redirect('profile')
else:
userForm = UserUpdateForm(instance=request.user)
profileForm = TeacherUpdateForm(instance=request.user.student)
context = {
'userForm': userForm,
'profileForm': profileForm,
'classes': request.user.teacher.classes.all()
}
return render(request, 'skoolos/profile_teacher.html', context)

View File

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

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

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

@ -8,6 +8,7 @@ from django.contrib import messages
from .models import Token from .models import Token
from api.models import Student, Teacher from api.models import Student, Teacher
from django.contrib.auth.models import Group
from .forms import UserCreationForm from .forms import UserCreationForm
@ -97,15 +98,18 @@ def create_account (request):
last_name=last_name, last_name=last_name,
password=password) password=password)
user.save() user.save()
token.delete() g, created = Group.objects.get_or_create(name='teachers')
if isStudent: if isStudent:
profile = Student(user=user, git=git, grade=grade) profile = Student(user=user, git=git, grade=grade, ion_user=username)
else: else:
profile = Teacher(user=user, git=git) profile = Teacher(user=user, git=git, ion_user=username)
group = Group.objects.get(name='teachers')
user.groups.add(group)
profile.save() profile.save()
token.delete()
print (user) print (user)
messages.success(request, "Your SkoolOS account has successfully been created") messages.success(request, "Your SkoolOS account has successfully been created")
return redirect(f'/login/?username={username}') return redirect(f'/login/?username={username}')
@ -145,4 +149,4 @@ def create_account (request):
def logout(request): def logout(request):
auth_logout(request) auth_logout(request)
messages.success(request, "You've been logged out!") messages.success(request, "You've been logged out!")
return redirect(request, "/login") return redirect("/login")

122
bgservice/bgservice.py Normal file
View File

@ -0,0 +1,122 @@
import time
import sys
import os
import pyinotify
import checker
class EventHandler(pyinotify.ProcessEvent):
_methods = [
"IN_CREATE",
"IN_CLOSE_WRITE",
"IN_DELETE",
"IN_MOVED_TO",
"IN_MOVED_FROM",
"IN_OPEN",
]
def process_IN_CREATE(self, event):
description = \
"Event: Created file\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
def process_IN_CLOSE_WRITE(self, event):
description = \
"Event: Wrote to a file\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
def process_IN_DELETE(self, event):
description = \
"Event: Deleted file\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
def process_IN_MOVED_TO(self, event):
description = \
"Event: Moved a file in\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
def process_IN_MOVED_FROM(self, event):
description = \
"Event: Moved a file out\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
def process_IN_OPEN(self, event):
description = \
"Event: Opened file\n" \
"Event Path: {}\n" \
"Timestamp: {}\n".format(
event.pathname,
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime())
)
print(description)
NOTIFIER = None
STDOUT = sys.stdout
DIR = None
START_TIME = None
def watch_dir(watched_dir="/tmp", logdir="/tmp/skooloslogs"):
global DIR
global START_TIME
global NOTIFIER
DIR = watched_dir
if not os.path.exists(logdir):
os.makedirs(logdir)
logfile = open(
logdir + "/skoolos_" +
time.strftime("%m%d%Y-%H%M%S", time.localtime()), 'w')
sys.stdout = logfile
START_TIME = time.time()
print("Start time: " +
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime()) + "\n\n")
wm = pyinotify.WatchManager()
mask = pyinotify.IN_CREATE | pyinotify.IN_CLOSE_WRITE | pyinotify.IN_DELETE | \
pyinotify.IN_MOVED_TO | pyinotify.IN_MOVED_FROM | pyinotify.IN_OPEN
NOTIFIER = pyinotify.ThreadedNotifier(wm, EventHandler())
NOTIFIER.start()
wm.add_watch(watched_dir, mask, rec=True)
def stop_watching():
NOTIFIER.stop()
now = time.time()
print("End time: " +
time.strftime("%A, %B %d, %Y %H:%M:%S", time.localtime()))
print("\nTotal work time: " +
time.strftime("%H:%M:%S", time.gmtime(now - START_TIME)))
suspicious_files = checker.file_check(DIR)
if suspicious_files != []:
print(
"\n\n--------------------------------------------------\n\n\n" +
"WARNING: One or more file did not have file extensions that are acceptable.\n"
+ "The paths to these files are listed below:\n")
print(*suspicious_files, sep='\n')
sys.stdout = STDOUT
print("Done watching.\n")

100
bgservice/checker.py Normal file
View File

@ -0,0 +1,100 @@
import os
from glob import glob
file_whitelist = [
# text and document files
".doc",
".docx",
".odt",
".pdf",
".rtf",
".tex",
".txt",
".wpd",
# video files
".3g2",
".3gp",
".avi",
".flv",
".h264",
".m4v",
".mkv",
".mov",
".mp4",
".mpg",
".mpeg",
".rm",
".swf",
".vob",
".wmv",
# spreadsheet files
".ods",
".xls",
".xlsm",
".xlsx",
".csv",
# programming files
".c",
".class",
".cpp",
".cs",
".go",
".h",
".java",
".pl",
".sh",
".swift",
".vb",
# presentation files
".key",
".odp",
".pps",
".ppt",
".pptx",
# image files
".ai",
".bmp",
".gif",
".ico",
".jpeg",
".jpg",
".png",
".ps",
".psd",
".svg",
".tif",
".tiff",
]
def shell_check():
bash_history = [
line.strip()
for line in open(os.path.expanduser("~/.bash_history"), 'r')
]
zsh_history = [
line.strip() for line in open(os.path.expanduser("~/.histfile"), 'r')
]
report = "Suspicios commands found:\n"
for i in bash_history + zsh_history:
if "git" in i:
report += i + "\n"
if report != "Suspicios commands found:\n":
return report
return "Nothing suspicious found in bash or zsh history."
def verify_file(file_):
for ext in file_whitelist:
if file_[len(file_) - len(ext):] == ext:
return True
return False
def file_check(dir_):
files = glob(dir_ + "/**/*", recursive=True)
suspicious_files = []
for file_ in files:
if not verify_file(file_):
suspicious_files.append(file_)
return suspicious_files

View File

View File

@ -1,27 +1,63 @@
appdirs==1.4.3
arandr==0.1.10
asgiref==3.2.7 asgiref==3.2.7
astroid==2.4.2
CacheControl==0.12.6
certifi==2020.4.5.1 certifi==2020.4.5.1
chardet==3.0.4 chardet==3.0.4
click==7.1.2 click==7.1.2
colorama==0.4.3
contextlib2==0.6.0
distlib==0.3.0
distro==1.4.0
Django==3.0.7 Django==3.0.7
django-cors-middleware==1.5.0 django-cors-middleware==1.5.0
django-crispy-forms==1.9.1 django-crispy-forms==1.9.1
django-oauth-toolkit==1.3.2 django-oauth-toolkit==1.3.2
djangorestframework==3.11.0 djangorestframework==3.11.0
greenlet==0.4.16
html5lib==1.0.1
idna==2.9 idna==2.9
isort==4.3.21
lazy-object-proxy==1.4.3
mccabe==0.6.1
meson==0.53.2
msgpack==0.6.2
numpy==1.18.5
oauthlib==3.1.0 oauthlib==3.1.0
ordered-set==3.1.1
packaging==20.1
pep517==0.8.1
Pillow==7.1.2
progress==1.5
prompt-toolkit==1.0.14 prompt-toolkit==1.0.14
pulsemixer==1.5.0
pycairo==1.19.1
pyclipper==1.1.0.post3 pyclipper==1.1.0.post3
Pygments==2.6.1 Pygments==2.6.1
PyGObject==3.34.0
pyinotify==0.9.6 pyinotify==0.9.6
PyInquirer==1.0.3 PyInquirer==1.0.3
pylint==2.5.3
pynvim==0.4.1
pyparsing==2.4.6
pyperclip==1.8.0 pyperclip==1.8.0
pytoml==0.1.21
pytz==2020.1 pytz==2020.1
pywal==3.3.0
regex==2020.5.14 regex==2020.5.14
requests==2.23.0 requests==2.23.0
requests-oauthlib==1.3.0 requests-oauthlib==1.3.0
retrying==1.3.3
selenium==3.141.0 selenium==3.141.0
six==1.15.0 six==1.15.0
sqlparse==0.3.1 sqlparse==0.3.1
team==1.0
toml==0.10.0
urllib3==1.25.9 urllib3==1.25.9
wcwidth==0.2.3 wcwidth==0.2.3
webencodings==0.5.1
Werkzeug==1.0.1 Werkzeug==1.0.1
wpgtk==6.1.3
wrapt==1.12.1
yapf==0.30.0

View File

@ -12,8 +12,10 @@ from werkzeug.urls import url_decode
import pprint import pprint
from PyInquirer import prompt, print_json from PyInquirer import prompt, print_json
import json import json
import datetime
import os import os
import argparse import argparse
import webbrowser
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6' client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY' client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
@ -36,48 +38,123 @@ def main():
if not os.path.exists(".profile"): if not os.path.exists(".profile"):
try: try:
URL = "http://127.0.0.1:8000/api/" URL = "http://127.0.0.1:8000/api/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) r = requests.get(url = URL)
print("End service at http://127.0.0.1:8000/ before continuing.")
sys.exit(0)
except: except:
pass print("Run Django server on http://127.0.0.1:8000/ before continuing")
sys.exit(0)
input("Welcome to SkoolOS. Press any key to create an account") input("Welcome to SkoolOS. Press any key to create an account")
#webbrowser.open("http://127.0.0.1:8000/login", new=2)
authenticate() authenticate()
else: 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') f = open('.profile','r')
data = json.loads(f.read()) data = json.loads(f.read())
f.close() f.close()
PWD = data['password'] PWD = data['password']
USER = data['username'] USER = data['username']
print(data['username'])
if(data['is_student']): if(data['is_student']):
studentCLI() studentCLI(USER, PWD)
else: else:
teacherCLI() teacherCLI(USER, PWD)
# while True: # while True:
# pass # pass
def studentCLI(): def studentCLI(user, password):
from CLI import student from CLI import student
data = getStudent(USER) data = getUser(user, password)
print(data)
student = student.Student(data) student = student.Student(data)
print(student) carray = student.sclass.split(",")
if(len(carray) == 1 and carray[0] == ""):
print("No classes")
return
carray.append("Exit SkoolOS")
courses = [
{
'type': 'list',
'name': 'course',
'choices':carray,
'message': 'Select class: ',
},
]
course = prompt(courses)
if course == "Exit SkoolOS":
student.exitCLI()
else:
student.viewClass(course)
student.getAssignments(course, datetime.datetime.now())
def teacherCLI(): def teacherCLI(user, password):
from CLI.teacher import Teacher from CLI import teacher
print("fail") data = getUser(user, password)
teacher = teacher.Teacher(data)
# 1. make a class
# 2. add studeents to an existing class
# 3. Get progress logs on a student
# 2. make an assignment for a class
# 3. view student submissions for an assignment
carray = teacher.sclass.split(",")
carray.remove("")
carray.append("Exit SkoolOS")
carray.append("Make New Class")
courses = [
{
'type': 'list',
'name': 'course',
'choices':carray,
'message': 'Select class: ',
},
]
course = prompt(courses)
if course == "Exit SkoolOS":
teacher.exitCLI()
if course == "Make New Class":
questions = [
{
'type': 'input',
'name': 'cname',
'message': 'Class Name: ',
},
]
cname = prompt(questions)
teacher.makeClass(cname)
soption = ["1) Add individual student", "2) Add list of students through path", "3) Exit"]
questions = [
{
'type': 'list',
'choices':soption,
'name': 'students',
'message': 'Add list of students (input path): ',
},
]
choice = prompt(questions).split(")")
if("1" == choice):
s = input("Student name: ")
teacher.addStudent(s, cname)
if("2" == choice):
p = input("Relativee Path: ")
if(os.path.exists(p)):
print(p + " does not exist.")
def getStudent(ion_user): else:
print("Class: " + cname)
options = ['1) Add student', "2) Add assignment", "3) View student information"]
questions = [
{
'type': 'list',
'name': 'course',
'choices':options,
'message': 'Select option: ',
},
]
option = prompt(questions)
def getUser(ion_user, password):
URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/" URL = "http://127.0.0.1:8000/api/students/" + ion_user + "/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) r = requests.get(url = URL, auth=(ion_user,password))
if(r.status_code == 200): if(r.status_code == 200):
data = r.json() data = r.json()
return data return data
@ -90,6 +167,10 @@ def getStudent(ion_user):
else: else:
return None return None
print(r.status_code) print(r.status_code)
def patchDB(data, url):
r = requests.patch(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
print("PATH:" + str(r.status_code))
return(r.json())
def getDB(url): def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
@ -152,82 +233,97 @@ def authenticate():
path = os.path.join(os.getcwd(), 'chromedriver-mac') path = os.path.join(os.getcwd(), 'chromedriver-mac')
browser = webdriver.Chrome(path) browser = webdriver.Chrome(path)
web_dir = os.path.join(os.getcwd(), 'CLI', 'oauth') # web_dir = os.path.join(os.getcwd(), 'CLI', 'oauth')
print(web_dir) # 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")
template = open("template.html", "r") # template = open("template.html", "r")
index = open("index.html", "w") # index = open("index.html", "w")
for line in template: # for line in template:
index.write(line.replace('AUTH_URL', authorization_url)) # index.write(line.replace('AUTH_URL', authorization_url))
template.close() # template.close()
index.close() # index.close()
server = Thread(target=create_server) # server = Thread(target=create_server)
server.daemon = True # server.daemon = True
server.start() # server.start()
browser.get("localhost:8000/") browser.get("localhost:8000/login")
while "http://localhost:8000/callback/?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/login/?", ""))
while "http://localhost:8000/login/?username=" not in browser.current_url and (not browser.current_url == "http://localhost:8000/"): #http://localhost:8000/
time.sleep(0.25) time.sleep(0.25)
url = browser.current_url url = browser.current_url
gets = url_decode(url.replace("http://localhost:8000/callback/?", "")) gets = url_decode(url.replace("http://localhost:8000/login/?username=", ""))
while "http://localhost:8000/callback/?code" not in browser.current_url: # code = gets.get("code")
time.sleep(0.25) # if state == gets.get("state"):
# state = gets.get("state")
url = browser.current_url # print("states good")
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() browser.quit()
questions = [
{
'type': 'input',
'name': 'username',
'message': 'Enter SkoolOS Username (Same as ION Username): ',
},
{
'type': 'password',
'name': 'pwd',
'message': 'Enter SkoolOS Password (NOT ION PASSWORD): ',
},
]
data =prompt(questions)
pwd = data['pwd']
user = data['username']
r = requests.get(url = "http://localhost:8000/api/", auth=(user,pwd))
while(r.status_code != 200):
print("INCORRECT LOGIN CREDENTIALS")
r = requests.get(url = "http://localhost:8000/api/", auth=(user,pwd))
data =prompt(questions)
pwd = data['pwd']
user = data['username']
print(r.status_code)
r = requests.get(url = "http://localhost:8000/api/students/" + user + "/", auth=(user,pwd))
is_student = False
if(r.status_code == 200):
is_student = True
print("Welcome, student " + user)
r = requests.get(url = "http://localhost:8000/api/students/" + user + "/", auth=(user,pwd))
profile = r.json()
username = profile['ion_user']
grade = profile['grade']
profile = {
'username':username,
'grade':grade,
'is_student':is_student,
'password':pwd,
}
profileFile = open(".profile", "w")
profileFile.write(json.dumps(profile))
profileFile.close()
#print(code) else:
print(state) print("Welcome, teacher " + user)
r = requests.get(url = "http://localhost:8000/api/teachers/" + user + "/", auth=(user,pwd))
payload = {'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri, 'client_id': client_id, profile = r.json()
'client_secret': client_secret, 'csrfmiddlewaretoken': state} username = profile['ion_user']
token = requests.post("https://ion.tjhsst.edu/oauth/token/", data=payload).json() grade = profile['grade']
#print(token) profile = {
headers = {'Authorization': f"Bearer {token['access_token']}"} 'username':username,
'grade':grade,
# And finally get the user's profile! 'is_student':is_student,
profile = requests.get("https://ion.tjhsst.edu/api/profile", headers=headers).json() 'password':pwd,
}
#pprint.pprint(profile) profileFile = open(".profile", "w")
username = profile['ion_username'] profileFile.write(json.dumps(profile))
email = profile['tj_email'] profileFile.close()
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 sys.exit

100
snew.py Normal file
View File

@ -0,0 +1,100 @@
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
import webbrowser
import subprocess
from django.conf import settings
import django
from Website.config.settings import DATABASES, INSTALLED_APPS
INSTALLED_APPS.remove('users.apps.UsersConfig')
INSTALLED_APPS.remove('api')
INSTALLED_APPS.remove('skoolos.apps.SkoolosConfig')
INSTALLED_APPS.append('Website.api')
settings.configure(DATABASES=DATABASES, INSTALLED_APPS=INSTALLED_APPS)
django.setup()
from Website.api.models import *
def command(command):
ar = []
command = command.split(" ")
for c in command:
ar.append(c)
process = subprocess.Popen(ar, stdout=subprocess.PIPE,stderr=subprocess.PIPE)
p=process.poll()
output = process.communicate()[0]
print(output.decode('utf-8'))
return output.decode('utf-8')
class Students:
def __init__(self, username):
self.student = Student.objects.get(ion_user = username)
#ion id: student.user
if(os.path.isdir(self.student.user) == False):
if(self.student.repo == ""):
user= self.student.git
pwd= input("Enter Github password: ")
#curl -i -u USER:PASSWORD -d '{"name":"REPO"}' https://api.github.com/user/repos
url= "curl -i -u " + user + ":" + pwd + " -d '" + '{"name":"' + self.username + '"}' + "' " + "https://api.github.com/user/repos"
print(url)
os.system(url)
cdir = os.getcwd()
command('git clone https://github.com/' + self.git + '/' + self.username + '.git')
os.chdir(self.username)
command('git checkout master')
command('touch README.md')
command('git add README.md')
command('git commit -m "Hello"')
command('git push -u origin master')
os.chdir(cdir)
self.repo = 'https://github.com/' + self.git + '/' + self.username + '.git'
data={
'user':self.user,
'git':self.git,
'ion_user':self.username,
'added_to':self.snew,
'url':self.url,
'classes':self.sclass,
'grade':self.grade,
'completed':self.completed,
'repo':self.repo
}
print(putDB(data, self.url))
print("Synced to " + self.username)
# c = {
# 'name':'Math5'
# }
# c = Class.objects.get(name='Math5')
data = requests.get(url = "http://localhost:8000/api/classes/Math5", auth=('raffukhondaker','hackgroup1')).json()
r = requests.post(url = "http://localhost:8000/api/classes/", data={'name':'English11', 'teacher':'eharris1', 'owner':2}, auth=('raffukhondaker','hackgroup1'))
print("POST:" + str(r.json()))
# print(r.json())
# print(c.name)
# c = {
# 'classes':c
# }
# print(c)
r = requests.patch(url = "http://localhost:8000/api/teachers/eharris1/", data={'classes':['English11']}, auth=('raffukhondaker','hackgroup1'))
print(r.json())