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

View File

@ -9,7 +9,18 @@ import time
import pyperclip
from distutils.dir_util import copy_tree
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
#get teacher info from api
@ -33,6 +44,10 @@ def getDB(url):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
print("GET:" + str(r.status_code))
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):
r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1'))
@ -66,30 +81,14 @@ class Teacher:
def __init__(self, data):
# teacher info already stored in API
# intitialze fields after GET request
self.first_name=data['first_name']
self.last_name=data['last_name']
self.git=data['git']
self.username=data['ion_user']
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)
cid=data['classes'].split(",")
try:
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'])
#array
self.classes=data['classes']
if(os.path.isdir(self.username + "/Students")):
print("Synced to " + self.username)
else:
@ -151,44 +150,31 @@ class Teacher:
#make class from existing directory, add to git and api
def addClass(self, path):
if (self.checkClass(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)):
cpath = self.username + "/" + cname
data = {
"name": cname,
"repo": "",
"path": cpath,
"teacher": self.username,
"assignments": "",
"default_file": "",
"confirmed": "",
"unconfirmed": ""
"owner":self.id
}
#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
#upate self.classes
self.classes.append(data)
if(len(self.sclass)==0):
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
data = {
'classes':self.classes
}
putDB(teacher, self.url)
return teacher
print(self.username)
print(patchDB(data, 'http://127.0.0.1:8000/api/teachers/' + self.username + "/"))
#make a new class from scratch
#subject: string, assignments: list
@ -224,8 +210,7 @@ class Teacher:
# f.close()
# os.chdir(cdir)
data = self.addClass(path)
return data
self.addClass(path)
def deleteClass(self, path):
if(os.path.exists(path) == False):
@ -240,25 +225,12 @@ class Teacher:
print("DELETE: " + self.classes[i]['name'])
for i in range(len(self.classes)):
c = self.classes[i]
if(c['name'] == cname):
if(c == cname):
del self.classes[i]
s=""
#recreate sclass field, using ids
for c in self.classes:
s = s + str(c['name']) + ","
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))
# data={
# 'classes':self.classes,
# }
# print(patchDB(data, self.url))
delDB("http://127.0.0.1:8000/api/classes/" + cname + "/")
break
@ -282,53 +254,37 @@ class Teacher:
print(sname + " does not exist.")
return False
course = getDB("http://127.0.0.1:8000/api/classes/" + cname)
if(sname in course['unconfirmed']):
print (sname + " already requested.")
return True
if(sname in course['confirmed']):
print (sname + " alredy enrolled.")
return False
# if(sname in str(course['unconfirmed'])):
# print (sname + " already requested.")
# return True
# if(sname in str(course['confirmed'])):
# print (sname + " alredy enrolled.")
# return False
student = getDB("http://127.0.0.1:8000/api/students/" + sname)
try:
if(student['added_to']==""):
student['added_to']=course['name']
else:
student['added_to']=student['added_to']+ "," + course['name']
except:
print(sname + " does not exist.")
return False
print(student['added_to'])
s={
'first_name':student["first_name"],
'last_name':student["last_name"],
'git':student["git"],
'ion_user':student["ion_user"],
'student_id':student["student_id"],
'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']==""):
# student = getDB("http://127.0.0.1:8000/api/students/" + sname)
# try:
# if(student['added_to']==""):
# student['added_to']=course['name']
# else:
# student['added_to']=student['added_to']+ "," + course['name']
# except:
# print(sname + " does not exist.")
# return False
# print(student['added_to'])
# data={
# 'added_to':student['added_to'],
# }
# student = patchDB(data, "http://localhost:8000/api/students/" + student['ion_user'] + "/")
student = getDB( "http://localhost:8000/api/students/" + (sname)+ "/")
if(course['unconfirmed']==[]):
course['unconfirmed']=student['ion_user']
else:
course['unconfirmed']=course['unconfirmed']+ "," + student['ion_user']
course['unconfirmed']=course['unconfirmed'].append(student['ion_user'])
cinfo = {
"name": course['name'],
"repo": "",
"path": self.username + "/" + course['name'],
"teacher": self.username,
"assignments": course['assignments'],
"default_file": "",
"confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed']
}
print(putDB(cinfo, course['url']))
print(cinfo)
patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/")
return True
#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']+",", "")
cinfo = {
"name": course['name'],
"repo": "",
"path": course['path'],
"teacher": self.username,
"assignments": course['assignments'],
"default_file": "",
"confirmed": course["confirmed"],
"unconfirmed": course['unconfirmed']
}
print(putDB(cinfo, course['url']))
print(patchDB(cinfo, "http://localhost:8000/api/classes/" + course['name'] + "/"))
return True
#goes through list of studennts, tries to add, then request, return unconfirmed students
@ -417,10 +367,10 @@ class Teacher:
parts = path.split("/")
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.")
return False
if((parts[1] in self.sclass) == False):
if((parts[1] in str(self.classes)) == False):
print("Not in valid class directory")
return False
#parts of assignment name (Essay1, APLit)
@ -445,7 +395,7 @@ class Teacher:
return False
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.")
return False
@ -459,7 +409,7 @@ class Teacher:
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd()
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)
if(os.path.exists(spath + "/" + aname) == False):
os.mkdir(spath + "/" + aname)
@ -487,21 +437,14 @@ class Teacher:
}
postDB(ass, 'http://127.0.0.1:8000/api/assignments/')
if(course['assignments'] == ""):
course['assignments'] = aname
course['assignments'] = ass
else:
course['assignments'] = course['assignments'] + "," + aname
course['assignments'] = course['assignments'].append(ass)
cinfo = {
"name": course['name'],
"repo": "",
"path": course['path'],
"teacher": "eharris1",
"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
else:
print("Assignment already addedd")
@ -510,18 +453,22 @@ class Teacher:
#try to avoid
#copy modified assignments to student directories
def updateAssignment(self, path, course, due):
parts = path.split("/")
aname = parts[len(parts)-1]
if(os.path.isdir(path) == False):
print(path + " is not an assignment.")
return
try:
if(due != None or due == ""):
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:
print("Due-date format is incorrect")
return
print("Due-date is the same")
input()
parts = path.split("/")
aname = parts[len(parts)-1]
course = getDB("http://127.0.0.1:8000/api/classes/" + course)
slist = os.listdir(os.getcwd() + "/" + self.username + "/Students/" + course['name'])
cdir = os.getcwd()
@ -654,12 +601,12 @@ class Teacher:
data = getTeacher("eharris1")
t = Teacher(data)
# t.makeClass("APLit_eharris1")
#t.addAssignment("eharris1/APLit_eharris1/Lab3_APLit_eharris1", "APLit_eharris1", '2020-08-11 16:58:33.383124')
#t.addClass("eharris1/APLit_eharris1")
#t.addAssignment("eharris1/APLit_eharris1/Essay1_eharris1", "APLit_eharris1", '2020-08-11 16:58:33.383124')
#ar = ['2022rkhondak','2022inafi','2023rumareti']
#extra = t.reqAddStudentList(ar, "APLit_eharris1")
#print(extra)
# t.getStudents('2022rkhondak')
t.reqStudent('2022rkhondak', 'APLit_eharris1')
# t.getChanges('2022rkhondak','APLit_eharris1', 10)
'''

View File

@ -2,7 +2,7 @@ from django.contrib import admin
from .models import (
DefFiles,
Assignment,
Classes,
Class,
Teacher,
Student
)
@ -13,4 +13,4 @@ admin.site.register(Teacher)
admin.site.register(Student)
admin.site.register(DefFiles)
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
#
# 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
#
# f1 = DefFiles(
@ -76,8 +80,8 @@
# A3.files.add(f4)
# A3.save()
#
# #classes
# math = Classes(
# #Class
# math = Class(
# name='Math5',
#
# )
@ -86,7 +90,7 @@
# math.assignments.add(A2)
# math.save()
#
# english = Classes(
# english = Class(
# name='English',
# )
# english.save()
@ -104,8 +108,8 @@
# repo="https://github.com/therealraffi/2022rkhondak.git",
# )
# raffu.save()
# raffu.classes.add(math)
# raffu.classes.add(english)
# raffu.Class.add(math)
# raffu.Class.add(english)
# raffu.save()
#
# #teachers
@ -115,7 +119,7 @@
# ion_user="eharris1"
# )
# ng.save()
# ng.classes.add(math)
# ng.Class.add(math)
# ng.save()
#
# chao = Teacher(
@ -124,5 +128,5 @@
# ion_user="AKBailey"
# )
# chao.save()
# chao.classes.add(english)
# chao.Class.add(english)
# 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.contrib.auth.models import User
import secrets
class DefFiles(models.Model):
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)
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
ion_user = models.CharField(max_length=100, primary_key=True)
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):
owner = models.ForeignKey('auth.User', related_name='assignments', on_delete=models.CASCADE)
@ -21,44 +33,59 @@ class Assignment(models.Model):
def __str__(self):
return '%s' % (self.name)
class Classes(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Class(models.Model):
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)
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)
path=models.CharField(max_length=100, default="")
teacher=models.CharField(max_length=100, default="")
assignments=models.TextField(default="", blank=True)
assignments=models.ManyToManyField(Assignment, blank=True)
default_file=models.CharField(max_length=100, default="", blank=True)
confirmed=models.TextField(default="", blank=True)
unconfirmed=models.TextField(default="", blank=True)
confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed')
unconfirmed=models.ManyToManyField(Student, blank=True, related_name='unconfirmed')
# assignments = models.ManyToManyField(Assignment, default="")
# default_file = models.ManyToManyField(DefFiles)
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):
user = models.OneToOneField(User, on_delete=models.CASCADE)
# classes = models.ManyToManyField(Classes, default="")
classes=models.CharField(max_length=100, default="", blank=True)
classes=models.ManyToManyField(Class, blank=True, related_name='classes')
git=models.CharField(max_length=100, default="", blank=True)
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):
super(Teacher, self).save(*args, **kwargs)
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
grade = models.IntegerField(default=0, blank=True)
git=models.CharField(default="", max_length=100, blank=True)
repo=models.URLField(default="", blank=True)
classes=models.CharField(max_length=100, default="", blank=True)
added_to=models.CharField(max_length=100, default="", blank=True)
completed=models.TextField(default="", blank=True)
# class Student(models.Model):
# user = models.OneToOneField(User, on_delete=models.CASCADE)
# ion_user=models.CharField(primary_key=True, 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 DefFiles(models.Model):
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
# 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):
#only teachers can make classes and assignmenst

View File

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

View File

@ -9,8 +9,8 @@ urlpatterns = [
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()),
path('classes/', views.ClassList.as_view()),
path('classes/<str:pk>/', views.ClassDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)

View File

@ -1,5 +1,5 @@
from .models import Student, Teacher, Classes, Assignment, DefFiles
from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer
from .models import Student, Teacher, Class, Assignment, DefFiles
from .serializers import StudentSerializer, TeacherSerializer, ClassSerializer, AssignmentSerializer, UserSerializer
from rest_framework import generics, viewsets, permissions, response, status
from django.http import Http404
from rest_framework.views import APIView
@ -8,13 +8,13 @@ from .permissions import isTeacher, IsOwnerOrReadOnly
from django.shortcuts import render, redirect
from rest_framework.parsers import JSONParser
from rest_framework.response import Response
from django.contrib.auth.models import Group
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
permission_Class = [permissions.IsAuthenticated]
class StudentViewSet(viewsets.ModelViewSet):
@ -23,10 +23,10 @@ class StudentViewSet(viewsets.ModelViewSet):
"""
queryset = Student.objects.all()
serializer_class = StudentSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
permission_Class = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
serializer.save(user=self.request.user)
class TeacherViewSet(viewsets.ModelViewSet):
"""
@ -34,25 +34,25 @@ class TeacherViewSet(viewsets.ModelViewSet):
"""
queryset = Teacher.objects.all()
serializer_class = TeacherSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
permission_Class = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
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.
"""
queryset = Classes.objects.all()
serializer_class = ClassesSerializer
permission_classes = [permissions.IsAuthenticated, IsOwnerOrReadOnly]
queryset = Class.objects.all()
serializer_class = ClassSerializer
permission_Class = [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)
# 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):
@ -61,7 +61,7 @@ class AssignmentViewSet(viewsets.ModelViewSet):
"""
queryset = Assignment.objects.all()
serializer_class = AssignmentSerializer
permission_classes = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly]
permission_Class = [permissions.IsAuthenticated, isTeacher, IsOwnerOrReadOnly]
def perform_create(self, serializer):
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()
# 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'teachers', api_views.TeacherViewSet)
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'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;
margin-top: 5rem;
font-family: 'Segoe UI';
margin-left: 2.5rem;
margin-right: 2.5rem;
}
h1, h2, h3, h4, h5, h6 {
color: #444444;
}
ul {
margin: 0;
}
.bg-steel {
background: #3cba54;
}
.site-header .navbar-nav .nav-link {
color: #cbd5db;
color: #e1e1e1;
}
.site-header .navbar-nav .nav-link:hover {
@ -69,7 +67,8 @@ a.article-title:hover {
.article-metadata {
padding-bottom: 1px;
margin-bottom: 4px;
border-bottom: 1px solid #e3e3e3
border-bottom: 1px solid #e3e3e3;
font-size: 1.5em;
}
.article-metadata a:hover {
@ -93,8 +92,3 @@ a.article-title:hover {
.account-heading {
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">
<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
<img src="{% static 'skoolos/tj_trans.png' %}" width="30" height="30" class="d-inline-block align-top" alt="">
SkoolOS
</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>
@ -43,6 +43,16 @@
</nav>
</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 %}
<!-- Bootstrap JS -->
<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" %}
{% 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 %}

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.
urlpatterns = [
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.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.
@login_required()
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")
@login_required()
def profile (request):
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 api.models import Student, Teacher
from django.contrib.auth.models import Group
from .forms import UserCreationForm
@ -97,15 +98,18 @@ def create_account (request):
last_name=last_name,
password=password)
user.save()
token.delete()
g, created = Group.objects.get_or_create(name='teachers')
if isStudent:
profile = Student(user=user, git=git, grade=grade)
profile = Student(user=user, git=git, grade=grade, ion_user=username)
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()
token.delete()
print (user)
messages.success(request, "Your SkoolOS account has successfully been created")
return redirect(f'/login/?username={username}')
@ -145,4 +149,4 @@ def create_account (request):
def logout(request):
auth_logout(request)
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
astroid==2.4.2
CacheControl==0.12.6
certifi==2020.4.5.1
chardet==3.0.4
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-cors-middleware==1.5.0
django-crispy-forms==1.9.1
django-oauth-toolkit==1.3.2
djangorestframework==3.11.0
greenlet==0.4.16
html5lib==1.0.1
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
ordered-set==3.1.1
packaging==20.1
pep517==0.8.1
Pillow==7.1.2
progress==1.5
prompt-toolkit==1.0.14
pulsemixer==1.5.0
pycairo==1.19.1
pyclipper==1.1.0.post3
Pygments==2.6.1
PyGObject==3.34.0
pyinotify==0.9.6
PyInquirer==1.0.3
pylint==2.5.3
pynvim==0.4.1
pyparsing==2.4.6
pyperclip==1.8.0
pytoml==0.1.21
pytz==2020.1
pywal==3.3.0
regex==2020.5.14
requests==2.23.0
requests-oauthlib==1.3.0
retrying==1.3.3
selenium==3.141.0
six==1.15.0
sqlparse==0.3.1
team==1.0
toml==0.10.0
urllib3==1.25.9
wcwidth==0.2.3
webencodings==0.5.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
from PyInquirer import prompt, print_json
import json
import datetime
import os
import argparse
import webbrowser
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
@ -36,48 +38,123 @@ def main():
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)
r = requests.get(url = URL)
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")
#webbrowser.open("http://127.0.0.1:8000/login", new=2)
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']
print(data['username'])
if(data['is_student']):
studentCLI()
studentCLI(USER, PWD)
else:
teacherCLI()
teacherCLI(USER, PWD)
# while True:
# pass
def studentCLI():
def studentCLI(user, password):
from CLI import student
data = getStudent(USER)
print(data)
data = getUser(user, password)
student = student.Student(data)
print(student)
carray = student.sclass.split(",")
if(len(carray) == 1 and carray[0] == ""):
print("No classes")
return
def teacherCLI():
from CLI.teacher import Teacher
print("fail")
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 getStudent(ion_user):
def teacherCLI(user, password):
from CLI import teacher
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.")
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 + "/"
r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1'))
r = requests.get(url = URL, auth=(ion_user,password))
if(r.status_code == 200):
data = r.json()
return data
@ -90,6 +167,10 @@ def getStudent(ion_user):
else:
return None
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):
r = requests.get(url = url, auth=('raffukhondaker','hackgroup1'))
@ -152,79 +233,94 @@ def authenticate():
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")
# 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()
# 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()
# server = Thread(target=create_server)
# server.daemon = True
# 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)
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")
gets = url_decode(url.replace("http://localhost:8000/login/?username=", ""))
# 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
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,
'email':email,
'first_name':first_name,
'last_name':last_name,
'grade':grade,
'is_student':is_student,
'password':password,
'password':pwd,
}
os.chdir(cdir)
profileFile = open(".profile", "w")
profileFile.write(json.dumps(profile))
profileFile.close()
#try to make password
password = makePass()
profile['password'] = password
else:
print("Welcome, teacher " + user)
r = requests.get(url = "http://localhost:8000/api/teachers/" + 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()

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