def testConvertFieldValues_Errors(self): """We don't crash on bad requests.""" mar = mock.Mock() mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) mar.config.field_defs = [ tracker_bizobj.MakeFieldDef(2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, 0, 99, None, False, None, None, None, None, 'doc', False), ] field_values = [ api_pb2_v1.FieldValue( fieldName='Unknown', operator=api_pb2_v1.FieldValueOperator.clear), ] actual = api_pb2_v1_helpers.convert_field_values( field_values, mar, self.services) (fv_list_add, fv_list_remove, fv_list_clear, label_list_add, label_list_remove) = actual self.assertEquals([], fv_list_add) self.assertEquals([], fv_list_remove) self.assertEquals([], fv_list_clear) self.assertEquals([], label_list_add) self.assertEquals([], label_list_remove)
def testConvertFieldValues_Normal(self): """The client wants to edit a custom field.""" mar = mock.Mock() mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) mar.config.field_defs = [ tracker_bizobj.MakeFieldDef( 1, 789, 'Priority', tracker_pb2.FieldTypes.ENUM_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, 0, 99, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 3, 789, 'Nickname', tracker_pb2.FieldTypes.STR_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 4, 789, 'Verifier', tracker_pb2.FieldTypes.USER_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 5, 789, 'Deadline', tracker_pb2.FieldTypes.DATE_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef( 6, 789, 'Homepage', tracker_pb2.FieldTypes.URL_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), ] field_values = [ api_pb2_v1.FieldValue(fieldName='Priority', fieldValue='High'), api_pb2_v1.FieldValue(fieldName='EstDays', fieldValue='4'), api_pb2_v1.FieldValue(fieldName='Nickname', fieldValue='Scout'), api_pb2_v1.FieldValue( fieldName='Verifier', fieldValue='*****@*****.**'), api_pb2_v1.FieldValue(fieldName='Deadline', fieldValue='2017-12-06'), api_pb2_v1.FieldValue( fieldName='Homepage', fieldValue='http://example.com'), ] actual = api_pb2_v1_helpers.convert_field_values( field_values, mar, self.services) (fv_list_add, fv_list_remove, fv_list_clear, label_list_add, label_list_remove) = actual self.assertEquals( [tracker_bizobj.MakeFieldValue(2, 4, None, None, None, None, False), tracker_bizobj.MakeFieldValue(3, None, 'Scout', None, None, None, False), tracker_bizobj.MakeFieldValue(4, None, None, 111, None, None, False), tracker_bizobj.MakeFieldValue( 5, None, None, None, 1512518400, None, False), tracker_bizobj.MakeFieldValue( 6, None, None, None, None, 'http://example.com', False), ], fv_list_add) self.assertEquals([], fv_list_remove) self.assertEquals([], fv_list_clear) self.assertEquals(['Priority-High'], label_list_add) self.assertEquals([], label_list_remove)
def issues_insert(self, request): """Add a new issue.""" mar = self.mar_factory(request) if not mar.perms.CanUsePerm( permissions.CREATE_ISSUE, mar.auth.effective_ids, mar.project, []): raise permissions.PermissionException( 'The requester %s is not allowed to create issues for project %s.' % (mar.auth.email, mar.project_name)) owner_id = None if request.owner: try: owner_id = self._services.user.LookupUserID( mar.cnxn, request.owner.name) except user_svc.NoSuchUserException: raise endpoints.BadRequestException( 'The specified owner %s does not exist.' % request.owner.name) cc_ids = [] if request.cc: cc_ids = self._services.user.LookupUserIDs( mar.cnxn, [ap.name for ap in request.cc], autocreate=True).values() comp_ids = api_pb2_v1_helpers.convert_component_ids( mar.config, request.components) fields_add, _, _, fields_labels, _ = ( api_pb2_v1_helpers.convert_field_values( request.fieldValues, mar, self._services)) field_helpers.ValidateCustomFields( mar, self._services, fields_add, mar.config, mar.errors) if mar.errors.AnyErrors(): raise endpoints.BadRequestException( 'Invalid field values: %s' % mar.errors.custom_fields) local_id = self._services.issue.CreateIssue( mar.cnxn, self._services, mar.project_id, request.summary, request.status, owner_id, cc_ids, request.labels + fields_labels, fields_add, comp_ids, mar.auth.user_id, request.description, blocked_on=api_pb2_v1_helpers.convert_issueref_pbs( request.blockedOn, mar, self._services), blocking=api_pb2_v1_helpers.convert_issueref_pbs( request.blocking, mar, self._services)) new_issue = self._services.issue.GetIssueByLocalID( mar.cnxn, mar.project_id, local_id) self._services.issue_star.SetStar( mar.cnxn, self._services, mar.config, new_issue.issue_id, mar.auth.user_id, True) if request.sendEmail: notify.PrepareAndSendIssueChangeNotification( new_issue.issue_id, framework_helpers.GetHostPort(), new_issue.reporter_id, 0) return api_pb2_v1_helpers.convert_issue( api_pb2_v1.IssuesGetInsertResponse, new_issue, mar, self._services)
def testConvertFieldValues_ClearAndRemove(self): """The client wants to clear and remove some custom fields.""" mar = mock.Mock() mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) mar.config.field_defs = [ tracker_bizobj.MakeFieldDef(1, 789, 'Priority', tracker_pb2.FieldTypes.ENUM_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef(11, 789, 'OS', tracker_pb2.FieldTypes.ENUM_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef(2, 789, 'EstDays', tracker_pb2.FieldTypes.INT_TYPE, None, None, False, False, False, 0, 99, None, False, None, None, None, None, 'doc', False), tracker_bizobj.MakeFieldDef(3, 789, 'Nickname', tracker_pb2.FieldTypes.STR_TYPE, None, None, False, False, False, None, None, None, False, None, None, None, None, 'doc', False), ] field_values = [ api_pb2_v1.FieldValue( fieldName='Priority', fieldValue='High', operator=api_pb2_v1.FieldValueOperator.remove), api_pb2_v1.FieldValue( fieldName='OS', operator=api_pb2_v1.FieldValueOperator.clear), api_pb2_v1.FieldValue( fieldName='EstDays', operator=api_pb2_v1.FieldValueOperator.clear), api_pb2_v1.FieldValue( fieldName='Nickname', fieldValue='Scout', operator=api_pb2_v1.FieldValueOperator.remove), ] actual = api_pb2_v1_helpers.convert_field_values( field_values, mar, self.services) (fv_list_add, fv_list_remove, fv_list_clear, label_list_add, label_list_remove) = actual self.assertEquals([], fv_list_add) self.assertEquals([ tracker_bizobj.MakeFieldValue(3, None, 'Scout', None, None, None, False) ], fv_list_remove) self.assertEquals([11, 2], fv_list_clear) self.assertEquals([], label_list_add) self.assertEquals(['Priority-High'], label_list_remove)
def testConvertFieldValues_Empty(self): """The client's request might not have any field edits.""" mar = mock.Mock() mar.config = tracker_bizobj.MakeDefaultProjectIssueConfig(789) field_values = [] actual = api_pb2_v1_helpers.convert_field_values( field_values, mar, self.services) (fv_list_add, fv_list_remove, fv_list_clear, label_list_add, label_list_remove) = actual self.assertEquals([], fv_list_add) self.assertEquals([], fv_list_remove) self.assertEquals([], fv_list_clear) self.assertEquals([], label_list_add) self.assertEquals([], label_list_remove)
def issues_comments_insert(self, request): """Add a comment.""" mar = self.mar_factory(request) issue = self._services.issue.GetIssueByLocalID( mar.cnxn, mar.project_id, request.issueId) old_owner_id = tracker_bizobj.GetOwnerId(issue) if not permissions.CanCommentIssue( mar.auth.effective_ids, mar.perms, mar.project, issue, mar.granted_perms): raise permissions.PermissionException( 'User is not allowed to comment this issue (%s, %d)' % (request.projectId, request.issueId)) updates_dict = {} if request.updates: if request.updates.moveToProject: move_to = request.updates.moveToProject.lower() move_to_project = issuedetail.CheckMoveIssueRequest( self._services, mar, issue, True, move_to, mar.errors) if mar.errors.AnyErrors(): raise endpoints.BadRequestException(mar.errors.move_to) updates_dict['move_to_project'] = move_to_project updates_dict['summary'] = request.updates.summary updates_dict['status'] = request.updates.status if request.updates.owner: if request.updates.owner == framework_constants.NO_USER_NAME: updates_dict['owner'] = framework_constants.NO_USER_SPECIFIED else: updates_dict['owner'] = self._services.user.LookupUserID( mar.cnxn, request.updates.owner) updates_dict['cc_add'], updates_dict['cc_remove'] = ( api_pb2_v1_helpers.split_remove_add(request.updates.cc)) updates_dict['cc_add'] = self._services.user.LookupUserIDs( mar.cnxn, updates_dict['cc_add'], autocreate=True).values() updates_dict['cc_remove'] = self._services.user.LookupUserIDs( mar.cnxn, updates_dict['cc_remove']).values() updates_dict['labels_add'], updates_dict['labels_remove'] = ( api_pb2_v1_helpers.split_remove_add(request.updates.labels)) blocked_on_add_strs, blocked_on_remove_strs = ( api_pb2_v1_helpers.split_remove_add(request.updates.blockedOn)) updates_dict['blocked_on_add'] = api_pb2_v1_helpers.issue_global_ids( blocked_on_add_strs, issue.project_id, mar, self._services) updates_dict['blocked_on_remove'] = api_pb2_v1_helpers.issue_global_ids( blocked_on_remove_strs, issue.project_id, mar, self._services) blocking_add_strs, blocking_remove_strs = ( api_pb2_v1_helpers.split_remove_add(request.updates.blocking)) updates_dict['blocking_add'] = api_pb2_v1_helpers.issue_global_ids( blocking_add_strs, issue.project_id, mar, self._services) updates_dict['blocking_remove'] = api_pb2_v1_helpers.issue_global_ids( blocking_remove_strs, issue.project_id, mar, self._services) components_add_strs, components_remove_strs = ( api_pb2_v1_helpers.split_remove_add(request.updates.components)) updates_dict['components_add'] = ( api_pb2_v1_helpers.convert_component_ids( mar.config, components_add_strs)) updates_dict['components_remove'] = ( api_pb2_v1_helpers.convert_component_ids( mar.config, components_remove_strs)) if request.updates.mergedInto: merge_project_name, merge_local_id = tracker_bizobj.ParseIssueRef( request.updates.mergedInto) merge_into_project = self._services.project.GetProjectByName( mar.cnxn, merge_project_name or issue.project_name) merge_into_issue = self._services.issue.GetIssueByLocalID( mar.cnxn, merge_into_project.project_id, merge_local_id) merge_allowed = tracker_helpers.IsMergeAllowed( merge_into_issue, mar, self._services) if not merge_allowed: raise permissions.PermissionException( 'User is not allowed to merge into issue %s:%s' % (merge_into_issue.project_name, merge_into_issue.local_id)) updates_dict['merged_into'] = merge_into_issue.issue_id (updates_dict['field_vals_add'], updates_dict['field_vals_remove'], updates_dict['fields_clear'], updates_dict['fields_labels_add'], updates_dict['fields_labels_remove']) = ( api_pb2_v1_helpers.convert_field_values( request.updates.fieldValues, mar, self._services)) field_helpers.ValidateCustomFields( mar, self._services, (updates_dict.get('field_vals_add', []) + updates_dict.get('field_vals_remove', [])), mar.config, mar.errors) if mar.errors.AnyErrors(): raise endpoints.BadRequestException( 'Invalid field values: %s' % mar.errors.custom_fields) _, comment = self._services.issue.DeltaUpdateIssue( cnxn=mar.cnxn, services=self._services, reporter_id=mar.auth.user_id, project_id=mar.project_id, config=mar.config, issue=issue, status=updates_dict.get('status'), owner_id=updates_dict.get('owner'), cc_add=updates_dict.get('cc_add', []), cc_remove=updates_dict.get('cc_remove', []), comp_ids_add=updates_dict.get('components_add', []), comp_ids_remove=updates_dict.get('components_remove', []), labels_add=(updates_dict.get('labels_add', []) + updates_dict.get('fields_labels_add', [])), labels_remove=(updates_dict.get('labels_remove', []) + updates_dict.get('fields_labels_remove', [])), field_vals_add=updates_dict.get('field_vals_add', []), field_vals_remove=updates_dict.get('field_vals_remove', []), fields_clear=updates_dict.get('fields_clear', []), blocked_on_add=updates_dict.get('blocked_on_add', []), blocked_on_remove=updates_dict.get('blocked_on_remove', []), blocking_add=updates_dict.get('blocking_add', []), blocking_remove=updates_dict.get('blocking_remove', []), merged_into=updates_dict.get('merged_into'), index_now=False, comment=request.content, summary=updates_dict.get('summary'), ) move_comment = None if 'move_to_project' in updates_dict: move_to_project = updates_dict['move_to_project'] old_text_ref = 'issue %s:%s' % (issue.project_name, issue.local_id) tracker_fulltext.UnindexIssues([issue.issue_id]) moved_back_iids = self._services.issue.MoveIssues( mar.cnxn, move_to_project, [issue], self._services.user) new_text_ref = 'issue %s:%s' % (issue.project_name, issue.local_id) if issue.issue_id in moved_back_iids: content = 'Moved %s back to %s again.' % (old_text_ref, new_text_ref) else: content = 'Moved %s to now be %s.' % (old_text_ref, new_text_ref) move_comment = self._services.issue.CreateIssueComment( mar.cnxn, move_to_project.project_id, issue.local_id, mar.auth.user_id, content, amendments=[ tracker_bizobj.MakeProjectAmendment(move_to_project.project_name)]) if 'merged_into' in updates_dict: new_starrers = tracker_helpers.GetNewIssueStarrers( mar.cnxn, self._services, issue.issue_id, merge_into_issue.issue_id) tracker_helpers.AddIssueStarrers( mar.cnxn, self._services, mar, merge_into_issue.issue_id, merge_into_project, new_starrers) _merge_comment = tracker_helpers.MergeCCsAndAddComment( self._services, mar, issue, merge_into_project, merge_into_issue) merge_into_issue_cmnts = self._services.issue.GetCommentsForIssue( mar.cnxn, merge_into_issue.issue_id) notify.PrepareAndSendIssueChangeNotification( merge_into_issue.issue_id, framework_helpers.GetHostPort(), mar.auth.user_id, len(merge_into_issue_cmnts) - 1, send_email=True) tracker_fulltext.IndexIssues( mar.cnxn, [issue], self._services.user, self._services.issue, self._services.config) comment = comment or move_comment if comment is None: return api_pb2_v1.IssuesCommentsInsertResponse() cmnts = self._services.issue.GetCommentsForIssue(mar.cnxn, issue.issue_id) seq = len(cmnts) - 1 if request.sendEmail: notify.PrepareAndSendIssueChangeNotification( issue.issue_id, framework_helpers.GetHostPort(), comment.user_id, seq, send_email=True, old_owner_id=old_owner_id) can_delete = permissions.CanDelete( mar.auth.user_id, mar.auth.effective_ids, mar.perms, comment.deleted_by, comment.user_id, mar.project, permissions.GetRestrictions(issue), granted_perms=mar.granted_perms) return api_pb2_v1.IssuesCommentsInsertResponse( id=seq, kind='monorail#issueComment', author=api_pb2_v1_helpers.convert_person( comment.user_id, mar.cnxn, self._services), content=comment.content, published=datetime.datetime.fromtimestamp(comment.timestamp), updates=api_pb2_v1_helpers.convert_amendments( issue, comment.amendments, mar, self._services), canDelete=can_delete)