diff --git a/CLI/commands.py b/CLI/commands.py index c8827a1..b89acfc 100644 --- a/CLI/commands.py +++ b/CLI/commands.py @@ -4,7 +4,6 @@ import json import os import argparse - ''' my_parser = argparse.ArgumentParser(prog='skool', description='Let SkoolOS control your system', epilog="Try again") my_parser.add_argument('--init', action="store_true") #returns true if run argument @@ -16,7 +15,8 @@ if(outputs['init']): start() ''' -#already ccrerrated account through website, has to login + +# already created account through website, has to login def update(): """ Gets data from the database @@ -24,6 +24,7 @@ def update(): """ return + def yesorno(question): questions = [ { @@ -33,17 +34,18 @@ def yesorno(question): }, ] answers = prompt(questions) - if(answers["response"] == "y"): + if answers["response"] == "y": return True return False + def login(): """ Login to the website with a username and password :return: user information json if successful, None otherwise """ - #enter username - #enter password + # enter username + # enter password questions = [ { 'type': 'input', @@ -57,12 +59,12 @@ def login(): }, ] user = prompt(questions) - #reading from json of users (replace w GET to database) to check if user is registered + # reading from json of users (replace w GET to database) to check if user is registered with open('users.json', 'r') as json_file: data = json.load(json_file) for i in range(len(data)): if user["webmail"] == data[i]["webmail"]: - if(user["password"] == data[i]["password"]): + if user["password"] == data[i]["password"]: print("Logged in!") return data[i] else: @@ -71,7 +73,8 @@ def login(): print("User not found. Please Try again") return None -#did not create account through website, has to signup/login + +# did not create account through website, has to signup/login def signup(): """ Used to create an account for the service. @@ -93,7 +96,7 @@ def signup(): 'type': 'list', 'name': 'grade', 'message': 'Grade?', - 'choices':["9","10","11","12"] + 'choices': ["9", "10", "11", "12"] }, { 'type': 'input', @@ -114,7 +117,7 @@ def signup(): if len(user["password"]) < 6: print("Password is too short. Try again.") return None - if (("@tjhsst.edu" in user['webmail']) == False): + if not ("@tjhsst.edu" in user['webmail']): print("Webmail entered was not a @tjhhsst.edu. Try again.") return None @@ -125,6 +128,7 @@ def signup(): open("users.json", "w").write(str(json.dumps(data))) return user + def relogin(): """ Login to an already verified user account @@ -135,15 +139,15 @@ def relogin(): 'type': 'list', 'name': 'choice', 'message': '', - 'choices':["Continue as current user","Login into new user","Sign up into new account"] + 'choices': ["Continue as current user", "Login into new user", "Sign up into new account"] }, ] answer = prompt(questions) def setup(user): - #Read classes/assignenments and setup directory: - #SkoolOS/Math/Week1 + # Read classes/assignenments and setup directory: + # SkoolOS/Math/Week1 """ Reads classes and assignments of/for the user and properly sets of their work directory :param user: @@ -154,20 +158,20 @@ def setup(user): for a in user["classes"][c]: os.makedirs(c + "/" + a) + def start(): """ Prompts the user for whether or not they have an account and allows them to login/signup depending on their response :return: """ - if(os.path.exists(".login.txt") == False): + if not os.path.exists(".login.txt"): b = yesorno("Do you have a SkoolOS account?(y/N)") - if(b): + if b: user = login() - if(user != None): + if user is not None: setup(user) open(".login.txt", "w").write(str(user)) else: user = signup() - if(user != None): + if user is not None: open(".login.txt").write(str(user)) - diff --git a/CLI/s-git-oldd.py b/CLI/s-git-oldd.py deleted file mode 100644 index 0cf4486..0000000 --- a/CLI/s-git-oldd.py +++ /dev/null @@ -1,256 +0,0 @@ -import subprocess -import os -import requests -import webbrowser -import pprint -import json -import shutil -import time -import pyperclip - -#git clone student directory ==> /classes/assignments - -#get teacher info from api -def getStudent(ion_user): - URL = "http://127.0.0.1:8000/students/" + ion_user + "/" - r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) - if(r.status_code == 200): - data = r.json() - return data - elif(r.status_code == 404): - return None - print("Make new account!") - elif(r.status_code == 403): - return None - print("Invalid username/password") - else: - return None - print(r.status_code) - -def getDB(url): - r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) - print("GET:" + str(r.status_code)) - return(r.json()) - -def postDB(data, url): - r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("POST:" + str(r.status_code)) - return(r.json()) - -def putDB(data, url): - r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("PUT:" + str(r.status_code)) - return(r.json()) - -def delDB(url): - r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) - print("DELETE:" + str(r.status_code)) - return None - -def 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()[1] - print(output.decode('utf-8')) - -#################################################################################################################################### - -#public methods: deleteClass, makeClass, update -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/students/" + self.username + "/" - self.email = data['email'] - self.grade = data['grade'] - self.student_id=data['student_id'] - self.completed = data['completed'] - #classes in id form (Example: 4,5) - - #storing actual classes - 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/classes/" + str(c) + "/" - classes.append(getDB(url)) - - self.classes = classes - self.sclass=str(data['classes']) - - #storing added_to classes - nid=data['added_to'].split(",") - try: - nid.remove('') - except: - pass - try: - nid.remove("") - except: - pass - nclasses=[] - for c in nid: - url = "http://127.0.0.1:8000/classes/" + str(c) + "/" - nclasses.append(getDB(url)) - - self.new = nclasses - self.snew=str(data['added_to']) - if(os.path.isdir(self.username)): - print("Synced to " + self.username) - else: - os.mkdir(self.username) - - - #update API and Github, all assignments / classes - def update(self): - #lists all classes - ignore=['.DS_Store'] - classes = os.listdir(self.username) - for i in ignore: - try: - classes.remove(i) - except: - pass - - for i in range(len(classes)): - c = classes[i] - path = self.username + "/" + c - #lists all assignments and default files - #push to git - isclass = False - for d in os.listdir(path): - if(d == '.git'): - isclass=True - break - if(isclass): - loc = os.getcwd() - os.chdir(path) - command('git fetch origin') - command('git checkout ' + self.username) - command('git add .') - command('git commit -m ' + self.username + '-update') - command('git push -u origin ' + self.username) - command('git merge master') - os.chdir(loc) - print("Updated: " + c) - else: - print(d + " is not a class") - - #class name format: _ - - - #add classes from 'new' field - def addClass(self, cid): - if((cid in self.snew) == False): - if((cid in self.sclass) == True): - print("Already enrolled in this class.") - else: - print("Not added by teacher yet.") - return None - data = getDB('http://127.0.0.1:8000/classes/'+cid) - - #clone class repo and make student branch (branch name: username) - os.chdir(self.username) - command("git clone " + data['repo']) - os.chdir(data['name']) - command("git checkout " + self.username) - command("git push -u origin " + self.username) - - self.classes.append(data) - if(len(self.sclass)==0): - self.sclass = data['id'] - else: - self.sclass = self.sclass + "," + str(data['id']) - - #upddate self.new - s="" - nar = '' - for i in range(len(self.new)): - if(self.new[i]['id'] == int(data['id'])): - print("DELETE: " + self.new[i]['name']) - del self.new[i] - #recreate sclass field, using ids - for c in self.new: - s = s + str(c['id']) + "," - nar.append(c) - self.snew=s - self.new=nar - break - - #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, - '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)) - return data - - def submit(self, path): - #2022rkhondak/English11_eharris1/Essay1 - #check if valid assignment - parts = path.split("/") - if(len(parts) != 3): - print("Assignment path too short") - return - isclass = False - for c in self.classes: - if(c['name'] == parts[1]): - isclass==True - break - if(parts[0] != self.username and isclass and os.path.isdir(path) == False): - print("Not valid assignment") - return - if((parts[1] + "/" + parts[2]) in self.completed): - print(parts[2] + " already submited. ") - # return - resp = input("Are you sure you want to submit? You cannot do this again.(y/N) ") - if(resp == 'y'): - os.chdir(self.username + "/" + parts[1]) - command("git add .") - command("git commit -m submit") - command("git tag " + parts[1] + "-final") - 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, - '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 - } - #print(putDB(data, "http://127.0.0.1:8000/students/" + self.username + "/")) - -data = getStudent("2022rkhondak") -s = Student(data) -s.update() \ No newline at end of file diff --git a/CLI/server.py b/CLI/server.py deleted file mode 100644 index 1cc095f..0000000 --- a/CLI/server.py +++ /dev/null @@ -1,23 +0,0 @@ -from http.server import HTTPServer - -class HTTPServer(BaseHTTPServer.HTTPServer): - - _continue = True - - def serve_until_shutdown(self): - while self._continue: - self.handle_request() - - def shutdown(self): - self._continue = False - # We fire a last request at the server in order to take it out of the - # while loop in `self.serve_until_shutdown`. - try: - urllib2.urlopen( - 'http://%s:%s/' % (self.server_name, self.server_port)) - except urllib2.URLError: - # If the server is already shut down, we receive a socket error, - # which we ignore. - pass - self.server_close() - diff --git a/CLI/t-git-old.py b/CLI/t-git-old.py deleted file mode 100644 index 6e11a47..0000000 --- a/CLI/t-git-old.py +++ /dev/null @@ -1,372 +0,0 @@ -import subprocess -import os -import requests -import webbrowser -import pprint -import json -import shutil -import time -import pyperclip - -#git clone student directory ==> /classes/assignments - -#get teacher info from api -def getTeacher(ion_user): - URL = "http://127.0.0.1:8000/teachers/" + ion_user + "/" - r = requests.get(url = URL, auth=('raffukhondaker','hackgroup1')) - if(r.status_code == 200): - data = r.json() - return data - elif(r.status_code == 404): - return None - print("Make new account!") - elif(r.status_code == 403): - return None - print("Invalid username/password") - else: - return None - print(r.status_code) - -def getDB(url): - r = requests.get(url = url, auth=('raffukhondaker','hackgroup1')) - print("GET:" + str(r.status_code)) - return(r.json()) - -def postDB(data, url): - r = requests.post(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("POST:" + str(r.status_code)) - return(r.json()) - -def putDB(data, url): - r = requests.put(url = url, data=data, auth=('raffukhondaker','hackgroup1')) - print("PUT:" + str(r.status_code)) - return(r.json()) - -def delDB(url): - r = requests.delete(url = url, auth=('raffukhondaker','hackgroup1')) - print("DELETE:" + str(r.status_code)) - return None - -def 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()[1] - #print(output.decode('utf-8')) - -#################################################################################################################################### - -#public methods: deleteClass, makeClass, update -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/teachers/" + self.username + "/" - self.email = data['email'] - #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/classes/" + str(c) + "/" - classes.append(getDB(url)) - - self.classes = classes - self.sclass=str(data['classes']) - if(os.path.isdir(self.username)): - print("Synced to " + self.username) - else: - os.mkdir(self.username) - - - #update API and Github, all assignments / classes - def update(self): - #lists all classes - ignore=['.git','.DS_Store'] - classes = os.listdir(self.username) - for i in ignore: - try: - classes.remove(i) - except: - pass - #list of classes that have been deleted (not with deleteClass) - extra = [] - for c in self.classes: - extra.append(c) - for i in range(len(extra)): - e = extra[i]['path'] - extra[i] = e - print("Extra: "+str(extra)) - print("Local:" + str(classes)) - #checks all class directories first - for c in classes: - path = self.username + "/" + c - if(self.checkClass(path) == False): - return - extra.remove(path) - print("Current classes: " + path) - - for e in extra: - self.deleteClass(e) - - for i in range(len(classes)): - c = classes[i] - path = self.username + "/" + c - #lists all assignments and default files - #if no .git, directory not synced to git or API - if (self.checkInDB(path)==False): - self.addClass(path) - else: - #push to git - loc = os.getcwd() - os.chdir(path) - command('git fetch origin') - command('git pull origin master') - command('git add .') - command('git commit -m "Update"') - command('git push -u origin master') - os.chdir(loc) - - #class name format: _ - - #turn existing directory into class, Pre-condition: directory exists - #relative path to class: 2022rkhondak/Math4 - def checkClass(self,path): - cname = path.split("/") - cname = cname[len(cname)-1] - if(os.path.isfile(path)): - print(path + " must be in a Class directory.") - return False - if(("_" + self.username) in cname) == False: - print("Incorrect class name: Must be in the format: " + self.username+ "/_, not " + path) - return False - dirs = os.listdir(path) - #checks if there is a file (not within Assignments) in class, need at least 1 - deffile = False - #checks if there is a file in an Assignment, need at least 1 (default True in case no assignments) - as_file = True - as_bad = "" - - for d in dirs: - if(os.path.isfile(d)): - deffile=True - else: - #checks if there is a file in an Assignment, need at least 1 - as_file = False - asdir = os.listdir(path + "/" + d) - for a in asdir: - if(os.path.isfile(path + "/" + d + "/" +a)): - as_file=True - if(as_file==False): - as_bad = d - break - if(as_file==False): - print("Assignment '" + as_bad + "' does not have a default file!") - return False - - if(deffile==False): - print("Need a default file in the " + path + " Directory!") - return False - return True - - def checkInDB(self, path): - n = path.split("/") - n = n[len(n)-1] - for c in self.classes: - if(n == c['name']): - return True - return False - - #adds class to git, not API - #Assuming valid class name - def addClasstoGit(self, path): - cname = path.split("/") - cname = cname[len(cname)-1] - #push to remote repo - url='https://github.com/' + self.git + "/" + cname - if(requests.get(url).status_code != 200): - input("Make new Git Repo with name: " + cname + " (Press any key to continue)\n") - try: - pyperclip.copy(cname) - print(cname + " copied to clipboard.") - except: - pass - time.sleep(2) - webbrowser.open('https://github.com/new') - input("Repo created? (Press any key to continue)\n") - - print(url) - while(requests.get(url).status_code != 200): - r = input("Repo not created yet. (Press any key to continue after repo created, or 'N' to exit)\n") - if(r=="N" or r=="No"): - return None - cdir = os.getcwd() - os.chdir(path) - command('git init') - command('git add .') - command('git commit -m Hello_Class') - command('git remote add origin ' + url + '.git') - command('git push -u origin master') - else: - cdir = os.getcwd() - os.chdir(path) - print("Repo already exists. Cloning instead.") - command('git clone') - command('git fetch origin') - command('git pull') - command('git add .') - command('git commit -m Hello_Class') - command('git push -u origin master') - os.chdir(cdir) - print(cdir) - data={ - 'name':cname, - 'repo':url, - 'path':path, - 'teacher':self.username, - } - return data - - #make class from existing directory, add to git and api - def addClass(self, path): - if (self.checkClass(path)): - data = self.addClasstoGit(path) - #make class instance in db - data = postDB(data, 'http://127.0.0.1:8000/classes/') - #add to instance - #upate self.classes - self.classes.append(data) - if(len(self.sclass)==0): - self.sclass = data['id'] - else: - self.sclass = self.sclass + "," + str(data['id']) - - #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, - 'url':self.url, - 'classes':self.sclass, - 'email':self.email - } - putDB(data, self.url) - - return data - - - #make a new class from scratch - #subject: string, assignments: list - #class name must be: _ - def makeClass(self, cname, assignments): - #check if class exists - path = self.username + "/" + cname - if(os.path.exists(path)): - print("Class already exists: " + cname) - return - else: - if((("_" + self.username) in cname) == False): - print("class name must be: "+ cname + "_" + self.username) - return - cdir = os.getcwd() - os.mkdir(path) - f=open(path + "/README.md", "w") - f.close() - #push to remote repo - os.chdir(path) - for a in assignments: - os.mkdir(a) - f=open(a + "/instructions.txt", "w") - f.close() - os.chdir(cdir) - - data = self.addClass(path) - return data - - def deleteClass(self, path): - if(os.path.exists(path) == False): - print(path + " does not exist locally.") - resp = input("Do you want to delete " + path + " from the SkoolOS system? (y/N) ") - if(resp != 'y'): - return - - cname = path.split("/") - cname = cname[len(cname)-1] - cid = None - repo = '' - for c in self.classes: - if cname == c['name']: - cid = str(c['id']) - repo = c['repo'] - - #remove from api - for i in range(len(self.classes)): - if(self.classes[i]['id'] == int(cid)): - print("DELETE: " + self.classes[i]['name']) - del self.classes[i] - s="" - #recreate sclass field, using ids - for c in self.classes: - s = s + str(c['id']) + "," - 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/classes/" + cid + "/") - break - - #remove locally - try: - shutil.rmtree(path) - except: - pass - - #remove from git - input("Delete repository: " + cname + ". Scroll to the bottom of the page and press 'Delete this repository' (Press any key to continue) ") - print(repo) - time.sleep(2) - webbrowser.open(repo + "/settings") - input("Repo deleted? (Press any key to continue) ") - - print(repo) - while(requests.get(repo).status_code == 200): - r = input("Repo still no deleted yet. (Press any key to continue after repo deleted, or 'N' to exit)\n") - if(r=="N" or r=="No" or r=='n'): - return None - -#make student repo by student id - def addStudent(self,stid): - print(stid) - - def comment(self): - print("heheheh") - -data = getTeacher("eharris1") -t = Teacher(data) -t.makeClass('English11_eharris1', ["Essay1"]) -t.update() diff --git a/Website/api/models.py b/Website/api/models.py index 9dc22f2..c4b92ae 100644 --- a/Website/api/models.py +++ b/Website/api/models.py @@ -3,16 +3,15 @@ from django.contrib.auth.models import User import secrets - class Student(models.Model): user = models.OneToOneField(User, blank=True, 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) + 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) @@ -24,13 +23,14 @@ class Student(models.Model): class Assignment(models.Model): owner = models.ForeignKey(User, null=True, blank=True, related_name='aowner', on_delete=models.CASCADE) - name=models.CharField(max_length=100, primary_key=True) - due_date=models.DateTimeField() + name = models.CharField(max_length=100, primary_key=True) + due_date = models.DateTimeField() # files = models.ManyToManyField(DefFiles) - files=models.CharField(max_length=100, default="", blank=True) - path=models.CharField(max_length=100) - classes=models.CharField(max_length=100) - teacher=models.CharField(max_length=100) + files = models.CharField(max_length=100, default="", blank=True) + path = models.CharField(max_length=100) + classes = models.CharField(max_length=100) + teacher = models.CharField(max_length=100) + def __str__(self): return '%s' % (self.name) @@ -41,12 +41,12 @@ class Class(models.Model): 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="") - assignments=models.ManyToManyField(Assignment, blank=True) - default_file=models.CharField(max_length=100, default="", blank=True) - confirmed=models.ManyToManyField(Student, blank=True, related_name='confirmed') - unconfirmed=models.ManyToManyField(Student, blank=True, related_name='unconfirmed') + repo = models.URLField(default="", blank=True) + path = models.CharField(max_length=100, default="") + assignments = models.ManyToManyField(Assignment, blank=True) + default_file = models.CharField(max_length=100, 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) @@ -62,11 +62,12 @@ class Class(models.Model): def __str__(self): return self.name + class Teacher(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) - 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) + 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) def __str__(self): return f"{self.user.username}'s Profile" @@ -74,6 +75,7 @@ class Teacher(models.Model): def save(self, *args, **kwargs): super(Teacher, self).save(*args, **kwargs) + # class Student(models.Model): # user = models.OneToOneField(User, on_delete=models.CASCADE) # ion_user=models.CharField(primary_key=True, max_length=100) @@ -86,8 +88,8 @@ class Teacher(models.Model): 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) + 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)