diff --git a/SE_API/API.py b/SE_API/API.py index 25e2045..4918e46 100644 --- a/SE_API/API.py +++ b/SE_API/API.py @@ -30,6 +30,7 @@ from SE_API.CampusRoutes import campus_routes from SE_API.CourseRoutes import course_routes from SE_API.ProjectRoutes import project_routes from SE_API.TaskRoutes import task_routes +from SE_API.MessageRoutes import message_routes @@ -51,6 +52,7 @@ app.register_blueprint(campus_routes) app.register_blueprint(course_routes) app.register_blueprint(project_routes) app.register_blueprint(task_routes) +app.register_blueprint(message_routes) auto = Autodoc(app) diff --git a/SE_API/CampusRoutes.py b/SE_API/CampusRoutes.py index 02d460e..2d5e4c0 100644 --- a/SE_API/CampusRoutes.py +++ b/SE_API/CampusRoutes.py @@ -76,9 +76,10 @@ def create_campus(token): print e user = get_user_by_token(token) - + arr = [] + arr.append(str(user.key().id())) try: - campus = Campus(title=payload['title'], email_ending=payload['email_ending'], master_user_id=user.key().id(), avatar_url=payload['avatar_url']) + campus = Campus(title=payload['title'], email_ending=payload['email_ending'], master_user_id=user.key().id(), avatar_url=payload['avatar_url'], membersId=arr) except Exception: return bad_request() @@ -94,6 +95,53 @@ def create_campus(token): # PUT #---------------------------------------------------------- +@campus_routes.route('/api/campuses/joinCampus//', methods=["PUT"]) +@auto.doc() +def joinCampus(token, campusId): + """ + This call will add the user (by token) to a specific campus +
+ Route Parameters
+ - seToken: 'seToken'
+ - campusId: 123456789 +
+
+ Payload
+ - None
+
+ Response +
+ 202 - Accepted +
+ 400 - Bad Request +
+ 403 - Invalid token or not a lecturer + """ + + user = get_user_by_token(token) + if user is None: + return bad_request("Wrong user Token") + + campus = Campus.get_by_id(int(campusId)) + if campus is None: + return bad_request("No such course") + + if user.key().id() in campus.membersId: + return no_content("User is already member in Project") + + campus.membersId.append(str(user.key().id())) + user.courses_id_list.append(str(campus.key().id())) + + db.put(campus) + db.put(user) + db.save + + return Response(response=campus.to_JSON(), + status=202, + mimetype="application/json") + + + #---------------------------------------------------------- # GET #---------------------------------------------------------- diff --git a/SE_API/CourseRoutes.py b/SE_API/CourseRoutes.py index 2864493..07c9101 100644 --- a/SE_API/CourseRoutes.py +++ b/SE_API/CourseRoutes.py @@ -49,7 +49,7 @@ def create_course(token): - JSON Object, Example:
{
'courseName': 'Advance Math',
- 'campusName': 'JCE',
+ 'campusId': 1234567890,
'startDate': {'year': 2015, 'month' : 4, 'day' : 3},
'endDate': {'year': 2016, 'month' : 5, 'day' : 14}
}
@@ -83,11 +83,12 @@ def create_course(token): if end_date <= start_date: return bad_request("end date cant be before (or same day) start date") - course = Course(courseName=payload['courseName'], campusName=payload['campusName'], master_id=user.key().id(), + course = Course(courseName=payload['courseName'], campusId=payload['campusId'], master_id=user.key().id(), startDate=start_date, endDate=end_date) #check if name already exists try: query = Course.all() + query.filter('campusId = ', payload['campusId']) query.filter("courseName = ", payload['courseName']) for c in query.run(limit=1): return forbidden("Course with same name already exists") @@ -113,64 +114,6 @@ def create_course(token): mimetype="application/json") - - -@course_routes.route('/api/courses/createMessage/', methods=['POST']) -@auto.doc() -def createMessage(token): - """ - This call will create a new Message in the DB -
- Route Parameters
- - seToken: 'seToken' -
-
- Payload
- - JSON Object, Example:
- {
- 'courseName': 'Advance Math',
- 'message': 'The lecture today is canceled'
- }
-
-
- Response -
- 201 - Created -
- 400 - Bad Request -
- 403 - Invalid token or not a lecturer - """ - if not request.data: - return bad_request("no data") - if not is_lecturer(token): #todo: change to lecturer id - return forbidden("Invalid token or not a lecturer!") - - user = get_user_by_token(token) - - #try to parse payload - try: - payload = json.loads(request.data) - except Exception as e: - return bad_request("here") - - try: - msg = Message(groupId=payload['groupId'], message=payload['message'], msgDate=datetime.datetime.now(), master_id=user.key().id()) - except Exception as e: - print e - return bad_request("there") - - try: - msg['isProject'] = payload['isProject'] - except Exception as e: - pass - - db.save(msg) - db.save - return created() - - - #---------------------------------------------------------- # PUT #---------------------------------------------------------- @@ -226,14 +169,14 @@ def joinCourse(token, courseId): #---------------------------------------------------------- -@course_routes.route('/api/courses/getCourseByCampusName/', methods=["GET"]) +@course_routes.route('/api/courses/getCoursesByCampus/', methods=["GET"]) @auto.doc() -def getCourseByCampusName(name): +def getCourseByCampus(campusId): """ >This Call will return an array of all courses in a given campus
Route Parameters
- - name: 'campus name' + - campusId: 1234567890

Payload
@@ -246,7 +189,7 @@ def getCourseByCampusName(name): {
'courseName': 'Advance Math',
- 'campusName': 'JCE',
+ 'campusId': 1234567890,
'startDate': '2015-14-3'
'endDate': '2015-29-6'
'taskFlag': 'False'
@@ -258,7 +201,7 @@ def getCourseByCampusName(name): """ arr = [] query = Course.all() - query.filter("campusName=", name) + query.filter("campusId = ", int(campusId)) for c in query.run(): arr.append(dict(json.loads(c.to_JSON()))) @@ -274,7 +217,7 @@ def getCourseByCampusName(name): @course_routes.route('/api/courses/getCoursesByUser//', methods=['GET']) @auto.doc() -def getCampusesByUser(token,campusId): +def getCampusesByUser(token, campusId): """ This Call will return an array of all Campuses of a certain User
@@ -319,7 +262,7 @@ def getCampusesByUser(token,campusId): arr = [] for i in user.courses_id_list: course = Course.get_by_id(int(i)) - if course.courseName == campus.title: + if course.campusId == campus.key().id(): arr.append(dict(json.loads(course.to_JSON()))) if len(arr) != 0: @@ -332,61 +275,6 @@ def getCampusesByUser(token,campusId): mimetype="application/json") -@course_routes.route('/api/courses/getMessagesByCourseName/', methods=["GET"]) -@auto.doc() -def getMessagesByCourseName(name): - """ - >This Call will return an array of all courses in a given campus -
- Route Parameters
- - name: 'campus name' -
-
- Payload
- - NONE -
-
- Response -
- 200 - JSON Example:
- - {
- 'courseName': 'Advance Math',
- 'campusName': 'JCE',
- 'startDate': '2015-14-3'
- 'endDate': '2015-29-6'
- 'taskFlag': false,
- 'id' : 1234567890
- - } -
-
- """ - arr = [] - query = Message.all() - query.filter("courseName = ", name) - - for m in query.run(): - msgDic = dict(json.loads(m.to_JSON())) - #add a key 'forSortDate' for sorting dates - msgTime = datetime.datetime(msgDic['date']['year'], msgDic['date']['month'], msgDic['date']['day'], msgDic['date']['hour'], msgDic['date']['minute']) - msgDic['forSortDate'] = msgTime - arr.append(msgDic) - - arr = sorted(arr, key=itemgetter('forSortDate'), reverse=False) - for i in arr: - del i['forSortDate'] - print arr - - if len(arr) != 0: - return Response(response=json.dumps(arr), - status=200, - mimetype="application/json") - else: - return Response(response=[], - status=200, - mimetype="application/json") - #---------------------------------------------------------- # PUT #---------------------------------------------------------- @@ -402,7 +290,7 @@ def getMessagesByCourseName(name): @course_routes.route('/api/courses/deleteCourse//', methods=['DELETE']) @auto.doc() -def deleteCourse(token,courseid): +def deleteCourse(token, courseid): """ This Call will delete a specific Course
@@ -448,64 +336,64 @@ def deleteCourse(token,courseid): return forbidden("lecturer is not owner of course") -@course_routes.route('/api/courses/deleteCoursesByCampus//', methods=['DELETE']) -@auto.doc() -def deleteCoursesByCampus(token,campusName): - """ - This Call will delete a specific campus's courses -
- Route Parameters
- - seToken: 'seToken' - - title: 'campusName' -
-
- Payload
- - NONE
-
-
- Response -
- 202 - Deleted campus -
- 204 - No Matching Campus Found -
- ....
- {
- ...
- }req
- - ]
- 400 - Bad Request -
- 403 - Invalid token or not a lecturer!
- """ - - if not is_lecturer(token): #todo: change to lecturer id - return forbidden("Invalid token or not a lecturer!") - - - user = get_user_by_token(token) - campus = get_campus_by_campusName(campusName) - if campus is None: - return bad_request("Not a campus!") - - #check user is owner of campus - if campus.master_user_id != user.key().id(): - return forbidden("lecturer is not owner of campus!") - - query = Course.all() - - try: - query.filter('campusName =', campusName) - except Exception as e: - print e - return bad_request("invalid course title attribute") - - for c in query.run(): - db.delete(c) - db.save - - return no_content() +# @course_routes.route('/api/courses/deleteCoursesByCampus//', methods=['DELETE']) +# @auto.doc() +# def deleteCoursesByCampus(token,campusName): +# """ +# This Call will delete a specific campus's courses +#
+# Route Parameters
+# - seToken: 'seToken' +# - title: 'campusName' +#
+#
+# Payload
+# - NONE
+#
+#
+# Response +#
+# 202 - Deleted campus +#
+# 204 - No Matching Campus Found +#
+# ....
+# {
+# ...
+# }req
+# +# ]
+# 400 - Bad Request +#
+# 403 - Invalid token or not a lecturer!
+# """ +# +# if not is_lecturer(token): #todo: change to lecturer id +# return forbidden("Invalid token or not a lecturer!") +# +# +# user = get_user_by_token(token) +# campus = get_campus_by_campusName(campusName) +# if campus is None: +# return bad_request("Not a campus!") +# +# #check user is owner of campus +# if campus.master_user_id != user.key().id(): +# return forbidden("lecturer is not owner of campus!") +# +# query = Course.all() +# +# try: +# query.filter('campusName =', campusName) +# except Exception as e: +# print e +# return bad_request("invalid course title attribute") +# +# for c in query.run(): +# db.delete(c) +# db.save +# +# return no_content() diff --git a/SE_API/MessageRoutes.py b/SE_API/MessageRoutes.py new file mode 100644 index 0000000..1a81eb7 --- /dev/null +++ b/SE_API/MessageRoutes.py @@ -0,0 +1,246 @@ +__author__ = 'Aran' + +from flask import Blueprint +import json +from GithubAPI.GithubAPI import GitHubAPI_Keys + +from google.appengine.ext import db +import requests +import datetime +from operator import itemgetter + + +from flask import Flask, request, render_template, redirect, abort, Response + +from flask.ext.github import GitHub +from flask.ext.cors import CORS, cross_origin +from flask.ext.autodoc import Autodoc + +# DB Models +from models.Course import Course +from models.Project import Project +from models.Message import Message + +#Validation Utils Libs +from SE_API.Validation_Utils import * +from SE_API.Respones_Utils import * + + + +message_routes = Blueprint("message_routes", __name__) +auto = Autodoc() + + + +#---------------------------------------------------------- +# POST +#---------------------------------------------------------- + + +@message_routes.route('/api/messages/create/', methods=['POST']) +@auto.doc() +def createMessage(token): + """ + This call will create a new Message in the DB +
+ Route Parameters
+ - seToken: 'seToken' +
+
+ Payload
+ - JSON Object, Example:
+ {
+ 'groupId' : 123456789,
+ 'message' : 'Class is canceled',
+ 'date' : {
+ 'year': 2015,
+ 'month': 3,
+ 'day': 14,
+ 'hour': 16,
+ 'minute': 53
+ },
+ 'isProject' : true
+ }
+
+
+ Response +
+ 201 - Created +
+ 400 - Bad Request +
+ 403 - Invalid token or not a lecturer + """ + if not request.data: + return bad_request("no data") + if not is_lecturer(token): #todo: change to lecturer id + return forbidden("Invalid token or not a lecturer!") + + user = get_user_by_token(token) + + #try to parse payload + try: + payload = json.loads(request.data) + except Exception as e: + return bad_request("here") + + try: + msg = Message(groupId=payload['groupId'], message=payload['message'], msgDate=datetime.datetime.now(), master_id=user.key().id()) + except Exception as e: + print e + return bad_request("there") + + try: + msg['isProject'] = payload['isProject'] + except Exception as e: + pass + + db.put(msg) + db.save + return created() + + + + +#---------------------------------------------------------- +# PUT +#---------------------------------------------------------- + + +#---------------------------------------------------------- +# GET +#---------------------------------------------------------- + +@message_routes.route('/api/messages/getMessagesByGroup//', methods=["GET"]) +@auto.doc() +def getMessagesByGroup(token, groupId): + """ + >This Call will return an array of all messages (sorted by date),
+ for a given group (course or project)
+
+ Route Parameters
+ - SeToken: token
+ - groupId: 1234567890 +
+
+ Payload
+ - NONE +
+
+ Response +
+ 200 - JSON Example:
+ + {
+ 'groupId' : 1234567890,
+ 'message' : 'hello all',
+ 'date' : {
+ 'year': 2015,
+ 'month': 5,
+ 'day': 5,
+ 'hour': 5,
+ 'minute': 5
+ },
+ 'id' : 1234567890,
+ 'master_id' : 1234567890,
+ 'isProject' : false
+ }
+
+
+ """ + if get_user_by_token(token) is None: + return bad_request("No such User") + + arr = [] + query = Message.all() + query.filter("groupId = ", int(groupId)) + + for m in query.run(): + msgDic = dict(json.loads(m.to_JSON())) + #add a key 'forSortDate' for sorting dates + msgTime = datetime.datetime(msgDic['date']['year'], msgDic['date']['month'], msgDic['date']['day'], msgDic['date']['hour'], msgDic['date']['minute']) + msgDic['forSortDate'] = msgTime + arr.append(msgDic) + print arr + arr = sorted(arr, key=itemgetter('forSortDate'), reverse=True) + for i in arr: + del i['forSortDate'] + print arr + + if len(arr) != 0: + return Response(response=json.dumps(arr), + status=200, + mimetype="application/json") + else: + return Response(response=[], + status=200, + mimetype="application/json") + + +#---------------------------------------------------------- +# DELETE +#---------------------------------------------------------- + +@message_routes.route('/api/messages/deleteMessage//', methods=["DELETE"]) +@auto.doc() +def deleteMessage(token, msgId): + """ + >This Call will delete a message by owner token +
+ Route Parameters
+ - SeToken: token + - msgId: 1234567890 +
+
+ Payload
+ - NONE +
+
+ Response +
+ 200 - JSON Example:
+ + {
+ 'groupId' : 1234567890,
+ 'message' : 'hello all',
+ 'date' : {
+ 'year': 2015,
+ 'month': 5,
+ 'day': 5,
+ 'hour': 5,
+ 'minute': 5
+ },
+ 'id' : 1234567890,
+ 'master_id' : 1234567890,
+ 'isProject' : false
+ }
+
+
+ """ + + user = get_user_by_token(token) + if user is None: + return bad_request("No such User") + + msg = Message.get_by_id(int(msgId)) + if msg is None: + return bad_request("No such Message") + + if msg.master_id != user.key().id(): + return forbidden("User is not the Creator of the message") + + db.delete(msg) + db.save + return no_content() + + + + + +#---------------------------------------------------------- +# DOCUMENTATION +#---------------------------------------------------------- + +@message_routes.route('/api/messages/help') +def documentation(): + return auto.html() \ No newline at end of file diff --git a/SE_API/ProjectRoutes.py b/SE_API/ProjectRoutes.py index f1848db..80a7839 100644 --- a/SE_API/ProjectRoutes.py +++ b/SE_API/ProjectRoutes.py @@ -42,7 +42,7 @@ def create_project(token): - JSON Object, Example:
{
'projectName': 'Advance Math',
- 'courseName': 'JCE',
+ 'courseId': 1234567890,
'logo_url': 'http://location.domain.com/image.jpg',
'gitRepository': 'http://location.git.com/somthing'
}
@@ -62,18 +62,14 @@ def create_project(token): payload = json.loads(request.data) except Exception as e: return bad_request("invalid JSON format") - #if not is_lecturer(token): #todo: change to lecturer id - # return forbidden("Invalid token or not a lecturer!") user = get_user_by_token(token) if user is None: return bad_request("Wrong user Token") - #todo: check legality - try: - project = Project(projectName=payload['projectName'], courseName=payload['courseName'], master_id=user.key().id(), gitRepository=payload['gitRepository'], membersId=[token]) + project = Project(projectName=payload['projectName'], courseId=payload['courseId'], master_id=user.key().id(), gitRepository=payload['gitRepository'], membersId=[token]) except Exception as e: print e return bad_request() @@ -142,14 +138,14 @@ def joinProject(token, projectId): # GET #---------------------------------------------------------- -@project_routes.route('/api/projects/getProjectsByCourseName/', methods=["GET"]) +@project_routes.route('/api/projects/getProjectsByCourse/', methods=["GET"]) @auto.doc() -def getProjectsByCourseName(name): +def getProjectsByCourse(courseId): """ >This Call will return an array of all projects in a given course
Route Parameters
- - name: 'course name' + - courseId: 1234567890

Payload
@@ -162,7 +158,7 @@ def getProjectsByCourseName(name): {
'projectName': 'Advance Math',
- 'courseName': 'JCE',
+ 'courseId': 123456789,
'grade': 98,
'logo_url': 'http://location.domain.com/image.jpg',
'gitRepository': 'http://location.git.com/somthing',
@@ -175,7 +171,7 @@ def getProjectsByCourseName(name): arr = [] query = Project.all() - query.filter("courseName = ", name) + query.filter("courseId = ", int(courseId)) for p in query.run(): arr.append(dict(json.loads(p.to_JSON()))) diff --git a/SE_API/UserRoutes.py b/SE_API/UserRoutes.py index 54f19a8..b1d350c 100644 --- a/SE_API/UserRoutes.py +++ b/SE_API/UserRoutes.py @@ -17,6 +17,7 @@ from flask.ext.autodoc import Autodoc # DB Models from models.User import User from models.Course import Course +from models.Project import Project #Validation Utils Libs from SE_API.Validation_Utils import * @@ -270,6 +271,7 @@ def getUserByToken(token): return no_content("No User Found") + @user_routes.route('/api/users/getUserById/', defaults={'token': None, 'id': None}) @user_routes.route('/api/users/getUserById//', methods=["GET"]) @auto.doc() @@ -333,18 +335,201 @@ def getUserById(token, id): +@user_routes.route('/api/users/getUsersByCampus//', methods=["GET"]) +@auto.doc() +def getUsersByCampus(token, campusId): + """ + >This Call will return all users in Campus +
+ Route Parameters
+ - seToken: 'seToken'
+ - campusId: 123456789 +
+
+ Payload
+ - NONE +
+
+ Response +
+ 200 - JSON Example:
+ + {
+ 'username': 'DarkLord',
+ 'name': 'Darth Vader',
+ 'email': 'darkLord@death.planet,
+ 'isLecturer': 'True',
+ 'seToken': 'xxxxxx-xxxxx-xxxxx-xxxxxx',
+ 'avatar_url': 'http://location.git.com/somthing'
+ 'isFirstLogin': False,
+ 'campuses_id_list': [75894378,5893482,894032],
+ 'courses_id_list': [4324,432432,4324324]
+ } +
+
+ 403 - No User Found + """ + if token is None: + return no_content("Token Is Empty, No User Found") + + user = get_user_by_token(token) + if user is None: + return bad_request("Bad User Token") + + campus = Campus.get_by_id(int(campusId)) + if campus is None: + return bad_request("No such Campus") + + arr = [] + + for u in enumerate(campus.membersId): + u = json.loads(User.get_by_id(int(u)).to_JSON()) + arr.append(dict(u)) + + if len(arr) != 0: + return Response(response=json.dumps(arr), + status=200, + mimetype="application/json") + else: + return Response(response=[], + status=200, + mimetype="application/json") + + +@user_routes.route('/api/users/getUsersByCourse//', methods=["GET"]) +@auto.doc() +def getUsersByCourse(token, courseId): + """ + >This Call will return all users in Course +
+ Route Parameters
+ - seToken: 'seToken'
+ - courseId: 123456789 +
+
+ Payload
+ - NONE +
+
+ Response +
+ 200 - JSON Example:
+ + {
+ 'username': 'DarkLord',
+ 'name': 'Darth Vader',
+ 'email': 'darkLord@death.planet,
+ 'isLecturer': 'True',
+ 'seToken': 'xxxxxx-xxxxx-xxxxx-xxxxxx',
+ 'avatar_url': 'http://location.git.com/somthing'
+ 'isFirstLogin': False,
+ 'campuses_id_list': [1243567,7583584904],
+ 'courses_id_list': [543543,54353453,543543534]
+ } +
+
+ 403 - No User Found + """ + if token is None: + return no_content("Token Is Empty, No User Found") + + user = get_user_by_token(token) + if user is None: + return bad_request("Bad User Token") + + course = Course.get_by_id(int(courseId)) + if course is None: + return bad_request("No such Course") + + arr = [] + + for u in enumerate(course.membersId): + u = json.loads(User.get_by_id(int(u)).to_JSON()) + arr.append(dict(u)) + + if len(arr) != 0: + return Response(response=json.dumps(arr), + status=200, + mimetype="application/json") + else: + return Response(response=[], + status=200, + mimetype="application/json") + + +@user_routes.route('/api/users/getUsersByProject//', methods=["GET"]) +@auto.doc() +def getUsersByCampus(token, projectId): + """ + >This Call will return all users in Project +
+ Route Parameters
+ - seToken: 'seToken'
+ - projectId: 123456789 +
+
+ Payload
+ - NONE +
+
+ Response +
+ 200 - JSON Example:
+ + {
+ 'username': 'DarkLord',
+ 'name': 'Darth Vader',
+ 'email': 'darkLord@death.planet,
+ 'isLecturer': 'True',
+ 'seToken': 'xxxxxx-xxxxx-xxxxx-xxxxxx',
+ 'avatar_url': 'http://location.git.com/somthing'
+ 'isFirstLogin': False,
+ 'campuses_id_list': [43243532532,5325325325,532532342],
+ 'courses_id_list': [53523,43432423,432432432432]
+ } +
+
+ 403 - No User Found + """ + if token is None: + return no_content("Token Is Empty, No User Found") + + user = get_user_by_token(token) + if user is None: + return bad_request("Bad User Token") + + project = Project.get_by_id(int(projectId)) + if project is None: + return bad_request("No such Project") + + arr = [] + + for u in enumerate(project.membersId): + u = json.loads(User.get_by_id(int(u)).to_JSON()) + arr.append(dict(u)) + + if len(arr) != 0: + return Response(response=json.dumps(arr), + status=200, + mimetype="application/json") + else: + return Response(response=[], + status=200, + mimetype="application/json") + #---------------------------------------------------------- # DELETE #---------------------------------------------------------- -@user_routes.route('/api/users/removeUserFromCampus//', methods=["PUT"]) +@user_routes.route('/api/users/removeUserFromCampus///', methods=["PUT"]) @auto.doc() -def removeUserFromCampus(token, campusId): +def removeUserFromCampus(token, userId, campusId): """ - >This Call will remove a Campus from a user Campus list + >This Call will remove a user from a campus
Route Parameters
- - seToken: 'seToken' + - seToken: 'seToken'
+ - userId: 0987654321,
- 'campusId': 1234567890


@@ -360,18 +545,13 @@ def removeUserFromCampus(token, campusId): 400 - Bad Request """ - if not request.data: - return bad_request() + requestingUser = get_user_by_token(token) + if requestingUser is None: + return bad_request("Bad User Token") - try: - payload = json.loads(request.data) - except Exception as e: - return bad_request() - - if not is_lecturer(token): #todo: change to lecturer id - return forbidden("Invalid token or not a lecturer!") - - user = get_user_by_token(token) + userToRemove = User.get_by_id(int(userId)) + if userToRemove is None: + return bad_request("No such user to remove") #check Campus Exists campus = Campus.get_by_id(int(campusId)) @@ -379,18 +559,20 @@ def removeUserFromCampus(token, campusId): return bad_request("No such Campus!") #check if user is owner of Campus - if user.key().id() != campus.master_user_id: - return forbidden("Lecturer is not owner of course") + if requestingUser.key().id() != campus.master_user_id: + # check if user want to delete itself + if requestingUser.key().id() != userToRemove.key().id(): + return forbidden("No permission to delete user") try: - user.campuses_id_list.remove(campusId) + userToRemove.campuses_id_list.remove(campusId) except Exception as e: - print e return bad_request("user is not listed to this campus") - db.put(user) + + db.put(userToRemove) db.save - return Response(response=user.to_JSON(), + return Response(response=userToRemove.to_JSON(), status=200, mimetype="application/json") # Real response! @@ -398,64 +580,128 @@ def removeUserFromCampus(token, campusId): -# @user_routes.route('/api/users/removeUserFromCourse//', methods=["PUT"]) -# @auto.doc() -# def removeUserFromCourse(token, courseId): -# """ -# >This Call will remove a Course from a user Campus list -#
-# Route Parameters
-# - seToken: 'seToken' -# - 'courseId': 1234567890
-#
-#
-# Payload
-# - NONE -# {
-# }
-#
-# Response -#
-# 200 - User updated -#
-# 400 - Bad Request -# """ -# -# if not request.data: -# return bad_request() -# -# try: -# payload = json.loads(request.data) -# except Exception as e: -# return bad_request() -# -# user = get_user_by_token(token) -# if user is None: -# return bad_request("No such user!") -# -# -# #check Course Exists -# course = Course.get_by_id(int(courseId)) -# if course is None: -# return bad_request("No such Course!") -# -# #check if user is owner of Campus -# if user.key().id() != course.master_id: -# return forbidden("Lecturer is not owner of course") -# -# try: -# user.campuses_id_list.remove(campusId) -# except Exception as e: -# print e -# return bad_request("user is not listed to this campus") -# -# db.put(user) -# db.save -# return Response(response=user.to_JSON(), -# status=200, -# mimetype="application/json") # Real response! -# -# + +@user_routes.route('/api/users/removeUserFromCourse///', methods=["PUT"]) +@auto.doc() +def removeUserFromCourse(token, userId, courseId): + """ + >This Call will remove a user from a course +
+ Route Parameters
+ - seToken: 'seToken'
+ - userId: 0987654321,
+ - 'courseId': 1234567890
+
+
+ Payload
+ - NONE + {
+ }
+
+ Response +
+ 200 - User updated +
+ 400 - Bad Request + """ + + requestingUser = get_user_by_token(token) + if requestingUser is None: + return bad_request("Bad User Token") + + userToRemove = User.get_by_id(int(userId)) + if userToRemove is None: + return bad_request("No such user to remove") + + #check Course Exists + course = Course.get_by_id(int(courseId)) + if course is None: + return bad_request("No such Course!") + + #check if user is owner of Course + if requestingUser.key().id() != course.master_id: + # check if user want to delete itself + if requestingUser.key().id() != userToRemove.key().id(): + return forbidden("No permission to delete user") + + try: + userToRemove.courses_id_list.remove(courseId) + course.membersId.remove(userToRemove.key().id()) + except Exception as e: + return bad_request("user is not listed to this course") + + + + db.put(userToRemove) + db.put(course) + db.save + return Response(response=userToRemove.to_JSON(), + status=200, + mimetype="application/json") # Real response! + + + + + +@user_routes.route('/api/users/removeUserFromProject///', methods=["PUT"]) +@auto.doc() +def removeUserFromProject(token, userId, projectId): + """ + >This Call will remove a user from a project +
+ Route Parameters
+ - seToken: 'seToken'
+ - userId: 0987654321,
+ - 'projectId': 1234567890
+
+
+ Payload
+ - NONE + {
+ }
+
+ Response +
+ 200 - User updated +
+ 400 - Bad Request + """ + + requestingUser = get_user_by_token(token) + if requestingUser is None: + return bad_request("Bad User Token") + + userToRemove = User.get_by_id(int(userId)) + if userToRemove is None: + return bad_request("No such user to remove") + + #check project Exists + project = Project.get_by_id(int(projectId)) + if project is None: + return bad_request("No such Project!") + + #check if user is owner of project + if requestingUser.key().id() != project.master_id: + # check if user want to delete itself + if requestingUser.key().id() != userToRemove.key().id(): + return forbidden("No permission to delete user") + + try: + userToRemove.projects_id_list.remove(projectId) + project.membersId.remove(userToRemove.key().id()) + except Exception as e: + return bad_request("user is not listed to this project") + + + + db.put(userToRemove) + db.put(project) + db.save + return Response(response=userToRemove.to_JSON(), + status=200, + mimetype="application/json") # Real response! + + diff --git a/Testing/CoursesAPI_test.py b/Testing/CoursesAPI_test.py new file mode 100644 index 0000000..dcc9a84 --- /dev/null +++ b/Testing/CoursesAPI_test.py @@ -0,0 +1,97 @@ +__author__ = 'etye' +import unittest +import requests +import json +from Testing.config import __CONFIG__ + +class UserTestPlan(unittest.TestCase): + @classmethod + def setUpClass(cls): + debug = __CONFIG__['DEBUG'] + if debug: + url = __CONFIG__['PATHS']['DEBUG'] + else: + url = __CONFIG__['PATHS']['PRODUCTION'] + cls.url_ = url + request = requests.get(url+'api/qa/init') + if 200 <= request.status_code <= 299: + print 'Initialized' + + def test_courseCreate_lecturer(self): + #url = "http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER" + url=self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['LECTURER'] + data = { + 'courseName': 'matan', + 'campusName': 'https://yt3.ggpht.com/--ZkWxybWGOM/AAAAAAAAAAI/AAAAAAAAAAA/_nAICC_kzzI/s88-c-k-no/photo.jpg', + 'projects': '@gay.lord.ultima.multi.omega', + 'startDate': {'year': 2015, 'month' : 4, 'day' : 3}, + 'endDate': {'year': 2016,'month' : 6,'day' : 6} + } + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + r = requests.post(url, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 201) + + def test_courseCreate_lecturerExsistingCourse(self): + #url = "http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER" + url=self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['LECTURER'] + data = { + 'courseName': 'matan', + 'campusName': 'https://yt3.ggpht.com/--ZkWxybWGOM/AAAAAAAAAAI/AAAAAAAAAAA/_nAICC_kzzI/s88-c-k-no/photo.jpg', + 'projects': '@gay.lord.ultima.multi.omega', + 'startDate': {'year': 2015, 'month' : 4, 'day' : 3}, + 'endDate': {'year': 2016,'month' : 6,'day' : 6} + } + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + r = requests.post(url, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 403) + + def test_courseCreate_student(self): + #url = "http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER" + url=self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['STUDENT'] + data = { + 'courseName': 'matan', + 'campusName': 'https://yt3.ggpht.com/--ZkWxybWGOM/AAAAAAAAAAI/AAAAAAAAAAA/_nAICC_kzzI/s88-c-k-no/photo.jpg', + 'projects': '@gay.lord.ultima.multi.omega', + 'startDate': {'year': 2015, 'month' : 4, 'day' : 3}, + 'endDate': {'year': 2016,'month' : 6,'day' : 6} + } + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + r = requests.post(url, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 403) + + def test_courseCreate_invalidToken(self): + #url = "http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER" + url=self.__class__.url_+'api/courses/create/invalidToken' + data = { + 'courseName': 'matan', + 'campusName': 'https://yt3.ggpht.com/--ZkWxybWGOM/AAAAAAAAAAI/AAAAAAAAAAA/_nAICC_kzzI/s88-c-k-no/photo.jpg', + 'projects': '@gay.lord.ultima.multi.omega', + 'startDate': {'year': 2015, 'month' : 4, 'day' : 3}, + 'endDate': {'year': 2016,'month' : 6,'day' : 6} + } + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + r = requests.post(url, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 403) + + def test_courseCreate_hebrewToken(self): + #url = "http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER" + url=self.__class__.url_+'api/courses/create/????' + data = { + 'courseName': 'matan', + 'campusName': 'https://yt3.ggpht.com/--ZkWxybWGOM/AAAAAAAAAAI/AAAAAAAAAAA/_nAICC_kzzI/s88-c-k-no/photo.jpg', + 'projects': '@gay.lord.ultima.multi.omega', + 'startDate': {'year': 2015, 'month' : 4, 'day' : 3}, + 'endDate': {'year': 2016,'month' : 6,'day' : 6} + } + headers = {'Content-type': 'application/json', 'Accept': 'text/plain'} + r = requests.post(url, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 404) + + #/api/courses/getCourseByCampusName/ + def test_getCourseByCampusName_EXSISTING_CAMPUS(self): + url=self.__class__.url_+'api/courses/getCourseByCampusName/'+__CONFIG__['CAMPUS_NAME']['JCE'] + r = requests.get(url) + self.assertEquals(r.status_code, 200) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/models/Campus.py b/models/Campus.py index dd910de..343fbda 100644 --- a/models/Campus.py +++ b/models/Campus.py @@ -9,12 +9,15 @@ class Campus(db.Model): avatar_url = db.StringProperty(required=True) email_ending = db.StringProperty(required=True) master_user_id = db.IntegerProperty(required=True) + membersId = db.StringListProperty(required=True, default=[]) + def to_JSON(self): data = {'title': self.title, 'email_ending': self.email_ending, 'master_user_id': self.master_user_id, 'avatar_url': self.avatar_url, + 'membersId': self.membersId, 'id' : self.key().id() } return json.dumps(data) diff --git a/models/Course.py b/models/Course.py index a96503a..57bb436 100644 --- a/models/Course.py +++ b/models/Course.py @@ -5,7 +5,7 @@ from google.appengine.ext import db class Course(db.Model): courseName = db.StringProperty(required=True) - campusName = db.StringProperty(required=True) + campusId = db.IntegerProperty(required=True) master_id = db.IntegerProperty(required=True) # projects = db.StringListProperty(required=True,default=[]) startDate = db.DateProperty(required=True) @@ -14,7 +14,7 @@ class Course(db.Model): def to_JSON(self): data = {'courseName' : self.courseName, - 'campusName' : self.campusName, + 'campusId' : self.campusId, 'master_id' : self.master_id, # 'projects' : self.projects, 'startDate' : { diff --git a/models/Project.py b/models/Project.py index 4e6cacb..042c082 100644 --- a/models/Project.py +++ b/models/Project.py @@ -5,7 +5,7 @@ from google.appengine.ext import db class Project(db.Model): projectName = db.StringProperty(required=True) - courseName = db.StringProperty(required=True) + courseId = db.IntegerProperty(required=True) master_id = db.IntegerProperty(required=True) grade = db.IntegerProperty(required=True, default=0) logo_url = db.StringProperty(required=False) @@ -14,7 +14,7 @@ class Project(db.Model): def to_JSON(self): data = {'projectName' : self.projectName, - 'courseName' : self.courseName, + 'courseId' : self.courseId, 'master_id' : self.master_id, 'grade' : self.grade, 'logo_url' : self.logo_url, diff --git a/templates/API_Doc/api_doc_index.html b/templates/API_Doc/api_doc_index.html index e1b4ae1..9a1111f 100644 --- a/templates/API_Doc/api_doc_index.html +++ b/templates/API_Doc/api_doc_index.html @@ -62,6 +62,7 @@
  • Courses Related API
  • Projects Related API
  • Tasks Related API
  • +
  • Messages Related API
  • Validation Related API
  • Miscellaneous Methods