diff --git a/SE_API/API.py b/SE_API/API.py index d8f1be3..2e66002 100644 --- a/SE_API/API.py +++ b/SE_API/API.py @@ -1,3 +1,4 @@ + __author__ = 'sagi' import json from GithubAPI.GithubAPI import GitHubAPI_Keys @@ -14,10 +15,13 @@ from flask.ext.autodoc import Autodoc # DB Models from models.User import User +from models.Course import Course +from models.Project import Project from models.Campus import Campus #Validation Utils Libs from SE_API.Validation_Utils import * +from SE_API.Respones_Utils import * @@ -41,6 +45,70 @@ def page_not_found(e): def wellcomePage(): return app.send_static_file('index.html') +@app.route('/api/validation/confirm/') +@auto.doc() +def confirm_user_to_campus(validation_token): + """ + This Function is will re + :param validation_token: 'seToken|email_suffix' + :return: + 200 - redirect to home + new cookie + 403 - Invalid Token + """ + #TODO + token = str(validation_token).split('|')[0] + email_sufix = '@'+str(validation_token).split('|')[1] + + user = get_user_by_token(token) + + if user is None: + return forbidden('Forbidden: invalid Token') + else: + campus = get_campus_by_suffix(email_sufix) + if campus is None: + return bad_request('Bad Request: Email Suffix ' + email_sufix + ' Not Found') + user.isFirstLogin = False + user.seToken = str(uuid.uuid4()) + if str(campus.key().id()) not in user.campuses_id_list: + user.campuses_id_list.append(str(campus.key().id())) + db.put(user) + return cookieMonster(user.seToken) + + + +@app.route('/api/validation/sendmail/', methods=['POST']) +@auto.doc() +def send_activation(token): + """ + This Method Will Send An Email To The User - To Confirm his Account + :param token: - seToken + :payload: JSON - {email: 'academic@email.ac.com'} + :return: + 200 - Email Sent - No Response + 400 - Bad Request + 403 - Invalid Token + """ + if not request.data: + return Response(response=json.dumps({'message': 'Bad Request'}), + status=400, + mimetype="application/json") + payload = json.loads(request.data) + if not is_user_token_valid(token): + return Response(response=json.dumps({'message': 'Not A Valid Token!'}), + status=403, + mimetype="application/json") + query = User.all() + query.filter('seToken =', token) + for u in query.run(limit=1): + try: + send_validation_email(token=token, name=u.username, email=payload["email"]) + except Exception: + return Response(response=json.dumps({'message': 'Bad Request'}), + status=400, + mimetype="application/json") + + return Response(status=200) + @app.route('/api/help') def documentation(): return auto.html() @@ -67,8 +135,8 @@ def getUserByToken(token): for u in query.run(limit=5): return Response(response=u.to_JSON(), - status=201, - mimetype="application/json") # Real response! + status=201, + mimetype="application/json") # Real response! return Response(response=json.dumps({'message' : 'No User Found'}), status=400, @@ -95,7 +163,7 @@ def oauth(oauth_token): print user_data["login"] - for u in resault.run(limit=5): + for u in resault.run(): print "Exists!!!" u.seToken = str(uuid.uuid4()) u.accessToken = oauth_token @@ -111,12 +179,58 @@ def oauth(oauth_token): else: tempEmail = user_data["email"] - user = User(username=user_data["login"], name=tempName, avatar_url=user_data["avatar_url"], email=tempEmail, isLecturer=False, accsessToken=oauth_token, seToken=str(uuid.uuid4())) + user = User(username=user_data["login"], name=tempName, avatar_url=user_data["avatar_url"], email=tempEmail, isLecturer=False, accessToken=oauth_token, seToken=str(uuid.uuid4())) db.put(user) db.save return cookieMonster(user.seToken) +@app.route('/api/Campuses/create/', methods=['POST']) +@auto.doc() +def create_campus(token): + """ + This call will create a new campus in the DB + :param token: user seToken + Payload + {'title': self.title, + 'email_ending': self.email_ending, + 'avatar_url': self.avatar_url + } + :return: + code 200 + """ + print "1\n" + if not request.data: + return Response(response=json.dumps({'message': 'Bad Request0'}), + status=400, + mimetype="application/json") + payload = json.loads(request.data) + if not is_lecturer(token): #todo: change to lecturer id + return Response(response=json.dumps({'message': 'Invalid token or not a lecturer!'}), + status=403, + mimetype="application/json") + + user = get_user_by_token(token) + + #todo: check legality + + + try: + campus = Campus(title=payload['title'], email_ending=payload['email_ending'], master_user_id=user.key().id(), avatar_url=payload['avatar_url']) + except Exception: + return Response(response=json.dumps({'message': 'Bad Request1'}), + status=400, + mimetype="application/json") + + db.put(campus) + db.save + return Response(response=json.dumps(campus.to_JSON()), + status=200, + mimetype="application/json") + + + + @app.route('/api/Campuses/', methods=['GET']) @auto.doc() def get_campuses(token): @@ -135,7 +249,7 @@ def get_campuses(token): .... { ... - } + }req ] code 403: Forbidden - Invalid Token diff --git a/SE_API/Respones_Utils.py b/SE_API/Respones_Utils.py new file mode 100644 index 0000000..b789974 --- /dev/null +++ b/SE_API/Respones_Utils.py @@ -0,0 +1,15 @@ +__author__ = 'Aran' + +from flask import Response +import json + +def bad_request(message='Bad Request'): + return Response(response=json.dumps({'message': message}), + status=400, + mimetype="application/json") + + +def forbidden(message='Forbidden'): + return Response(response=json.dumps({'message': message}), + status=403, + mimetype="application/json") \ No newline at end of file diff --git a/SE_API/Validation_Utils.py b/SE_API/Validation_Utils.py index e074f13..e99b2bd 100644 --- a/SE_API/Validation_Utils.py +++ b/SE_API/Validation_Utils.py @@ -1,11 +1,81 @@ __author__ = 'sagi' from google.appengine.ext import db from models.User import User +from models.Campus import Campus +from google.appengine.api import mail -def is_user_token_valid(token): + +def get_user_by_token(token): query = User.all() query.filter("seToken = ", token) - for u in query.run(): + for u in query.run(limit = 1): + return u + return None + +def get_campus_by_suffix(suffix): + query = Campus.all() + query.filter("email_ending = ", suffix) + + for c in query.run(limit = 1): + return c + return None + +def is_user_token_valid(token): + user = get_user_by_token(token) + if user is not None: return True return False + +def is_lecturer(token): + user = get_user_by_token(token) + if user is None: + return False + return user.isLecturer + + +def send_validation_email(token, email, name): + emailSuffix = str(email).split('@')[1] + message = mail.EmailMessage(sender="SE-Hub Support ", + subject="SE-Hub Activate Account") + + message.to = email + + message.body = """ + Dear """+name+""": + + To Activate your SE-Hub Account please click on the link below:
+ http://se-hub.appspot.com/api/validation/confirm/"""+token+"""|"""+emailSuffix+""" + to get access to your Campus :) + + Please let us know if you have any questions. + + SE-Hub (c) 2015 niptop Team. + """ + + message.html = """ + +
+
+ + +
+
+
+

Hey """+name+"""- Just one More Step...

+

Dear """+name+""":

+ + To Activate your SE-Hub Account please click on the link below:
+ http://se-hub.appspot.com/api/validation/confirm/"""+token+"""|"""+emailSuffix+""" + + to access you virtual class. +
+

+ Please let us know if you have any questions. +
+ SE-Hub (c) 2015 niptop Team. + + + """ + + message.send() diff --git a/models/Campus.py b/models/Campus.py index 4859409..f4e9cef 100644 --- a/models/Campus.py +++ b/models/Campus.py @@ -11,12 +11,12 @@ class Campus(db.Model): master_user_id = db.IntegerProperty(required=True) def to_JSON(self): - dick = {'title': self.title, + data = {'title': self.title, 'email_ending': self.email_ending, 'master_user_id': self.master_user_id, 'avatar_url': self.avatar_url } - return json.dumps(dick) + return json.dumps(data) """ diff --git a/models/Course.py b/models/Course.py new file mode 100644 index 0000000..83557a7 --- /dev/null +++ b/models/Course.py @@ -0,0 +1,22 @@ +import json + +__author__ = 'Aran' +from google.appengine.ext import db + +class Course(db.Model): + courseName = db.StringProperty(required=True) + campusName = db.StringProperty(required=True) + projects = db.StringListProperty(required=True) + startDate = db.DateProperty(required=True) + endDate = db.DateProperty(required=False) + taskFlag = db.BooleanProperty(required=True) + + def to_JSON(self): + data = {'courseName' : self.courseName, + 'campusName' : self.campusName, + 'projects' : self.projects, + 'startDate' : self.startDate, + 'endDate' : self.endDate, + 'taskFlag' : self.taskFlag, + } + return json.dumps(data) diff --git a/models/Project.py b/models/Project.py new file mode 100644 index 0000000..edecd83 --- /dev/null +++ b/models/Project.py @@ -0,0 +1,20 @@ +import json + +__author__ = 'Aran' +from google.appengine.ext import db + +class Project(db.Model): + projectName = db.StringProperty(required=True) + grade = db.IntegerProperty(required=True) + logo_url = db.StringProperty(required=True) + gitRepository = db.StringProperty(required=True) + membersId = db.StringListProperty(required=True) + + def to_JSON(self): + data = {'projectName' : self.projectName, + 'grade' : self.grade, + 'logo_url' : self.logo_url, + 'gitRepository' : self.gitRepository, + 'membersId' : self.membersId, + } + return json.dumps(data) diff --git a/models/Task.py b/models/Task.py new file mode 100644 index 0000000..20119cc --- /dev/null +++ b/models/Task.py @@ -0,0 +1,24 @@ +import json + +__author__ = 'Aran' +from google.appengine.ext import db + +class Task(db.Model): + title = db.StringProperty(required=True) + description = db.StringProperty(required=True) + dueDate = db.DateProperty(required=True) + isProject = db.BooleanProperty(required=True) + isClose = db.BooleanProperty(required=True) + isDone = db.BooleanProperty(required=True) + taskGrade = db.IntegerProperty(required=True) + + def to_JSON(self): + data = {'title' : self.title, + 'description' : self.description, + 'dueDate' : self.dueDate, + 'isProject' : self.isProject, + 'isClose' : self.membersId, + 'isDone' : self.isDone, + 'taskGrade' : self.taskGrade, + } + return json.dumps(data) diff --git a/models/User.py b/models/User.py index e2aa922..8c3e330 100644 --- a/models/User.py +++ b/models/User.py @@ -5,21 +5,25 @@ from google.appengine.ext import db class User(db.Model): username = db.StringProperty(required=True) - name = db.StringProperty(required=True) + name = db.StringProperty(required=False) email = db.StringProperty(required=True) isLecturer = db.BooleanProperty(required=True) - accsessToken = db.StringProperty(required=True) + accessToken = db.StringProperty(required=True) seToken = db.StringProperty(required=True) avatar_url = db.StringProperty(required=True) isFirstLogin = db.BooleanProperty(default=True) + campuses_id_list = db.StringListProperty(default=[]) + classes_id_list = db.StringListProperty(default=[]) def to_JSON(self): - dick = {'username' : self.username, + data = {'username' : self.username, 'name' : self.name, 'email' : self.email, 'isLecturer' : self.isLecturer, 'seToken' : self.seToken, 'avatar_url' : self.avatar_url, 'isFirstLogin' : self.isFirstLogin, + 'campuses_id_list': self.campuses_id_list, + 'classes_id_list': self.classes_id_list } - return json.dumps(dick) \ No newline at end of file + return json.dumps(data) diff --git a/templates/js/services/apiService.js b/templates/js/services/apiService.js index b794224..e240375 100644 --- a/templates/js/services/apiService.js +++ b/templates/js/services/apiService.js @@ -22,6 +22,20 @@ service.factory('apiService', ['$http', function($http) { url : url }; + return $http(req); + }, + sendValidationMail: function(token, email){ + var url = (DEBUG ? "http://localhost:8080" : "http://se-hub.appspot.com") + "/api/validation/sendmail/" + token; + payload = { + email: email + }; + + req = { + method: "POST", + url: url, + data: payload + }; + return $http(req); }