mirror of
https://github.com/Rushilwiz/SkoolOS.git
synced 2025-04-16 02:10:19 -04:00
Merge branch 'master' of https://github.com/Rushilwiz/SkoolOS
This commit is contained in:
commit
afea2c1494
173
CLI/commands.py
Normal file
173
CLI/commands.py
Normal file
|
@ -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))
|
||||||
|
|
|
@ -5,7 +5,7 @@ import secrets
|
||||||
|
|
||||||
|
|
||||||
class Student(models.Model):
|
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)
|
ion_user = models.CharField(max_length=100, primary_key=True)
|
||||||
grade = models.IntegerField(default=0, blank=True)
|
grade = models.IntegerField(default=0, blank=True)
|
||||||
git=models.CharField(default="", max_length=100, blank=True)
|
git=models.CharField(default="", max_length=100, blank=True)
|
||||||
|
@ -20,8 +20,9 @@ class Student(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.user.username}'s Profile"
|
return f"{self.user.username}'s Profile"
|
||||||
|
|
||||||
|
|
||||||
class Assignment(models.Model):
|
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)
|
name=models.CharField(max_length=100, primary_key=True)
|
||||||
due_date=models.DateTimeField()
|
due_date=models.DateTimeField()
|
||||||
|
@ -33,8 +34,9 @@ class Assignment(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '%s' % (self.name)
|
return '%s' % (self.name)
|
||||||
|
|
||||||
|
|
||||||
class Class(models.Model):
|
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)
|
teacher = models.CharField(max_length=100)
|
||||||
name = models.CharField(primary_key=True, max_length=100)
|
name = models.CharField(primary_key=True, max_length=100)
|
||||||
id = models.CharField(max_length=8, blank=True, null=True)
|
id = models.CharField(max_length=8, blank=True, null=True)
|
||||||
|
|
|
@ -16,6 +16,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
]
|
]
|
||||||
|
|
||||||
def process_IN_CREATE(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Created file\n" \
|
"Event: Created file\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -26,6 +31,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
print(description)
|
print(description)
|
||||||
|
|
||||||
def process_IN_CLOSE_WRITE(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Wrote to a file\n" \
|
"Event: Wrote to a file\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -36,6 +46,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
print(description)
|
print(description)
|
||||||
|
|
||||||
def process_IN_DELETE(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Deleted file\n" \
|
"Event: Deleted file\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -46,6 +61,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
print(description)
|
print(description)
|
||||||
|
|
||||||
def process_IN_MOVED_TO(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Moved a file in\n" \
|
"Event: Moved a file in\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -56,6 +76,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
print(description)
|
print(description)
|
||||||
|
|
||||||
def process_IN_MOVED_FROM(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Moved a file out\n" \
|
"Event: Moved a file out\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -66,6 +91,11 @@ class EventHandler(pyinotify.ProcessEvent):
|
||||||
print(description)
|
print(description)
|
||||||
|
|
||||||
def process_IN_OPEN(self, event):
|
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 = \
|
description = \
|
||||||
"Event: Opened file\n" \
|
"Event: Opened file\n" \
|
||||||
"Event Path: {}\n" \
|
"Event Path: {}\n" \
|
||||||
|
@ -82,15 +112,22 @@ DIR = None
|
||||||
START_TIME = 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 DIR
|
||||||
global START_TIME
|
global START_TIME
|
||||||
global NOTIFIER
|
global NOTIFIER
|
||||||
DIR = watched_dir
|
DIR = watched_dir
|
||||||
if not os.path.exists(logdir):
|
if not os.path.exists(log_dir):
|
||||||
os.makedirs(logdir)
|
os.makedirs(log_dir)
|
||||||
logfile = open(
|
logfile = open(
|
||||||
logdir + "/skoolos_" +
|
log_dir + "/skoolos_" +
|
||||||
time.strftime("%m%d%Y-%H%M%S", time.localtime()), 'w')
|
time.strftime("%m%d%Y-%H%M%S", time.localtime()), 'w')
|
||||||
START_TIME = time.time()
|
START_TIME = time.time()
|
||||||
wm = pyinotify.WatchManager()
|
wm = pyinotify.WatchManager()
|
||||||
|
@ -106,6 +143,10 @@ def watch_dir(watched_dir="/tmp", logdir="/tmp/skooloslogs"):
|
||||||
|
|
||||||
|
|
||||||
def stop_watching():
|
def stop_watching():
|
||||||
|
"""
|
||||||
|
Stops the watch started by watch_dir()
|
||||||
|
:return: none
|
||||||
|
"""
|
||||||
NOTIFIER.stop()
|
NOTIFIER.stop()
|
||||||
now = time.time()
|
now = time.time()
|
||||||
print("End time: " +
|
print("End time: " +
|
||||||
|
|
|
@ -68,6 +68,10 @@ file_whitelist = [
|
||||||
|
|
||||||
|
|
||||||
def shell_check():
|
def shell_check():
|
||||||
|
"""
|
||||||
|
Check .bash_history and .histfile for git commands that could interfere with SkoolOS
|
||||||
|
:return: results of the check
|
||||||
|
"""
|
||||||
bash_history = [
|
bash_history = [
|
||||||
line.strip()
|
line.strip()
|
||||||
for line in open(os.path.expanduser("~/.bash_history"), 'r')
|
for line in open(os.path.expanduser("~/.bash_history"), 'r')
|
||||||
|
@ -79,7 +83,7 @@ def shell_check():
|
||||||
for i in bash_history + zsh_history:
|
for i in bash_history + zsh_history:
|
||||||
if "git" in i:
|
if "git" in i:
|
||||||
suspicious_commands.append(i)
|
suspicious_commands.append(i)
|
||||||
if suspicious_commands != []:
|
if suspicious_commands:
|
||||||
return str(
|
return str(
|
||||||
len(suspicious_commands)
|
len(suspicious_commands)
|
||||||
) + " suspicious commands found:\n" + "\n".join(suspicious_commands)
|
) + " suspicious commands found:\n" + "\n".join(suspicious_commands)
|
||||||
|
@ -87,6 +91,11 @@ def shell_check():
|
||||||
|
|
||||||
|
|
||||||
def verify_file(file_):
|
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:
|
for ext in file_whitelist:
|
||||||
if len(file_) > len(ext):
|
if len(file_) > len(ext):
|
||||||
if file_[len(file_) - len(ext):] == ext:
|
if file_[len(file_) - len(ext):] == ext:
|
||||||
|
@ -95,6 +104,11 @@ def verify_file(file_):
|
||||||
|
|
||||||
|
|
||||||
def file_check(dir_):
|
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)
|
files = glob(dir_ + "/**/*", recursive=True)
|
||||||
suspicious_files = []
|
suspicious_files = []
|
||||||
for file_ in files:
|
for file_ in files:
|
||||||
|
|
Loading…
Reference in New Issue
Block a user