def post(self):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     wantsNotifications = {"true": True, "false": False}.get(self.request.params['notify'].lower())
     task_json = simplejson.loads(self.request.body)
     logging.info(self.request.body)
     task = helpers.apply_json_to_model_instance(Task(),task_json)
     # ensure Guest-created tasks are unallocated
     currentUserId = self.request.params['UUID']
     cukey = db.Key.from_path('User', int(currentUserId))
     user = db.get(cukey)
     if str(user.role) == '_Guest' and task_json.has_key('projectId') == True and task_json['projectId'] != None:
       task.projectId = None
     task.put()
     guid = task.key().id_or_name()
     # Push notification email on the queue if the task has some sort of status, etc..
     if notification.should_notify(currentUserId, task, wantsNotifications):
       taskqueue.add(url='/mailer', params={'taskId': int(guid), 'currentUUID': self.request.params['UUID'], 'action': "createTask", 'name': "New Task"})
     new_url = "/tasks-server/task/%s" % guid
     task_json["id"] = guid
     self.response.set_status(201, "Task created")
     self.response.headers['Location'] = new_url
     self.response.headers['Content-Type'] = 'application/json'
     self.response.out.write(simplejson.dumps(task_json))
   else:
     helpers.report_unauthorized_access(self.response)
 def put(self, guid):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     key = db.Key.from_path('User', int(guid))
     user = db.get(key)
     if not user == None:
       user_json = simplejson.loads(self.request.body)
       # if user password hasn't been modified by GUI keep it the same as what is in the database
       if user_json['password'] == "password":
         user_json['password'] = user.password
       status = user_json.get('status')
       being_deleted = (status != None and status == 'deleted')
       if being_deleted or helpers.is_login_name_valid(user_json['loginName'], user):
         # Prevent non-Managers from changing their role
         currentUserId = self.request.params['UUID']
         cukey = db.Key.from_path('User', int(currentUserId))
         cuser = db.get(cukey)
         if str(user.role) != user_json['role'] and str(cuser.role) != "_Manager":
           user_json['role'] = str(user.role)
           helpers.report_unauthorized_access(self.response)
         user = helpers.apply_json_to_model_instance(user, user_json)
         user.put()
         if user.password != None and len(user.password) != 0:
           user_json['password'] = "******"
         self.response.headers['Content-Type'] = 'application/json'
         self.response.out.write(simplejson.dumps(user_json))
       else:
         helpers.report_invalid_login_name(self.response)
     else:
       helpers.report_missing_record(self.response)
   else:
     helpers.report_unauthorized_access(self.response)
 def post(self):
   # Create a new user
   if len(self.request.params) > 0:
     if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
       helpers.create_user(self.request, self.response, False)
     else:
       helpers.report_unauthorized_access(self.response)
   # Signup a new user
   else:
     helpers.create_user(self.request, self.response, True)
 def put(self, guid):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     key = db.Key.from_path('Comment', int(guid))
     comment = db.get(key)
     if not comment == None:
       comment_json = simplejson.loads(self.request.body)
       comment = helpers.apply_json_to_model_instance(comment, comment_json)
       comment.put()
       self.response.headers['Content-Type'] = 'application/json'
       self.response.out.write(simplejson.dumps(comment_json))
     else:
       helpers.report_missing_record(self.response)
   else:
     helpers.report_unauthorized_access(self.response)
 def post(self):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     comment_json = simplejson.loads(self.request.body)
     comment = helpers.apply_json_to_model_instance(Comment(), comment_json)
     comment.save()
     guid = comment.key().id_or_name()
     new_url = "/tasks-server/comment/%s" % guid
     comment_json["id"] = guid
     self.response.set_status(201, "Comment created")
     self.response.headers['Location'] = new_url
     self.response.headers['Content-Type'] = 'application/json'
     self.response.out.write(simplejson.dumps(comment_json))
   else:
     helpers.report_unauthorized_access(self.response)
 def post(self):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     watch_json = simplejson.loads(self.request.body)
     watch = helpers.apply_json_to_model_instance(Watch(), watch_json)
     watch.put()
     guid = watch.key().id_or_name()
     new_url = "/tasks-server/watch/%s" % guid
     watch_json["id"] = guid
     self.response.set_status(201, "Watch created")
     self.response.headers['Location'] = new_url
     self.response.headers['Content-Type'] = 'application/json'
     self.response.out.write(simplejson.dumps(watch_json))
   else:
     helpers.report_unauthorized_access(self.response)
 def post(self):
   userId = self.request.params['UUID']
   key = db.Key.from_path('User', int(userId))
   user = db.get(key)
   if user != None:
     if user.authToken == self.request.params['authToken']:
       # clear out authentication token to indicate user was logged out
       user.authToken = None
       user.put()
       self.response.set_status(200, "User logged out")
       self.response.headers['Content-Type'] = 'application/json'
       self.response.out.write(simplejson.dumps({ "message": 'Logout successful'}))
     else:
       helpers.report_unauthorized_access(self.response)
   else:
     helpers.report_missing_record(self.response)
 def put(self, guid):
   if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):
     key = db.Key.from_path('Task', int(guid))
     task = db.get(key)
     if task != None:
       # cache current values before updates
       taskName = task.name
       taskType = task.type
       taskPriority = task.priority
       taskStatus = task.developmentStatus
       taskValidation = task.validation
       taskSubmitterId = task.submitterId
       taskAssigneeId = task.assigneeId
       taskEffort = task.effort
       taskProjectId = task.projectId
       taskDescription = task.description
       task_json = simplejson.loads(self.request.body)
       wantsNotifications = {"true": True, "false": False}.get(self.request.params['notify'].lower())
       task = helpers.apply_json_to_model_instance(task, task_json)
       # ensure Guest-created tasks are unallocated
       currentUserId = self.request.params['UUID']
       cukey = db.Key.from_path('User', int(currentUserId))
       user = db.get(cukey)
       if str(user.role) == '_Guest' and task_json.has_key('projectId') == True and task_json['projectId'] != None:
         taskProjectId = task.projectId = None
       task.put()
       # Push notification email on the queue if we need to notify
       action = "deleteTask" if task.status == "deleted" else "updateTask"
       if notification.should_notify(currentUserId, task, wantsNotifications):
         taskqueue.add(url='/mailer', params={'taskId': int(guid), 'currentUUID': self.request.params['UUID'], 'action': action, 'name': taskName, 'type': taskType, 'priority': taskPriority, 'status': taskStatus, 'validation': taskValidation, 'submitterId': taskSubmitterId, 'assigneeId': taskAssigneeId, 'effort': taskEffort, 'projectId': taskProjectId, 'description': taskDescription})
       self.response.headers['Content-Type'] = 'application/json'
       self.response.out.write(simplejson.dumps(task_json))
     else:
       helpers.report_missing_record(self.response)
   else:
     helpers.report_unauthorized_access(self.response)
  def get(self):
    
    if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], self.request.params['action']):

      currentUserId = int(self.request.params['UUID'])
      users = User.all()
      projects = Project.all()
      tasks = Task.all()
      watches = Watch.all()
      comments = Comment.all()
      
      # If lastRetrievedAt is '', get full list of non-soft-deleted records (invoked at GUI startup - first time it is run or if local storage is not used)
      # else get incremental list of records updated since last refresh
      if len(self.request.params) > 0:
        try:
          lastRetrievedAt = self.request.params['lastRetrievedAt']
        except:
          lastRetrievedAt = ''
        try:
          loadDoneProjectData = self.request.params['loadDoneProjectData']
        except:
          loadDoneProjectData = 'false'
      
      if lastRetrievedAt != '':
        query = 'updatedAt >'
        timestamp = int(lastRetrievedAt)
        users.filter(query, timestamp)
        users = users.fetch(helpers.MAX_RESULTS)
        projects.filter(query, timestamp)
        projects = projects.fetch(helpers.MAX_RESULTS)
        tasks.filter(query, timestamp)
        tasks = tasks.fetch(helpers.MAX_RESULTS)
        watches.filter(query, timestamp)
        watches = watches.fetch(helpers.MAX_RESULTS)
        comments.filter(query, timestamp)
        comments = comments.fetch(helpers.MAX_RESULTS)
        
      notDoneProjects = []
      doneProjectIds = []
      tasksInNotDoneProjects = []
      tasksInDoneProjectIds = []
      watchesOnTasksInNotDoneProjects = []
      commentsOnTasksInNotDoneProjects = []
      if loadDoneProjectData == 'false':
        for project in projects:
          if project.developmentStatus == '_Done':
            doneProjectIds.append(project.key().id_or_name());
          else:
            notDoneProjects.append(project);
        for task in tasks:
          try:
            idx = doneProjectIds.index(task.projectId)
          except:
            idx = -1
          if idx == -1:
            tasksInNotDoneProjects.append(task);
          else:
            tasksInDoneProjectIds.append(task.key().id_or_name());
        for watch in watches:
          try:
            idx = tasksInDoneProjectIds.index(watch.taskId)
          except:
            idx = -1
          if idx == -1:
            watchesOnTasksInNotDoneProjects.append(watch);

        for comment in comments:
          try:
            idx = tasksInDoneProjectIds.index(comment.taskId)
          except:
            idx = -1
          if idx == -1:
            commentsOnTasksInNotDoneProjects.append(comment);
        
      users_json = helpers.build_user_list_json(helpers.extract_non_deleted_records(users), currentUserId)
      projects_json = helpers.build_project_list_json(helpers.extract_non_deleted_records(projects if loadDoneProjectData == 'true' else notDoneProjects))
      tasks_json = helpers.build_task_list_json(helpers.extract_non_deleted_records(tasks if loadDoneProjectData == 'true' else tasksInNotDoneProjects))
      watches_json = helpers.build_watch_list_json(helpers.extract_non_deleted_records(watches if loadDoneProjectData == 'true' else watchesOnTasksInNotDoneProjects))
      comments_json = helpers.build_comment_list_json(helpers.extract_non_deleted_records(comments if loadDoneProjectData == 'true' else commentsOnTasksInNotDoneProjects))
    
      records_json = {
        "result": {
         "users": users_json,
         "projects": projects_json,
         "tasks": tasks_json,
         "watches": watches_json,
         "comments": comments_json
        }
      }
    
      # Set the response content type and dump the json
      self.response.headers['Content-Type'] = 'application/json'
      self.response.out.write(simplejson.dumps(records_json))
    else:
      helpers.report_unauthorized_access(self.response)
  def get(self):

    if helpers.authorized(self.request.params['UUID'], self.request.params['authToken'], "cleanup"):
      
      now = int(time.time()*1000)
      
      # Delete soft-deleted records older than timestamp (if specified) or older than a month
      try:
        cutoff = self.request.params['cutoff']
        cutoff = int(cutoff)
      except:
        # default to a cutoff time a month ago
        cutoff = now - helpers.MONTH_MILLISECONDS
    
      users_json = helpers.build_user_list_json(helpers.purge_soft_deleted_records(User.all(), cutoff), None)
      projects_json = helpers.build_project_list_json(helpers.purge_soft_deleted_records(Project.all(), cutoff))
      tasks_json = helpers.build_task_list_json(helpers.purge_soft_deleted_records(Task.all(), cutoff))
      watches_json = helpers.build_watch_list_json(helpers.purge_soft_deleted_records(Watch.all(), cutoff))
      comments_json = helpers.build_comment_list_json(helpers.purge_soft_deleted_records(Comment.all(), cutoff))
    
      # Handle IDs referencing non-existent records:
      # * non-existent task projectId/submitterId/assigneeId should be set to null
      # * watches with non-existent taskId/watchId should be soft-deleted
      # * set updatedAt for all records being modified
      user_ids = helpers.extract_record_ids(User.all())
      project_ids = helpers.extract_record_ids(Project.all())
      tasks = Task.all()
      task_ids = helpers.extract_record_ids(tasks)
      tasks_updated = []
      for task in tasks:
        updated = False
        project_id = task.projectId
        if project_id != None and project_id != '':
          try:
            idx = project_ids.index(project_id)
          except:
            idx = -1
          if idx == -1:
            task.projectId = None
            updated = True
        submitter_id = task.submitterId
        if submitter_id != None and submitter_id != '':
          try:
            idx = user_ids.index(submitter_id)
          except:
            idx = -1
          if idx == -1:
            task.submitterId = None
            updated = True
        assignee_id = task.assigneeId
        if assignee_id != None and assignee_id != '':
          try:
            idx = user_ids.index(assignee_id)
          except:
            idx = -1
          if idx == -1:
            task.assigneeId = None
            updated = True
        if updated:
          task.updatedAt = now
          task.put()
          tasks_updated.append(task)
      tasks_updated_json = helpers.build_task_list_json(tasks_updated)
          
      watches = Watch.all()
      watches_soft_deleted = []
      for watch in watches:
        if watch.status != 'deleted':
          task_id = watch.taskId
          if task_id != None and task_id != '':
            try:
              task_idx = task_ids.index(task_id)
            except:
              task_idx = -1
          user_id = watch.userId
          if user_id != None and user_id != '':
            try:
              user_idx = user_ids.index(user_id)
            except:
              user_idx = -1
          if task_idx == -1 or user_idx == -1:
            watch.status = 'deleted'
            watch.updatedAt = now
            watch.put()
            watches_soft_deleted.append(watch)
      watches_soft_deleted_json = helpers.build_watch_list_json(watches_soft_deleted)
          
      comments = Comment.all()
      comments_soft_deleted = []
      for comment in comments:
        if comment.status != 'deleted':
          task_id = comment.taskId
          if task_id != None and task_id != '':
            try:
              task_idx = task_ids.index(task_id)
            except:
              task_idx = -1
          user_id = comment.userId
          if user_id != None and user_id != '':
            try:
              user_idx = user_ids.index(user_id)
            except:
              user_idx = -1
          if task_idx == -1 or user_idx == -1:
            comment.status = 'deleted'
            comment.updatedAt = now
            comment.put()
            comments_soft_deleted.append(comment)
      comments_soft_deleted_json = helpers.build_comment_list_json(comments_soft_deleted)
          
      # Return all affected records broken down by category
      result = {
       "cutoff": cutoff,
       "usersDeleted": users_json,
       "projectsDeleted": projects_json,
       "tasksDeleted": tasks_json,
       "watchesDeleted": watches_json,
       "comentsDeleted": comments_json,
       "tasksUpdated": tasks_updated_json,
       "watchesSoftDeleted": watches_soft_deleted_json,
       "commentsSoftDeleted": comments_soft_deleted_json
      }
      records_json = {
        "result": result
      }
  
      self.response.set_status(200, "Cleanup done")
      self.response.headers['Content-Type'] = 'application/json'
      self.response.out.write(simplejson.dumps(records_json))
    
    else:
      helpers.report_unauthorized_access(self.response)