From 695d052cf0ffa5a6cea20a60f48b97d47d5716a0 Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Wed, 24 Jun 2015 21:54:02 +0300 Subject: [PATCH 01/10] change in function name --- SE_API/ProjectRoutes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SE_API/ProjectRoutes.py b/SE_API/ProjectRoutes.py index f1848db..80d1d02 100644 --- a/SE_API/ProjectRoutes.py +++ b/SE_API/ProjectRoutes.py @@ -142,9 +142,9 @@ 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(name): """ >This Call will return an array of all projects in a given course
From 18ad25f18d62c0228bcaf57438dfb73f2043d0cc Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Wed, 24 Jun 2015 21:57:31 +0300 Subject: [PATCH 02/10] MERGE WARNING!! deleted CourseAPI_test from my rep. i think this file doesnt exist in @etyemy rep aswell --- Testing/CoursesAPI_test.py | 94 ++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 50 deletions(-) diff --git a/Testing/CoursesAPI_test.py b/Testing/CoursesAPI_test.py index dcc9a84..f4c37d5 100644 --- a/Testing/CoursesAPI_test.py +++ b/Testing/CoursesAPI_test.py @@ -3,8 +3,7 @@ import unittest import requests import json from Testing.config import __CONFIG__ - -class UserTestPlan(unittest.TestCase): +class CoursesTestPlan(unittest.TestCase): @classmethod def setUpClass(cls): debug = __CONFIG__['DEBUG'] @@ -17,80 +16,75 @@ class UserTestPlan(unittest.TestCase): 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'] + def test_coursesCreate_Lecturer(self): + headers = {'content-type': 'application/json'} + url = 'http://se-hub.appspot.com/api/courses/create/_QA_TOKEN_TEST_LECTURER' + params = {'seToken': 'seToken' } data = { - 'courseName': 'matan', + 'courseName': 'QA COURSE', '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', + #r = requests.post(self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['STUDENT'],data=payload) + r = requests.post(url, params=params, data=json.dumps(data), headers=headers) + ''' + payload = { + 'courseName': 'QA COURSE', '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) + ''' + # r = requests.post(self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['LECTURER'],data=payload) + #r = requests.post('http://localhost:8080/api/courses/create/_QA_TOKEN_TEST_LECTURER',data=payload) + #self.assertEquals(r.status_code, 201) + + def test_coursesCreate_InvalidToken(self): + headers = {'content-type': 'application/json'} + url = self.__class__.url_+'api/courses/create/invalidToken' + data = { + 'courseName': 'QA COURSE', + '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} + } + params = {'seToken': 'seToken' } + r = requests.post(url, params=params, 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', + ''' + payload = {'courseName': 'Advance Math', 'campusName': 'JCE', 'startDate':'2015-14-3','endDate': '2015-29-6','taskFlag': 'False'} + payload = { + 'courseName': 'QA COURSE', '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' + r = requests.post(self.__class__.url_+'api/courses/create/invalidToken',data=payload) + ''' + def test_coursesCreate_Student(self): + headers = {'content-type': 'application/json'} + url = self.__class__.url_+'api/courses/create/_QA_TOKEN_TEST_STUDENT' + params = {'seToken': 'seToken' } data = { - 'courseName': 'matan', + 'courseName': 'QA COURSE', '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) + #r = requests.post(self.__class__.url_+'api/courses/create/'+__CONFIG__['TOKENS']['STUDENT'],data=payload) + r = requests.post(url, params=params, data=json.dumps(data), headers=headers) + self.assertEquals(r.status_code, 403, 'message: ' + r.json()['message']) - #/api/courses/getCourseByCampusName/ - def test_getCourseByCampusName_EXSISTING_CAMPUS(self): - url=self.__class__.url_+'api/courses/getCourseByCampusName/'+__CONFIG__['CAMPUS_NAME']['JCE'] - r = requests.get(url) + def test_getCourseByCampusName(self): + r = requests.get(self.__class__.url_+'api/courses/getCourseByCampusName/'+__CONFIG__['TOKENS']['CAMPUS_NAME']) self.assertEquals(r.status_code, 200) if __name__ == '__main__': From e07deaddb2a3f4179408aef8cd82206b073b263b Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 15:47:39 +0300 Subject: [PATCH 03/10] removed messages from course --- SE_API/CourseRoutes.py | 115 +---------------------------------------- 1 file changed, 1 insertion(+), 114 deletions(-) diff --git a/SE_API/CourseRoutes.py b/SE_API/CourseRoutes.py index 7075f36..578b36c 100644 --- a/SE_API/CourseRoutes.py +++ b/SE_API/CourseRoutes.py @@ -113,64 +113,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 #---------------------------------------------------------- @@ -274,7 +216,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
@@ -332,61 +274,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 #---------------------------------------------------------- From 664fcedca019b08c2287ed7013910ba5c1c1d19f Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 15:48:39 +0300 Subject: [PATCH 04/10] added Message routes. create, get and delete function are available. doc should be updated --- SE_API/API.py | 2 + SE_API/MessageRoutes.py | 246 +++++++++++++++++++++++++++ templates/API_Doc/api_doc_index.html | 1 + 3 files changed, 249 insertions(+) create mode 100644 SE_API/MessageRoutes.py diff --git a/SE_API/API.py b/SE_API/API.py index 136e6b0..327d7ed 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/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/templates/API_Doc/api_doc_index.html b/templates/API_Doc/api_doc_index.html index ff55e84..c69ffb2 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
  • From 1574b7e19e072f36ffc5106f53ce5bf791120817 Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 16:48:01 +0300 Subject: [PATCH 05/10] IMPORTANT: alot of function name changes and new Doc --- SE_API/CourseRoutes.py | 134 ++++++++++++++++++++-------------------- SE_API/ProjectRoutes.py | 18 +++--- models/Course.py | 4 +- models/Project.py | 4 +- 4 files changed, 78 insertions(+), 82 deletions(-) diff --git a/SE_API/CourseRoutes.py b/SE_API/CourseRoutes.py index 578b36c..e4e1c8c 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,7 +83,7 @@ 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: @@ -168,14 +168,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
    @@ -188,7 +188,7 @@ def getCourseByCampusName(name): {
    'courseName': 'Advance Math',
    - 'campusName': 'JCE',
    + 'campusId': 1234567890,
    'startDate': '2015-14-3'
    'endDate': '2015-29-6'
    'taskFlag': 'False'
    @@ -200,7 +200,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()))) @@ -261,7 +261,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: @@ -289,7 +289,7 @@ def getCampusesByUser(token, campusId): @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
    @@ -335,64 +335,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/ProjectRoutes.py b/SE_API/ProjectRoutes.py index 80d1d02..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/getProjectsByCourse/', methods=["GET"]) +@project_routes.route('/api/projects/getProjectsByCourse/', methods=["GET"]) @auto.doc() -def getProjectsByCourse(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 getProjectsByCourse(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 getProjectsByCourse(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/models/Course.py b/models/Course.py index a96503a..444ed04 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.campusName, '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, From 93078f4f1818dd7eadf3c2640bdb0cfd83285863 Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 17:16:36 +0300 Subject: [PATCH 06/10] fix #46 - added delete user from project, course, campus --- SE_API/UserRoutes.py | 221 +++++++++++++++++++++++++++---------------- 1 file changed, 142 insertions(+), 79 deletions(-) diff --git a/SE_API/UserRoutes.py b/SE_API/UserRoutes.py index a448ae6..4a7f35e 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 * @@ -277,14 +278,15 @@ def getUserByToken(token): # 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


    @@ -300,18 +302,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)) @@ -319,18 +316,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! @@ -338,64 +337,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 removeUserFromCourse(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! + + From 6452dbd66a7d9294a1ec85fbef1f596ffbfe5fed Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 17:30:22 +0300 Subject: [PATCH 07/10] fix #79 --- SE_API/CourseRoutes.py | 1 + models/Course.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/SE_API/CourseRoutes.py b/SE_API/CourseRoutes.py index 1585d28..07c9101 100644 --- a/SE_API/CourseRoutes.py +++ b/SE_API/CourseRoutes.py @@ -88,6 +88,7 @@ def create_course(token): #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") diff --git a/models/Course.py b/models/Course.py index 444ed04..57bb436 100644 --- a/models/Course.py +++ b/models/Course.py @@ -14,7 +14,7 @@ class Course(db.Model): def to_JSON(self): data = {'courseName' : self.courseName, - 'campusId' : self.campusName, + 'campusId' : self.campusId, 'master_id' : self.master_id, # 'projects' : self.projects, 'startDate' : { From f9190f73d2914979a65547dcb5278aff827352c2 Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 17:43:08 +0300 Subject: [PATCH 08/10] function name fix --- SE_API/UserRoutes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SE_API/UserRoutes.py b/SE_API/UserRoutes.py index 57a107e..8efb16d 100644 --- a/SE_API/UserRoutes.py +++ b/SE_API/UserRoutes.py @@ -462,7 +462,7 @@ def removeUserFromCourse(token, userId, courseId): @user_routes.route('/api/users/removeUserFromProject///', methods=["PUT"]) @auto.doc() -def removeUserFromCourse(token, userId, projectId): +def removeUserFromProject(token, userId, projectId): """ >This Call will remove a user from a project
    From 9d323c442273c351f0677802de646896a3342743 Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 17:53:37 +0300 Subject: [PATCH 09/10] added join campus function --- SE_API/CampusRoutes.py | 52 ++++++++++++++++++++++++++++++++++++++++-- models/Campus.py | 3 +++ 2 files changed, 53 insertions(+), 2 deletions(-) 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/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) From b5ba1fbbb8c759948b6f07b9d626918f97dec16c Mon Sep 17 00:00:00 2001 From: aranzaiger Date: Sun, 28 Jun 2015 18:08:05 +0300 Subject: [PATCH 10/10] added getUsersByCampus/Course/Project functions --- SE_API/UserRoutes.py | 183 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 183 insertions(+) diff --git a/SE_API/UserRoutes.py b/SE_API/UserRoutes.py index 8efb16d..b1d350c 100644 --- a/SE_API/UserRoutes.py +++ b/SE_API/UserRoutes.py @@ -271,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() @@ -334,6 +335,188 @@ 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 #----------------------------------------------------------