diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2baa2f --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# planzz + +Planzz is a student course management system designed to help students find friends in the same classes as them. It enables the students to find friends or meet their peers in advance to get discussions going. + +Planzz utilizes Django 1.8.4 as it's framework and is written entirely in Python 3.5.0. diff --git a/StudentManager/models.py b/StudentManager/models.py index 2b2f9db..e7c7457 100644 --- a/StudentManager/models.py +++ b/StudentManager/models.py @@ -38,7 +38,6 @@ def __unicode__(self): def get_students(self): return self.students.all() -<<<<<<< HEAD def save(self, *args, **kwargs): self.current_enrolment = self.student_set.count() super(Lecture, self).__init__(*args, **kwargs) @@ -56,3 +55,35 @@ def save(self, *args, **kwargs): def __unicode__(self): return self.name + + +class OAuthError(RuntimeError): + """Generic exception class.""" + def __init__(self, message='OAuth error occured.'): + self.message = message + + +from oauth2_provider.models import AccessToken + +def verify_access_token(key): + # Import the AccessToken model + # try: + # model = AccessToken + # model_parts = str(model).split('.') + # module_path = '.'.join(model_parts[:-1]) + # module = __import__(module_path, globals(), locals(), ['AccessToken']) + # AccessToken = getattr(module, model_parts[-1]) + # except: + # raise OAuthError("Error importing AccessToken model") + + # Check if key is in AccessToken key + try: + token = AccessToken.objects.get(token=key) + + # Check if token has expired + if token.expires < timezone.now(): + raise OAuthError('AccessToken has expired.') + except AccessToken.DoesNotExist: + raise OAuthError("AccessToken not found at all.") + + return token diff --git a/db.sqlite3 b/db.sqlite3 index 08e1a8c..0c08071 100644 Binary files a/db.sqlite3 and b/db.sqlite3 differ diff --git a/planzz/settings.py b/planzz/settings.py index 6dc2717..f23851f 100644 --- a/planzz/settings.py +++ b/planzz/settings.py @@ -29,9 +29,9 @@ ALLOWED_HOSTS = [] -AUTH_USER_MODEL = 'django_facebook.FacebookCustomUser' - -AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile' +# AUTH_USER_MODEL = 'django_facebook.FacebookCustomUser' +# +# AUTH_PROFILE_MODULE = 'django_facebook.FacebookProfile' # Application definition @@ -42,8 +42,8 @@ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', - 'django_facebook', - 'tastypie' + # 'django_facebook', + 'tastypie', ) MIDDLEWARE_CLASSES = ( @@ -54,11 +54,10 @@ 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', - 'django.middleware.security.SecurityMiddleware', ) AUTHENTICATION_BACKENDS = ( - 'django_facebook.auth_backends.FacebookBackend', + # 'django_facebook.auth_backends.FacebookBackend', 'django.contrib.auth.backends.ModelBackend', ) diff --git a/planzz/urls.py b/planzz/urls.py index 2bbe9b5..c1ba49f 100644 --- a/planzz/urls.py +++ b/planzz/urls.py @@ -18,11 +18,12 @@ from planzz import views urlpatterns = [ - url(r'^admin$', include(admin.site.urls)), - url(r'^facebook$', include('django_facebook.urls')), - url(r'^accounts$', include('django_facebook.auth_urls')), url(r'^$', views.index, name='index'), url(r'^signup$', views.signup), url(r'^login$', views.login), - url(r'^schedule$', views.schedule) + url(r'^schedule$', views.schedule), + url(r'^signupprocess$', views.signupprocess), + url(r'^admin/', include(admin.site.urls)), + url(r'^loginprocess$', views.loginprocess), + url(r'^friends$', views.friends) ] diff --git a/planzz/views.py b/planzz/views.py index 5b676ef..0579ed8 100644 --- a/planzz/views.py +++ b/planzz/views.py @@ -1,12 +1,99 @@ from django.shortcuts import render, render_to_response +from django.http import HttpResponse +from django.http import HttpResponseRedirect +from django.template import RequestContext +from django.contrib import auth +from django import forms +from templates import forms + +from django.views.decorators.csrf import csrf_exempt +from django.contrib.auth import authenticate +from django.contrib.auth.forms import UserCreationForm + +from django.views.decorators.csrf import csrf_exempt + # Create your views here. def index(request): return render_to_response('index.html') def signup(request): return render_to_response('signup.html') + def login(request): + return render_to_response('login.html'); + +@csrf_exempt +def loginprocess(request): + user = authenticate(username=request.POST['email'], password=request.POST['password']) + print(user) + if (user is not None): + return HttpResponse('Logged in') + else: + return HttpResponse('Username or Password incorrect.') return render_to_response('login.html') + +@csrf_exempt +def signupprocess(request): + form = forms.RegisterForm(request.POST) + if form.is_valid(): + if form.cleaned_data['password'] == form.cleaned_data['confirm']: + form.save() + return render_to_response('schedule.html') + + return render_to_response('signup.html') + + #print(email) + #print(password) + + #student = Student() + def schedule(request): return render_to_response('schedule.html') + +def login_view(request): + username = request.POST.get('username', '') + password = request.POST.get('password', '') + user = auth.authenticate(username=username, password=password) + if user is not None and user.is_active: + auth.login(request, user) + return HttpResponseRedirect('/account/logedin/') + else: + return HttpResponseRedirect('/account/invalid/') + +def profile(request): + return render_to_response('registration/profile.html', {'username':request.user.username, 'user':request.user}) + +def register(request): + if request.method == 'POST': + form = UserCreationForm(request.POST) + if form.is_valid(): + new_user = form.save() + return HttpResponseRedirect('/accounts/signup/success/') + else: + form = UserCreationForm() + return render_to_response("registration/register.html", { + 'form': form, + }, RequestContext(request)) + +# def signup_success(request): +# return render_to_response('registration/signup_success.html') + +def invite(request): + return render_to_response('invite.html'); + +def home(request): + if request.method == 'POST': + form = UserCreationForm(request.POST) + if form.is_valid(): + new_user = form.save() + return HttpResponseRedirect('/accounts/profile/') + else: + form = UserCreationForm() + return render_to_response('index.html', { + 'form': form, + }, RequestContext(request)) + +def friends(request): + return render_to_response('friends.html') + diff --git a/src/pip-delete-this-directory.txt b/src/pip-delete-this-directory.txt new file mode 100644 index 0000000..c8883ea --- /dev/null +++ b/src/pip-delete-this-directory.txt @@ -0,0 +1,5 @@ +This file is placed here by pip to indicate the source was put +here by pip. + +Once this package is successfully installed this source code will be +deleted (unless you remove this file). diff --git a/src/tastypie b/src/tastypie new file mode 160000 index 0000000..b414196 --- /dev/null +++ b/src/tastypie @@ -0,0 +1 @@ +Subproject commit b4141969e91c03762682f0edbf4c23b63eaabb45 diff --git a/static/css/custom.css b/static/css/custom.css index 0205b85..d2f47a0 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1,7 +1,16 @@ +html { + background-color: rgba(46, 169, 223, 1); +} body { font-family: 'Titillium Web', sans-serif; color: black; } +/* color the table */ +table, tr, td, th { + color: white; + border: white 2px solid; + height: 70px; +} nav.navbar-default { margin-bottom: 0; box-shadow: none; @@ -40,9 +49,14 @@ header .header-content .header-content-inner p { font-size: 65px; text-align: center; } - +h1.header { + margin-top: 0px; + padding-top: 127px; + color: #fff; +} .sub-header { font-size: 30px !important; + color: #fff; } .learn { @@ -125,4 +139,32 @@ section.main.containersignup { .navbar-default .navbar-link:hover, .navbar-default .navbar-link{ color: white; +} + +#maintable { + margin-left: 20%; +} +#friendlist { + margin-left: 16%; + margin-bottom: 5%; +} +#coursedetails { + margin-left: 20%; + color: #fff; +} +#courses { + background-color: #2EA9DF; + width: 70%; + height: 6%; + color: #fff; + border: 2px solid #FFF; + border-radius: 2px; + font-size: 22px; +} +#signup.addclass { + margin-left: 59px !important; + margin-bottom: 13px; +} +a.learn.btn.register { + margin-top: 40px; } \ No newline at end of file diff --git a/static/js/custom.js b/static/js/custom.js new file mode 100644 index 0000000..adce712 --- /dev/null +++ b/static/js/custom.js @@ -0,0 +1,15 @@ +$(document).ready(function(){ + $("#coursedetails").hide(); + $("#courses").change(function(){ + $("#coursedetails").show(); + }); + + $("a.learn.btn.register").click(function(){ + $(".9mon").append("CSC236"); + $(".9tue").append("CSC236"); + $(".9wed").append("CSC236"); + $(".9thu").append("CSC236"); + $(".9fri").append("CSC236"); + }); + +}); \ No newline at end of file diff --git a/static/js/facebook.js b/static/js/facebook.js new file mode 100644 index 0000000..15124bd --- /dev/null +++ b/static/js/facebook.js @@ -0,0 +1,55 @@ +$(document).ready(function(){ +//global vars +var friends = []; + +window.fbAsyncInit = function() { + FB.init({ + appId : '507349916095512', + xfbml : true, + version : 'v2.4' + }); + + FB.login(function(response) { + // handle the response + FB.api( + "/me/taggable_friends", + function (response) { + if (response && !response.error) { + /* handle the result */ + console.log(response.data); + friends = response.data; + for(var i = 0; i < friends.length; i++){ + var extra = ""; + if(i == 0){ + extra = "In your CSC236 class"; + } else if(i == 1){ + extra = "In your CSC209 class"; + } else if(i == 2){ + extra = "In your CSC343, MAT235 and PHL100 class"; + } else { + extra = "In none of your classes"; + } + var row = "" + + "" + + "" + friends[i].name + "
" + extra + "" + + ""; + + $("#friendlist").append(row); + } + } + } + ); + }, {scope: 'user_friends'}); + +}; + +(function(d, s, id){ + var js, fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) {return;} + js = d.createElement(s); js.id = id; + js.src = "//connect.facebook.net/en_US/sdk.js"; + fjs.parentNode.insertBefore(js, fjs); +}(document, 'script', 'facebook-jssdk')); + + +}); diff --git a/tastypie_oauth/__init__.py b/tastypie_oauth/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tastypie_user/__init__.py b/tastypie_user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tastypie_user/resources.py b/tastypie_user/resources.py new file mode 100644 index 0000000..bbb6a4d --- /dev/null +++ b/tastypie_user/resources.py @@ -0,0 +1,133 @@ +try: + import json +except ImportError: + from django.utils import simplejson as json +from tastypie.resources import ModelResource +from tastypie.exceptions import ImmediateHttpResponse, BadRequest +from StudentManager.models import Student as User +from django.contrib import auth +from django.conf import settings +from django.http import HttpResponse +from tastypie import http + +from tastypie_oauth.authentication import OAuth20Authentication +from tastypie.authorization import DjangoAuthorization + +from django.utils import timezone + +class UserResource(ModelResource): + + def show_keys(self, request): + if request.user.is_authenticated(): + #api_key = request.user.api_key.key + keys = { + 'username': request.user.username, + #'api_key': api_key, + 'session_name': settings.SESSION_COOKIE_NAME, + 'session_key': request.session.session_key} + raise ImmediateHttpResponse( + HttpResponse(json.dumps(keys), content_type='application/json') + ) + else: + raise BadRequest('not login') + + # def obj_get_list(self, request=None, **kwargs): + # raise BadRequest('not allowed') + + def obj_create(self, bundle, **kwargs): + request = bundle.request + create_type = bundle.data.pop('type') + try: + key = request.GET.get('oauth_consumer_key') + my_user = User.objects.get(username = verify_access_token(key).user.username) + except OAuthError: + my_user = None + + if create_type == 'register': + + password1 = bundle.data.pop('password1') + password2 = bundle.data.pop('password2') + email = bundle.data.pop('email') + + if (password1 == password2): + new_user = User.objects.create_user(email, password1) + new_user.save() + bundle.obj = new_user + raise ImmediateHttpResponse(http.HttpAccepted()) + else: + raise BadRequest('signup error: password did not match') + # form = USER_CREATION_FORM(bundle.data) + # if form.is_valid(): + # new_user = form.save() + # new_user.send_email('activate') + # bundle.obj = new_user + # raise ImmediateHttpResponse(http.HttpAccepted()) + # #auto login, means request twice, first register, then login! + # else: + # #output the errors for tatstypie + # bundle.errors[self._meta.resource_name] = form.errors + # raise ImmediateHttpResponse(self.error_response(request, bundle.errors)) + + elif create_type == 'login': + expiry_seconds = bundle.data.pop('expiry_seconds', None) + user = auth.authenticate(**bundle.data) + + if user is not None and user.is_active: + auth.login(request, user) + if expiry_seconds: + request.session.set_expiry(int(expiry_seconds)) + self.show_keys(request) + + elif user is not None and not user.is_active: + raise BadRequest('not active') + else: + raise BadRequest('login error') + + + def get_detail(self, request=None, **kwargs): + if kwargs.get('pk') == 'keys': + self.show_keys(request) + else: + return super(UserResource, self).get_detail(request, **kwargs) + + def dehydrate(self, bundle): + + bundle.data['email'] = '' + bundle.data['password'] = '' + return bundle + + class Meta: + queryset = User.objects.all() + resource_name = 'user' + authorization = DjangoAuthorization() + authentication = OAuth20Authentication() + +from oauth2_provider.models import AccessToken + +class OAuthError(RuntimeError): + """Generic exception class.""" + def __init__(self, message='OAuth error occured.'): + self.message = message + +def verify_access_token(key): + # Import the AccessToken model + # try: + # model = AccessToken + # model_parts = str(model).split('.') + # module_path = '.'.join(model_parts[:-1]) + # module = __import__(module_path, globals(), locals(), ['AccessToken']) + # AccessToken = getattr(module, model_parts[-1]) + # except: + # raise OAuthError("Error importing AccessToken model") + + # Check if key is in AccessToken key + try: + token = AccessToken.objects.get(token=key) + + # Check if token has expired + if token.expires < timezone.now(): + raise OAuthError('AccessToken has expired.') + except AccessToken.DoesNotExist: + raise OAuthError("AccessToken not found at all.") + + return token diff --git a/templates/addclass.html b/templates/addclass.html new file mode 100644 index 0000000..a7413dd --- /dev/null +++ b/templates/addclass.html @@ -0,0 +1,55 @@ + + + + {% load staticfiles %} + + + + + + + + + + + + + + + + + +
+

Add a class

+ +
+ +
+
+ + + \ No newline at end of file diff --git a/templates/forms.py b/templates/forms.py new file mode 100644 index 0000000..dbe3055 --- /dev/null +++ b/templates/forms.py @@ -0,0 +1,13 @@ +from django import forms +from django.contrib.auth.models import User + +class RegisterForm(forms.Form): + email = forms.EmailField() + password = forms.CharField(max_length=100) + confirm = forms.CharField(max_length=100) + + def save(self): + data = self.cleaned_data + user = User(username=data['email'], email=data['email'], password=data['password']) + user.save() + \ No newline at end of file diff --git a/templates/friends.html b/templates/friends.html new file mode 100644 index 0000000..1badb9b --- /dev/null +++ b/templates/friends.html @@ -0,0 +1,56 @@ + + + + {% load staticfiles %} + + + + + + + + + + + + + + + + + +
+

Friends

+ + +
+ +
+ + + + \ No newline at end of file diff --git a/templates/index.html b/templates/index.html index 489a05b..088ad3c 100644 --- a/templates/index.html +++ b/templates/index.html @@ -47,10 +47,10 @@

Resolve conflicts effectively!

- Sign up + Sign up
- Login + Login
diff --git a/templates/login.html b/templates/login.html index e329b5c..5eeae08 100644 --- a/templates/login.html +++ b/templates/login.html @@ -27,15 +27,15 @@ - Planzz + Planzz @@ -45,11 +45,11 @@

Login

-
+

- Log in + Log in
diff --git a/templates/schedule.html b/templates/schedule.html index ad5204b..1873280 100644 --- a/templates/schedule.html +++ b/templates/schedule.html @@ -1,4 +1,5 @@ + {% load staticfiles %} @@ -27,15 +28,15 @@ - Planzz + Planzz @@ -45,7 +46,111 @@

Your schedule

- +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SundayMondayTuesdayWednesdayThursdayFridaySaturday
9am
10am
11am
12 noon
1pm
2pm
3pm
+ + Add a Class + +
+ +
+ + + + +
+

CSC309 - Web and Internet programming

+

These people are in your courses:

+

Bob Jones

+

Bill James

+ Register for this course +
+
diff --git a/templates/signup.html b/templates/signup.html index 1ffa4c3..58cbb90 100644 --- a/templates/signup.html +++ b/templates/signup.html @@ -1,17 +1,17 @@ - + {% load staticfiles %} - + - + - + @@ -27,32 +27,32 @@ - Planzz + Planzz - +

Signup

-
+


- - Sign up + +
- - \ No newline at end of file + +