diff --git a/CLI/commands.py b/CLI/commands.py new file mode 100644 index 0000000..c8827a1 --- /dev/null +++ b/CLI/commands.py @@ -0,0 +1,173 @@ +from __future__ import print_function, unicode_literals +from PyInquirer import prompt, print_json +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 +args = my_parser.parse_args() + +update() +outputs = vars(args) +if(outputs['init']): + start() +''' + +#already ccrerrated account through website, has to login +def update(): + """ + Gets data from the database + :return: + """ + return + +def yesorno(question): + questions = [ + { + 'type': 'input', + 'name': 'response', + 'message': question, + }, + ] + answers = prompt(questions) + 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 + questions = [ + { + 'type': 'input', + 'name': 'webmail', + 'message': 'What\'s TJ Webmail', + }, + { + 'type': 'password', + 'name': 'password', + 'message': 'Password?', + }, + ] + user = prompt(questions) + #reading from json of users (replace w GET to database) to check if user is registered + with open('users.json', 'r') as json_file: + data = json.load(json_file) + for i in range(len(data)): + if user["webmail"] == data[i]["webmail"]: + if(user["password"] == data[i]["password"]): + print("Logged in!") + return data[i] + else: + print("Password incorrect. Try again.") + return None + print("User not found. Please Try again") + return None + +#did not create account through website, has to signup/login +def signup(): + """ + Used to create an account for the service. + Called if the user does not have an existing account and must create one. + :return: the new user account + """ + questions = [ + { + 'type': 'input', + 'name': 'first-name', + 'message': 'What\'s your first name', + }, + { + 'type': 'input', + 'name': 'last-name', + 'message': 'What\'s your last name?', + }, + { + 'type': 'list', + 'name': 'grade', + 'message': 'Grade?', + 'choices':["9","10","11","12"] + }, + { + 'type': 'input', + 'name': 'webmail', + 'message': 'What\'s your TJ Webmail?', + }, + { + 'type': 'password', + 'name': 'password', + 'message': 'Password?', + }, + ] + user = prompt(questions) + for i in user: + if user[i] == "": + print("Some forms were left blank. Try again.\n") + return None + if len(user["password"]) < 6: + print("Password is too short. Try again.") + return None + if (("@tjhsst.edu" in user['webmail']) == False): + print("Webmail entered was not a @tjhhsst.edu. Try again.") + return None + + user["classes"] = [] + with open('users.json', 'r') as json_file: + data = json.load(json_file) + data.append(user) + open("users.json", "w").write(str(json.dumps(data))) + return user + +def relogin(): + """ + Login to an already verified user account + :return: + """ + questions = [ + { + 'type': 'list', + 'name': 'choice', + 'message': '', + 'choices':["Continue as current user","Login into new user","Sign up into new account"] + }, + ] + answer = prompt(questions) + + +def setup(user): + #Read classes/assignenments and setup directory: + #SkoolOS/Math/Week1 + """ + Reads classes and assignments of/for the user and properly sets of their work directory + :param user: + :return: + """ + for c in user["classes"]: + os.makedirs(c) + 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): + b = yesorno("Do you have a SkoolOS account?(y/N)") + if(b): + user = login() + if(user != None): + setup(user) + open(".login.txt", "w").write(str(user)) + else: + user = signup() + if(user != None): + open(".login.txt").write(str(user)) + diff --git a/Website/api/models.py b/Website/api/models.py index 823fb99..9dc22f2 100644 --- a/Website/api/models.py +++ b/Website/api/models.py @@ -5,7 +5,7 @@ import secrets class Student(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) + 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) @@ -20,8 +20,9 @@ class Student(models.Model): def __str__(self): return f"{self.user.username}'s Profile" + class Assignment(models.Model): - owner = models.ForeignKey('auth.User', related_name='aowner', on_delete=models.CASCADE) + 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() @@ -33,8 +34,9 @@ class Assignment(models.Model): def __str__(self): return '%s' % (self.name) + class Class(models.Model): - owner = models.ForeignKey('auth.User', related_name='cowner', on_delete=models.CASCADE) + owner = models.ForeignKey(User, null=True, blank=True, related_name='cowner', 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) diff --git a/bgservice/bgservice.py b/bgservice/bgservice.py index 8943172..ca9ab1e 100644 --- a/bgservice/bgservice.py +++ b/bgservice/bgservice.py @@ -16,6 +16,11 @@ class EventHandler(pyinotify.ProcessEvent): ] def process_IN_CREATE(self, event): + """ + Generates an output to record for IN_CREATE events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Created file\n" \ "Event Path: {}\n" \ @@ -26,6 +31,11 @@ class EventHandler(pyinotify.ProcessEvent): print(description) def process_IN_CLOSE_WRITE(self, event): + """ + Generates an output to record for IN_CLOSE_WRITE events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Wrote to a file\n" \ "Event Path: {}\n" \ @@ -36,6 +46,11 @@ class EventHandler(pyinotify.ProcessEvent): print(description) def process_IN_DELETE(self, event): + """ + Generates an output to record for IN_DELETE events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Deleted file\n" \ "Event Path: {}\n" \ @@ -46,6 +61,11 @@ class EventHandler(pyinotify.ProcessEvent): print(description) def process_IN_MOVED_TO(self, event): + """ + Generates an output to record for IN_MOVED_TO events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Moved a file in\n" \ "Event Path: {}\n" \ @@ -56,6 +76,11 @@ class EventHandler(pyinotify.ProcessEvent): print(description) def process_IN_MOVED_FROM(self, event): + """ + Generates an output to record for IN_MOVED_FROM events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Moved a file out\n" \ "Event Path: {}\n" \ @@ -66,6 +91,11 @@ class EventHandler(pyinotify.ProcessEvent): print(description) def process_IN_OPEN(self, event): + """ + Generates an output to record for IN_OPEN events + :param event: event automatically passed to function + :return: none + """ description = \ "Event: Opened file\n" \ "Event Path: {}\n" \ @@ -82,15 +112,22 @@ DIR = None START_TIME = None -def watch_dir(watched_dir="/tmp", logdir="/tmp/skooloslogs"): +def watch_dir(watched_dir="/tmp", log_dir="/tmp/skooloslogs"): + """ + Watches the specified directory for changes and outputs it in + human readable format to a log file in the specified log directory. + :param watched_dir: directory to watch for changes + :param log_dir: directory to store log files + :return: none + """ global DIR global START_TIME global NOTIFIER DIR = watched_dir - if not os.path.exists(logdir): - os.makedirs(logdir) + if not os.path.exists(log_dir): + os.makedirs(log_dir) logfile = open( - logdir + "/skoolos_" + + log_dir + "/skoolos_" + time.strftime("%m%d%Y-%H%M%S", time.localtime()), 'w') START_TIME = time.time() wm = pyinotify.WatchManager() @@ -106,6 +143,10 @@ def watch_dir(watched_dir="/tmp", logdir="/tmp/skooloslogs"): def stop_watching(): + """ + Stops the watch started by watch_dir() + :return: none + """ NOTIFIER.stop() now = time.time() print("End time: " + diff --git a/bgservice/checker.py b/bgservice/checker.py index 773e31a..58b3874 100644 --- a/bgservice/checker.py +++ b/bgservice/checker.py @@ -68,6 +68,10 @@ file_whitelist = [ def shell_check(): + """ + Check .bash_history and .histfile for git commands that could interfere with SkoolOS + :return: results of the check + """ bash_history = [ line.strip() for line in open(os.path.expanduser("~/.bash_history"), 'r') @@ -79,7 +83,7 @@ def shell_check(): for i in bash_history + zsh_history: if "git" in i: suspicious_commands.append(i) - if suspicious_commands != []: + if suspicious_commands: return str( len(suspicious_commands) ) + " suspicious commands found:\n" + "\n".join(suspicious_commands) @@ -87,6 +91,11 @@ def shell_check(): def verify_file(file_): + """ + Check if the file name has an extension in the list of whitelisted file exentsions + :param file_: path to file + :return: whether or not the file's extension is whitelisted + """ for ext in file_whitelist: if len(file_) > len(ext): if file_[len(file_) - len(ext):] == ext: @@ -95,6 +104,11 @@ def verify_file(file_): def file_check(dir_): + """ + Checks specified dir_ for non-whitelisted files using verify_file() + :param dir_: directory to check + :return: list of suspicious files + """ files = glob(dir_ + "/**/*", recursive=True) suspicious_files = [] for file_ in files: