mirror of
https://github.com/Rushilwiz/SkoolOS.git
synced 2025-04-28 15:59:55 -04:00
Merge branch 'development' of github.com:Rushilwiz/SkoolOS into development
This commit is contained in:
commit
fd31dd3b0e
142
CLI/commands.py
142
CLI/commands.py
|
@ -5,4 +5,144 @@ import os
|
||||||
import argparse
|
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():
|
||||||
|
#get data from database
|
||||||
|
return
|
||||||
|
|
||||||
|
def yesorno(question):
|
||||||
|
questions = [
|
||||||
|
{
|
||||||
|
'type': 'input',
|
||||||
|
'name': 'response',
|
||||||
|
'message': question,
|
||||||
|
},
|
||||||
|
]
|
||||||
|
answers = prompt(questions)
|
||||||
|
if(answers["response"] == "y"):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def login():
|
||||||
|
#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():
|
||||||
|
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():
|
||||||
|
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
|
||||||
|
for c in user["classes"]:
|
||||||
|
os.makedirs(c)
|
||||||
|
for a in user["classes"][c]:
|
||||||
|
os.makedirs(c + "/" + a)
|
||||||
|
|
||||||
|
def start():
|
||||||
|
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))
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import sys
|
import sys
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests_oauthlib import OAuth2Session
|
from requests_oauthlib import OAuth2Session
|
||||||
from selenium import webdriver
|
from selenium import webdriver
|
||||||
|
@ -11,6 +10,10 @@ import socketserver
|
||||||
from threading import Thread
|
from threading import Thread
|
||||||
from werkzeug.urls import url_decode
|
from werkzeug.urls import url_decode
|
||||||
import pprint
|
import pprint
|
||||||
|
from PyInquirer import prompt, print_json
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import argparse
|
||||||
|
|
||||||
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
|
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
|
||||||
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
|
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
|
||||||
|
@ -30,16 +33,14 @@ def main():
|
||||||
print("")
|
print("")
|
||||||
|
|
||||||
if not os.path.exists(".profile"):
|
if not os.path.exists(".profile"):
|
||||||
print(76546789876545678765)
|
input("Welcome to SkoolOS. Press any key to create an account")
|
||||||
authenticate()
|
authenticate()
|
||||||
print(open(".profile", "r").read())
|
|
||||||
else:
|
else:
|
||||||
print(open(".profile", "r").read())
|
print(open(".profile", "r").read())
|
||||||
|
|
||||||
# while True:
|
# while True:
|
||||||
# pass
|
# pass
|
||||||
|
|
||||||
|
|
||||||
def authenticate():
|
def authenticate():
|
||||||
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
|
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
|
||||||
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
|
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
# Generated by Django 3.0.7 on 2020-06-12 01:34
|
# Generated by Django 3.0.7 on 2020-06-12 23:18
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.db import migrations, models
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -8,33 +10,10 @@ class Migration(migrations.Migration):
|
||||||
initial = True
|
initial = True
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
]
|
]
|
||||||
|
|
||||||
operations = [
|
operations = [
|
||||||
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)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Classes',
|
|
||||||
fields=[
|
|
||||||
('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
|
|
||||||
('repo', models.URLField(default='')),
|
|
||||||
('path', models.CharField(default='', max_length=100)),
|
|
||||||
('teacher', models.CharField(default='', max_length=100)),
|
|
||||||
('assignments', models.CharField(default='', max_length=100)),
|
|
||||||
('default_file', models.CharField(default='', max_length=100)),
|
|
||||||
('confirmed', models.TextField(blank=True, default='')),
|
|
||||||
('unconfirmed', models.TextField(blank=True, default='')),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='DefFiles',
|
name='DefFiles',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -46,6 +25,19 @@ class Migration(migrations.Migration):
|
||||||
('teacher', 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)),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teachers', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Student',
|
name='Student',
|
||||||
fields=[
|
fields=[
|
||||||
|
@ -61,18 +53,33 @@ class Migration(migrations.Migration):
|
||||||
('classes', models.CharField(blank=True, default='', max_length=100)),
|
('classes', models.CharField(blank=True, default='', max_length=100)),
|
||||||
('added_to', models.CharField(blank=True, default='', max_length=100)),
|
('added_to', models.CharField(blank=True, default='', max_length=100)),
|
||||||
('completed', models.TextField(blank=True, default='')),
|
('completed', models.TextField(blank=True, default='')),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='students', to=settings.AUTH_USER_MODEL)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Teacher',
|
name='Classes',
|
||||||
fields=[
|
fields=[
|
||||||
('created', models.DateTimeField(auto_now_add=True)),
|
('name', models.CharField(max_length=100, primary_key=True, serialize=False)),
|
||||||
('first_name', models.CharField(max_length=100)),
|
('repo', models.URLField(blank=True, default='')),
|
||||||
('last_name', models.CharField(max_length=100)),
|
('path', models.CharField(default='', max_length=100)),
|
||||||
('classes', models.CharField(blank=True, default='', max_length=100)),
|
('teacher', models.CharField(default='', max_length=100)),
|
||||||
('ion_user', models.CharField(max_length=100, primary_key=True, serialize=False)),
|
('assignments', models.TextField(blank=True, default='')),
|
||||||
('git', models.CharField(max_length=100)),
|
('default_file', models.CharField(blank=True, default='', max_length=100)),
|
||||||
('email', models.CharField(blank=True, default='', max_length=100)),
|
('confirmed', models.TextField(blank=True, default='')),
|
||||||
|
('unconfirmed', models.TextField(blank=True, default='')),
|
||||||
|
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='classes', 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)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 3.0.7 on 2020-06-12 01:35
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('api', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='assignment',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=100),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='assignment',
|
|
||||||
name='path',
|
|
||||||
field=models.CharField(max_length=100, primary_key=True, serialize=False),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,23 +0,0 @@
|
||||||
# Generated by Django 3.0.7 on 2020-06-12 01:35
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('api', '0002_auto_20200612_0135'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='assignment',
|
|
||||||
name='name',
|
|
||||||
field=models.CharField(max_length=100, primary_key=True, serialize=False),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='assignment',
|
|
||||||
name='path',
|
|
||||||
field=models.CharField(max_length=100),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,28 +0,0 @@
|
||||||
# Generated by Django 3.0.7 on 2020-06-12 08:13
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('api', '0003_auto_20200612_0135'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='classes',
|
|
||||||
name='assignments',
|
|
||||||
field=models.TextField(blank=True, default=''),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='classes',
|
|
||||||
name='default_file',
|
|
||||||
field=models.CharField(blank=True, default='', max_length=100),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='classes',
|
|
||||||
name='repo',
|
|
||||||
field=models.URLField(blank=True, default=''),
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -8,6 +8,8 @@ class DefFiles(models.Model):
|
||||||
teacher=models.CharField(max_length=100)
|
teacher=models.CharField(max_length=100)
|
||||||
|
|
||||||
class Assignment(models.Model):
|
class Assignment(models.Model):
|
||||||
|
owner = models.ForeignKey('auth.User', related_name='assignments', 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()
|
||||||
# files = models.ManyToManyField(DefFiles)
|
# files = models.ManyToManyField(DefFiles)
|
||||||
|
@ -19,6 +21,8 @@ class Assignment(models.Model):
|
||||||
return '%s' % (self.name)
|
return '%s' % (self.name)
|
||||||
|
|
||||||
class Classes(models.Model):
|
class Classes(models.Model):
|
||||||
|
owner = models.ForeignKey('auth.User', related_name='classes', on_delete=models.CASCADE)
|
||||||
|
|
||||||
name = models.CharField(primary_key=True, max_length=100)
|
name = models.CharField(primary_key=True, max_length=100)
|
||||||
repo=models.URLField(default="", blank=True)
|
repo=models.URLField(default="", blank=True)
|
||||||
path=models.CharField(max_length=100, default="")
|
path=models.CharField(max_length=100, default="")
|
||||||
|
@ -34,6 +38,8 @@ class Classes(models.Model):
|
||||||
return super(Classes, self).save(*args, **kwargs)
|
return super(Classes, self).save(*args, **kwargs)
|
||||||
|
|
||||||
class Teacher(models.Model):
|
class Teacher(models.Model):
|
||||||
|
owner = models.ForeignKey('auth.User', related_name='teachers', on_delete=models.CASCADE)
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
first_name = models.CharField(max_length=100)
|
first_name = models.CharField(max_length=100)
|
||||||
last_name = models.CharField(max_length=100)
|
last_name = models.CharField(max_length=100)
|
||||||
|
@ -44,6 +50,8 @@ class Teacher(models.Model):
|
||||||
email=models.CharField(max_length=100, default="", blank=True)
|
email=models.CharField(max_length=100, default="", blank=True)
|
||||||
|
|
||||||
class Student(models.Model):
|
class Student(models.Model):
|
||||||
|
owner = models.ForeignKey('auth.User', related_name='students', on_delete=models.CASCADE)
|
||||||
|
|
||||||
created = models.DateTimeField(auto_now_add=True)
|
created = models.DateTimeField(auto_now_add=True)
|
||||||
first_name = models.CharField(max_length=100)
|
first_name = models.CharField(max_length=100)
|
||||||
last_name = models.CharField(max_length=100)
|
last_name = models.CharField(max_length=100)
|
||||||
|
|
25
Website/api/permissions.py
Normal file
25
Website/api/permissions.py
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
|
||||||
|
class IsOwnerOrReadOnly(permissions.BasePermission):
|
||||||
|
"""
|
||||||
|
Custom permission to only allow owners of an object to edit it.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
# Read permissions are allowed to any request,
|
||||||
|
# so we'll always allow GET, HEAD or OPTIONS requests.
|
||||||
|
if request.method in permissions.SAFE_METHODS:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Write permissions are only allowed to the owner of the snippet.
|
||||||
|
return obj.owner == request.user
|
||||||
|
|
||||||
|
class isTeacher(permissions.BasePermission):
|
||||||
|
#only teachers can make classes and assignmenst
|
||||||
|
def has_object_permission(self, request, view, obj):
|
||||||
|
if request.method in permissions.SAFE_METHODS:
|
||||||
|
return True
|
||||||
|
|
||||||
|
# Write permissions are only allowed to the owner of the snippet.
|
||||||
|
return obj.user.groups.filter(name__in=['teachers']).exists()
|
|
@ -1,37 +1,56 @@
|
||||||
from django.contrib.auth.models import User, Group
|
from django.contrib.auth.models import User, Group
|
||||||
from .models import Student, Teacher, Classes, Assignment, DefFiles
|
from .models import Student, Teacher, Classes, Assignment, DefFiles
|
||||||
from rest_framework import serializers, permissions
|
from rest_framework import serializers, permissions
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
class UserSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
students = serializers.PrimaryKeyRelatedField(many=True, queryset=Student.objects.all())
|
||||||
|
owner = serializers.ReadOnlyField(source='owner.username')
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
|
|
||||||
permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = DefFiles
|
model = User
|
||||||
fields = ['name', 'path','assignment','classes', "teacher",'url', 'id']
|
fields = ['id', 'username', 'students']
|
||||||
|
|
||||||
|
# class DefFilesSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
|
# class Meta:
|
||||||
|
# model = DefFiles
|
||||||
|
# fields = ['name', 'path','assignment','classes', "teacher",'url', 'id']
|
||||||
|
|
||||||
class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
|
class AssignmentSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
#permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
#permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
# files = DefFilesSerializer(many=True, read_only=True,allow_null=True)
|
# files = DefFilesSerializer(many=True, read_only=True,allow_null=True)
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
owner = serializers.ReadOnlyField(source='owner.username')
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Assignment
|
model = Assignment
|
||||||
fields = ['url','name', 'due_date', 'path' , "classes","teacher"]
|
fields = ['url','name', 'due_date', 'path' , "classes","teacher",'owner']
|
||||||
|
|
||||||
class ClassesSerializer(serializers.HyperlinkedModelSerializer):
|
class ClassesSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
# assignments = AssignmentSerializer(many=True, read_only=True,allow_null=True)
|
# assignments = AssignmentSerializer(many=True, read_only=True,allow_null=True)
|
||||||
# default_file=DefFilesSerializer(many=True, read_only=True,allow_null=True)
|
# default_file=DefFilesSerializer(many=True, read_only=True,allow_null=True)
|
||||||
|
owner = serializers.ReadOnlyField(source='owner.username')
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Classes
|
model = Classes
|
||||||
fields = ['url', 'name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed']
|
fields = ['url', 'name', 'repo','path', "teacher",'assignments',"default_file", 'confirmed', 'unconfirmed','owner']
|
||||||
|
|
||||||
class StudentSerializer(serializers.HyperlinkedModelSerializer):
|
class StudentSerializer(serializers.HyperlinkedModelSerializer):
|
||||||
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
|
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
|
||||||
|
owner = serializers.ReadOnlyField(source='owner.username')
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Student
|
model = Student
|
||||||
fields = ['url', 'first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo']
|
fields = ['url', 'first_name', 'last_name', 'grade','email','student_id', 'git','ion_user','classes','added_to','completed', 'repo','owner']
|
||||||
|
|
||||||
class TeacherSerializer(serializers.ModelSerializer):
|
class TeacherSerializer(serializers.ModelSerializer):
|
||||||
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
|
# classes = ClassesSerializer(many=True, read_only=True,allow_null=True)
|
||||||
|
owner = serializers.ReadOnlyField(source='owner.username')
|
||||||
|
permission_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Teacher
|
model = Teacher
|
||||||
fields = ['url', 'first_name', 'last_name','git','ion_user', 'email','classes']
|
fields = ['url', 'first_name', 'last_name','git','ion_user', 'email','classes','owner']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,14 @@
|
||||||
from .models import Student, Teacher, Classes, Assignment, DefFiles
|
from .models import Student, Teacher, Classes, Assignment, DefFiles
|
||||||
from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, DefFilesSerializer
|
from .serializers import StudentSerializer, TeacherSerializer, ClassesSerializer, AssignmentSerializer, UserSerializer
|
||||||
from rest_framework import generics, viewsets, permissions, response, status
|
from rest_framework import generics, viewsets, permissions, response, status
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
class UserViewSet(viewsets.ModelViewSet):
|
||||||
|
queryset = User.objects.all()
|
||||||
|
serializer_class = UserSerializer
|
||||||
|
|
||||||
|
|
||||||
class StudentViewSet(viewsets.ModelViewSet):
|
class StudentViewSet(viewsets.ModelViewSet):
|
||||||
"""
|
"""
|
||||||
|
@ -39,10 +45,10 @@ class AssignmentViewSet(viewsets.ModelViewSet):
|
||||||
serializer_class = AssignmentSerializer
|
serializer_class = AssignmentSerializer
|
||||||
permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
|
||||||
class DefFilesViewSet(viewsets.ModelViewSet):
|
# class DefFilesViewSet(viewsets.ModelViewSet):
|
||||||
"""
|
# """
|
||||||
API endpoint that allows users to be viewed or edited.
|
# API endpoint that allows users to be viewed or edited.
|
||||||
"""
|
# """
|
||||||
queryset = DefFiles.objects.all()
|
# queryset = DefFiles.objects.all()
|
||||||
serializer_class = DefFilesSerializer
|
# serializer_class = DefFilesSerializer
|
||||||
permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
# permissions_classes = [permissions.IsAuthenticatedOrReadOnly]
|
||||||
|
|
|
@ -135,4 +135,4 @@ STATIC_URL = '/static/'
|
||||||
|
|
||||||
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
CRISPY_TEMPLATE_PACK = 'bootstrap4'
|
||||||
|
|
||||||
LOGIN_REDIRECT_URL = '/'
|
LOGIN_REDIRECT_URL = '/'
|
||||||
|
|
|
@ -10,8 +10,8 @@ router.register(r'students', api_views.StudentViewSet)
|
||||||
router.register(r'teachers', api_views.TeacherViewSet)
|
router.register(r'teachers', api_views.TeacherViewSet)
|
||||||
router.register(r'assignments', api_views.AssignmentViewSet)
|
router.register(r'assignments', api_views.AssignmentViewSet)
|
||||||
router.register(r'classes', api_views.ClassesViewSet)
|
router.register(r'classes', api_views.ClassesViewSet)
|
||||||
router.register(r'files', api_views.DefFilesViewSet)
|
# router.register(r'files', api_views.DefFilesViewSet)
|
||||||
|
router.register(r'users', api_views.UserViewSet)
|
||||||
|
|
||||||
# Wire up our API using automatic URL routing.
|
# Wire up our API using automatic URL routing.
|
||||||
# Additionally, we include login URLs for the browsable API.
|
# Additionally, we include login URLs for the browsable API.
|
||||||
|
@ -19,5 +19,8 @@ urlpatterns = [
|
||||||
path('api/', include(router.urls)),
|
path('api/', include(router.urls)),
|
||||||
path('api-auth/', include('rest_framework.urls')),
|
path('api-auth/', include('rest_framework.urls')),
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
path('login/', auth_views.LoginView.as_view(template_name="users/login.html"), name='login')
|
path('login/', auth_views.LoginView.as_view(template_name="users/login.html"), name='login'),
|
||||||
]
|
path('register/', user_views.register, name='register'),
|
||||||
|
path('create_account/', user_views.create_account, name='create_account'),
|
||||||
|
path('callback/', user_views.callback, name='callback'),
|
||||||
|
]
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from .models import Token
|
||||||
|
|
||||||
# Register your models here.
|
# Register your models here.
|
||||||
|
admin.site.register(Token)
|
||||||
|
|
19
Website/users/forms.py
Normal file
19
Website/users/forms.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from django import forms
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
|
||||||
|
class UserCreationForm(forms.ModelForm):
|
||||||
|
|
||||||
|
username = forms.CharField(disabled=True)
|
||||||
|
email = forms.EmailField(disabled=True)
|
||||||
|
first_name = forms.CharField(disabled=True)
|
||||||
|
last_name = forms.CharField(disabled=True)
|
||||||
|
password = forms.PasswordInput()
|
||||||
|
confirm_password = forms.PasswordInput()
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super(UserCreationForm, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = User
|
||||||
|
fields = ['username', 'email', 'first_name', 'password', 'confirm_password']
|
26
Website/users/migrations/0001_initial.py
Normal file
26
Website/users/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
# Generated by Django 3.0.7 on 2020-06-13 08:25
|
||||||
|
|
||||||
|
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)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,3 +1,21 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
from uuid import uuid4
|
||||||
|
|
||||||
|
|
||||||
# Create your models here.
|
# Create your models here.
|
||||||
|
|
||||||
|
class Token(models.Model):
|
||||||
|
username = models.TextField()
|
||||||
|
email = models.TextField()
|
||||||
|
first_name = models.TextField()
|
||||||
|
last_name = models.TextField()
|
||||||
|
isStudent = models.BooleanField()
|
||||||
|
token = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
def save(self, *args, **kwargs):
|
||||||
|
if not self.token:
|
||||||
|
self.token = uuid4()
|
||||||
|
return super(Token, self).save(*args, **kwargs)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.username}'s Token";
|
||||||
|
|
13
Website/users/templates/users/create_password.html
Normal file
13
Website/users/templates/users/create_password.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "users/base.html" %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="login-page">
|
||||||
|
<div class="form">
|
||||||
|
<form class="register-form">
|
||||||
|
<input type="text" placeholder="name"/>
|
||||||
|
<input type="password" placeholder="password"/>
|
||||||
|
<input type="text" placeholder="email address"/>
|
||||||
|
<button>create</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -8,9 +8,9 @@
|
||||||
{% csrf_token %}
|
{% csrf_token %}
|
||||||
{{ form | crispy }}
|
{{ form | crispy }}
|
||||||
<button type="submit">login</button>
|
<button type="submit">login</button>
|
||||||
<p class="message">Not registered? <a href="#">Create an account with Ionreg</a></p>
|
<p class="message">Not registered? <a href="{% url 'register' %}">Create an account with Ion</a></p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -3,13 +3,13 @@
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="login-page">
|
<div class="login-page">
|
||||||
<div class="form">
|
<div class="form">
|
||||||
<form class="login-form" method="POST">
|
<div class="content-section">
|
||||||
{% csrf_token %}
|
<a href="{{ authorization_url }}" title="Ion" class="border border-dark p-3 btn btn-block btn-lg mx-auto" style="background: black; color: white;">
|
||||||
{{ form | crispy }}
|
<img src="https://ion.tjhsst.edu/static/img/favicon.png" style="filter: invert(1);">
|
||||||
<button type="submit">login</button>
|
Register with Ion
|
||||||
<p class="message">Not registered? <a href="#">Create an account with Ionreg</a></p>
|
</a>
|
||||||
</form>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,3 +1,80 @@
|
||||||
from django.shortcuts import render
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
from django.shortcuts import render, redirect
|
||||||
|
|
||||||
|
from requests_oauthlib import OAuth2Session
|
||||||
|
from django.contrib import messages
|
||||||
|
|
||||||
|
from .models import Token
|
||||||
|
|
||||||
|
from django.contrib.auth import authenticate
|
||||||
|
from django.contrib.auth import login as auth_login
|
||||||
|
from django.contrib.auth import logout as auth_logout
|
||||||
|
from django.contrib.auth.models import User
|
||||||
|
from django.contrib.auth.decorators import login_required
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
# Thanks Django, what would I do without this comment
|
||||||
|
|
||||||
|
client_id = r'QeZPBSKqdvWFfBv1VYTSv9iFGz5T9pVJtNUjbEr6'
|
||||||
|
client_secret = r'0Wl3hAIGY9SvYOqTOLUiLNYa4OlCgZYdno9ZbcgCT7RGQ8x2f1l2HzZHsQ7ijC74A0mrOhhCVeZugqAmOADHIv5fHxaa7GqFNtQr11HX9ySTw3DscKsphCVi5P71mlGY'
|
||||||
|
redirect_uri = 'http://localhost:8000/callback/'
|
||||||
|
token_url = 'https://ion.tjhsst.edu/oauth/authorize/'
|
||||||
|
scope=["read"]
|
||||||
|
|
||||||
|
def register(request):
|
||||||
|
oauth = OAuth2Session(client_id=client_id, redirect_uri=redirect_uri, scope=scope)
|
||||||
|
authorization_url, state = oauth.authorization_url("https://ion.tjhsst.edu/oauth/authorize/")
|
||||||
|
|
||||||
|
return render(request,"users/register.html", {"authorization_url": authorization_url})
|
||||||
|
|
||||||
|
def callback (request):
|
||||||
|
if request.method == "GET":
|
||||||
|
code = request.GET.get('code')
|
||||||
|
state = request.GET.get("state")
|
||||||
|
# Then if we get a response from Ion with the authorization code
|
||||||
|
if code is not None and state is not None:
|
||||||
|
print ("made it")
|
||||||
|
# We send it back to fetch the acess_token
|
||||||
|
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()
|
||||||
|
headers = {'Authorization': f"Bearer {token['access_token']}"}
|
||||||
|
print(token)
|
||||||
|
|
||||||
|
# And finally get the user's profile!
|
||||||
|
profile = requests.get("https://ion.tjhsst.edu/api/profile", headers=headers).json()
|
||||||
|
print(profile)
|
||||||
|
username = profile['ion_username']
|
||||||
|
email = profile['tj_email']
|
||||||
|
first_name = profile['first_name']
|
||||||
|
last_name = profile['last_name']
|
||||||
|
isStudent = profile['is_student']
|
||||||
|
|
||||||
|
if User.objects.filter(username=username).count() != 0:
|
||||||
|
messages.success(request, "This user already exists!")
|
||||||
|
return redirect('register')
|
||||||
|
else:
|
||||||
|
token = Token(username = username, email = email, first_name = first_name, last_name = last_name, isStudent = isStudent)
|
||||||
|
token.save()
|
||||||
|
tokenHash = token.token
|
||||||
|
print(f'/create_account/?token={tokenHash}')
|
||||||
|
return redirect(f'/create_account/?token={tokenHash}')
|
||||||
|
|
||||||
|
|
||||||
|
messages.warning(request, "Invalid Callback Response")
|
||||||
|
return redirect('register')
|
||||||
|
|
||||||
|
|
||||||
|
def create_account (request):
|
||||||
|
if request.method == "GET" and Token.objects.filter(token=request.GET.get('token')).count() == 1:
|
||||||
|
token = Token.objects.get(token=request.GET.get('token'))
|
||||||
|
username = token.username
|
||||||
|
email = token.email
|
||||||
|
first_name = token.first_name
|
||||||
|
last_name = token.last_name
|
||||||
|
isStudent = token.isStudent
|
||||||
|
|
||||||
|
|
||||||
|
else:
|
||||||
|
return redirect('/register/')
|
||||||
|
|
BIN
chromedriver-linux
Executable file
BIN
chromedriver-linux
Executable file
Binary file not shown.
BIN
chromedriver.exe
Normal file
BIN
chromedriver.exe
Normal file
Binary file not shown.
|
@ -1,2 +0,0 @@
|
||||||
for i in range(0, 100000):
|
|
||||||
print(i)
|
|
Loading…
Reference in New Issue
Block a user