AssigneeChanged event
Fired when a change's assignee has been changed or removed: type: "assignee-changed" change: The updated change changer: The user that issued the assignment oldAssignee: Assignee before it was changed. eventCreatedOn: Timestamp describing when this event was created. Change-Id: I5bf1f3f71b84afda82ecb1058a9cbf04185474f3
This commit is contained in:
parent
0e907f9812
commit
27b133bea8
@ -1,5 +1,4 @@
|
||||
= gerrit stream-events
|
||||
|
||||
== NAME
|
||||
gerrit stream-events - Monitor events occurring in real time
|
||||
|
||||
@ -59,6 +58,21 @@ this JSON stream should deal with that appropriately.
|
||||
|
||||
[[events]]
|
||||
== EVENTS
|
||||
=== Assignee Changed
|
||||
|
||||
Sent when the assignee of a change has been modified.
|
||||
|
||||
type:: "assignee-changed"
|
||||
|
||||
change:: link:json.html#change[change attribute]
|
||||
|
||||
changer:: link:json.html#account[account attribute]
|
||||
|
||||
oldAssignee:: Assignee before it was changed.
|
||||
|
||||
eventCreatedOn:: Time in seconds since the UNIX epoch when this event was
|
||||
created.
|
||||
|
||||
=== Change Abandoned
|
||||
|
||||
Sent when a change has been abandoned.
|
||||
|
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.extensions.events;
|
||||
|
||||
import com.google.gerrit.common.Nullable;
|
||||
import com.google.gerrit.extensions.annotations.ExtensionPoint;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
|
||||
/** Notified whenever a change assignee is changed. */
|
||||
@ExtensionPoint
|
||||
public interface AssigneeChangedListener {
|
||||
interface Event extends ChangeEvent {
|
||||
@Nullable AccountInfo getOldAssignee();
|
||||
}
|
||||
|
||||
void onAssigneeChanged(Event event);
|
||||
}
|
@ -30,8 +30,10 @@ import com.google.gerrit.server.account.AccountInfoCacheFactory;
|
||||
import com.google.gerrit.server.account.AccountJson;
|
||||
import com.google.gerrit.server.change.DeleteAssignee.Input;
|
||||
import com.google.gerrit.server.config.AnonymousCowardName;
|
||||
import com.google.gerrit.server.extensions.events.AssigneeChanged;
|
||||
import com.google.gerrit.server.git.BatchUpdate;
|
||||
import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
|
||||
import com.google.gerrit.server.git.BatchUpdate.Context;
|
||||
import com.google.gerrit.server.git.UpdateException;
|
||||
import com.google.gerrit.server.notedb.ChangeUpdate;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
@ -48,6 +50,7 @@ public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
|
||||
private final ChangeMessagesUtil cmUtil;
|
||||
private final Provider<ReviewDb> db;
|
||||
private final AccountInfoCacheFactory.Factory accountInfos;
|
||||
private final AssigneeChanged assigneeChanged;
|
||||
private final String anonymousCowardName;
|
||||
|
||||
@Inject
|
||||
@ -55,11 +58,13 @@ public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
|
||||
ChangeMessagesUtil cmUtil,
|
||||
Provider<ReviewDb> db,
|
||||
AccountInfoCacheFactory.Factory accountInfosFactory,
|
||||
AssigneeChanged assigneeChanged,
|
||||
@AnonymousCowardName String anonymousCowardName) {
|
||||
this.batchUpdateFactory = batchUpdateFactory;
|
||||
this.cmUtil = cmUtil;
|
||||
this.db = db;
|
||||
this.accountInfos = accountInfosFactory;
|
||||
this.assigneeChanged = assigneeChanged;
|
||||
this.anonymousCowardName = anonymousCowardName;
|
||||
}
|
||||
|
||||
@ -80,6 +85,7 @@ public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
|
||||
}
|
||||
|
||||
private class Op extends BatchUpdate.Op {
|
||||
private Change change;
|
||||
private Account deletedAssignee;
|
||||
|
||||
@Override
|
||||
@ -88,19 +94,18 @@ public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
|
||||
if (!ctx.getControl().canEditAssignee()) {
|
||||
throw new AuthException("Delete Assignee not permitted");
|
||||
}
|
||||
Change change = ctx.getChange();
|
||||
change = ctx.getChange();
|
||||
ChangeUpdate update = ctx.getUpdate(change.currentPatchSetId());
|
||||
Account.Id currentAssigneeId = change.getAssignee();
|
||||
if (currentAssigneeId == null) {
|
||||
return false;
|
||||
}
|
||||
Account account = accountInfos.create().get(currentAssigneeId);
|
||||
deletedAssignee = accountInfos.create().get(currentAssigneeId);
|
||||
// noteDb
|
||||
update.removeAssignee();
|
||||
// reviewDb
|
||||
change.setAssignee(null);
|
||||
addMessage(ctx, update, account);
|
||||
deletedAssignee = account;
|
||||
addMessage(ctx, update, deletedAssignee);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -120,5 +125,10 @@ public class DeleteAssignee implements RestModifyView<ChangeResource, Input> {
|
||||
"Assignee deleted: " + deleted.getName(anonymousCowardName));
|
||||
cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postUpdate(Context ctx) throws OrmException {
|
||||
assigneeChanged.fire(change, ctx.getAccount(), deletedAssignee, ctx.getWhen());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,9 @@ import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.account.AccountInfoCacheFactory;
|
||||
import com.google.gerrit.server.account.AccountsCollection;
|
||||
import com.google.gerrit.server.config.AnonymousCowardName;
|
||||
import com.google.gerrit.server.extensions.events.AssigneeChanged;
|
||||
import com.google.gerrit.server.git.BatchUpdate;
|
||||
import com.google.gerrit.server.git.BatchUpdate.Context;
|
||||
import com.google.gerrit.server.notedb.ChangeUpdate;
|
||||
import com.google.gerrit.server.validators.AssigneeValidationListener;
|
||||
import com.google.gerrit.server.validators.ValidationException;
|
||||
@ -49,20 +51,25 @@ public class SetAssigneeOp extends BatchUpdate.Op {
|
||||
private final DynamicSet<AssigneeValidationListener> validationListeners;
|
||||
private final AssigneeInput input;
|
||||
private final String anonymousCowardName;
|
||||
private final AssigneeChanged assigneeChanged;
|
||||
|
||||
private Change change;
|
||||
private Account newAssignee;
|
||||
private Account oldAssignee;
|
||||
|
||||
@AssistedInject
|
||||
SetAssigneeOp(AccountsCollection accounts,
|
||||
ChangeMessagesUtil cmUtil,
|
||||
AccountInfoCacheFactory.Factory accountInfosFactory,
|
||||
DynamicSet<AssigneeValidationListener> validationListeners,
|
||||
AssigneeChanged assigneeChanged,
|
||||
@AnonymousCowardName String anonymousCowardName,
|
||||
@Assisted AssigneeInput input) {
|
||||
this.accounts = accounts;
|
||||
this.cmUtil = cmUtil;
|
||||
this.accountInfosFactory = accountInfosFactory;
|
||||
this.validationListeners = validationListeners;
|
||||
this.assigneeChanged = assigneeChanged;
|
||||
this.anonymousCowardName = anonymousCowardName;
|
||||
this.input = input;
|
||||
}
|
||||
@ -73,17 +80,17 @@ public class SetAssigneeOp extends BatchUpdate.Op {
|
||||
if (!ctx.getControl().canEditAssignee()) {
|
||||
throw new AuthException("Changing Assignee not permitted");
|
||||
}
|
||||
Change change = ctx.getChange();
|
||||
change = ctx.getChange();
|
||||
ChangeUpdate update = ctx.getUpdate(change.currentPatchSetId());
|
||||
Optional<Account.Id> oldAssigneeId =
|
||||
Optional.fromNullable(ctx.getChange().getAssignee());
|
||||
Optional.fromNullable(change.getAssignee());
|
||||
if (input.assignee == null) {
|
||||
if (oldAssigneeId.isPresent()) {
|
||||
throw new BadRequestException("Cannot set Assignee to empty");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Account oldAssignee = null;
|
||||
oldAssignee = null;
|
||||
if (oldAssigneeId.isPresent()) {
|
||||
oldAssignee = accountInfosFactory.create().get(oldAssigneeId.get());
|
||||
}
|
||||
@ -100,7 +107,7 @@ public class SetAssigneeOp extends BatchUpdate.Op {
|
||||
if (!ctx.getControl().forUser(newAssigneeUser).isRefVisible()) {
|
||||
throw new AuthException(String.format(
|
||||
"Change %s is not visible to %s.",
|
||||
ctx.getChange().getChangeId(),
|
||||
change.getChangeId(),
|
||||
newAssigneeUser.getUserName()));
|
||||
}
|
||||
try {
|
||||
@ -134,14 +141,19 @@ public class SetAssigneeOp extends BatchUpdate.Op {
|
||||
}
|
||||
ChangeMessage cmsg = new ChangeMessage(
|
||||
new ChangeMessage.Key(
|
||||
ctx.getChange().getId(),
|
||||
change.getId(),
|
||||
ChangeUtil.messageUUID(ctx.getDb())),
|
||||
ctx.getAccountId(), ctx.getWhen(),
|
||||
ctx.getChange().currentPatchSetId());
|
||||
change.currentPatchSetId());
|
||||
cmsg.setMessage(msg.toString());
|
||||
cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postUpdate(Context ctx) throws OrmException {
|
||||
assigneeChanged.fire(change, ctx.getAccount(), oldAssignee, ctx.getWhen());
|
||||
}
|
||||
|
||||
public Account getNewAssignee() {
|
||||
return newAssignee;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ import com.google.gerrit.extensions.config.DownloadScheme;
|
||||
import com.google.gerrit.extensions.config.ExternalIncludedIn;
|
||||
import com.google.gerrit.extensions.config.FactoryModule;
|
||||
import com.google.gerrit.extensions.events.AgreementSignupListener;
|
||||
import com.google.gerrit.extensions.events.AssigneeChangedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeAbandonedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeIndexedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeMergedListener;
|
||||
@ -306,6 +307,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
DynamicSet.setOf(binder(), CacheRemovalListener.class);
|
||||
DynamicMap.mapOf(binder(), CapabilityDefinition.class);
|
||||
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
|
||||
DynamicSet.setOf(binder(), AssigneeChangedListener.class);
|
||||
DynamicSet.setOf(binder(), ChangeAbandonedListener.class);
|
||||
DynamicSet.setOf(binder(), CommentAddedListener.class);
|
||||
DynamicSet.setOf(binder(), DraftPublishedListener.class);
|
||||
|
@ -26,6 +26,7 @@ public class ChangeAttribute {
|
||||
public String number;
|
||||
public String subject;
|
||||
public AccountAttribute owner;
|
||||
public AccountAttribute assignee;
|
||||
public String url;
|
||||
public String commitMessage;
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.events;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.data.AccountAttribute;
|
||||
|
||||
public class AssigneeChangedEvent extends ChangeEvent {
|
||||
static final String TYPE = "assignee-changed";
|
||||
public Supplier<AccountAttribute> changer;
|
||||
public Supplier<AccountAttribute> oldAssignee;
|
||||
|
||||
public AssigneeChangedEvent(Change change) {
|
||||
super(TYPE, change);
|
||||
}
|
||||
}
|
@ -158,6 +158,7 @@ public class EventFactory {
|
||||
}
|
||||
a.url = getChangeUrl(change);
|
||||
a.owner = asAccountAttribute(change.getOwner());
|
||||
a.assignee = asAccountAttribute(change.getAssignee());
|
||||
a.status = change.getStatus();
|
||||
return a;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ public class EventTypes {
|
||||
private static final Map<String, Class<?>> typesByString = new HashMap<>();
|
||||
|
||||
static {
|
||||
register(AssigneeChangedEvent.TYPE, AssigneeChangedEvent.class);
|
||||
register(ChangeAbandonedEvent.TYPE, ChangeAbandonedEvent.class);
|
||||
register(ChangeMergedEvent.TYPE, ChangeMergedEvent.class);
|
||||
register(ChangeRestoredEvent.TYPE, ChangeRestoredEvent.class);
|
||||
|
@ -24,6 +24,7 @@ import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ApprovalInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.events.AssigneeChangedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeAbandonedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeMergedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeRestoredListener;
|
||||
@ -73,6 +74,7 @@ import java.util.Map.Entry;
|
||||
|
||||
@Singleton
|
||||
public class StreamEventsApiListener implements
|
||||
AssigneeChangedListener,
|
||||
ChangeAbandonedListener,
|
||||
ChangeMergedListener,
|
||||
ChangeRestoredListener,
|
||||
@ -91,6 +93,8 @@ public class StreamEventsApiListener implements
|
||||
public static class Module extends LifecycleModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
DynamicSet.bind(binder(), AssigneeChangedListener.class)
|
||||
.to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeAbandonedListener.class)
|
||||
.to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeMergedListener.class)
|
||||
@ -177,8 +181,8 @@ public class StreamEventsApiListener implements
|
||||
new Supplier<AccountAttribute>() {
|
||||
@Override
|
||||
public AccountAttribute get() {
|
||||
return eventFactory.asAccountAttribute(
|
||||
new Account.Id(account._accountId));
|
||||
return account != null ? eventFactory.asAccountAttribute(
|
||||
new Account.Id(account._accountId)) : null;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -265,6 +269,22 @@ public class StreamEventsApiListener implements
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAssigneeChanged(AssigneeChangedListener.Event ev) {
|
||||
try {
|
||||
Change change = getChange(ev.getChange());
|
||||
AssigneeChangedEvent event = new AssigneeChangedEvent(change);
|
||||
|
||||
event.change = changeAttributeSupplier(change);
|
||||
event.changer = accountAttributeSupplier(ev.getWho());
|
||||
event.oldAssignee = accountAttributeSupplier(ev.getOldAssignee());
|
||||
|
||||
dispatcher.get().postEvent(change, event);
|
||||
} catch (OrmException e) {
|
||||
log.error("Failed to dispatch event", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTopicEdited(TopicEditedListener.Event ev) {
|
||||
try {
|
||||
|
@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2016 The Android Open Source Project
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package com.google.gerrit.server.extensions.events;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.events.AssigneeChangedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
public class AssigneeChanged {
|
||||
private static final Logger log =
|
||||
LoggerFactory.getLogger(AssigneeChanged.class);
|
||||
|
||||
private final DynamicSet<AssigneeChangedListener> listeners;
|
||||
private final EventUtil util;
|
||||
|
||||
@Inject
|
||||
AssigneeChanged(DynamicSet<AssigneeChangedListener> listeners,
|
||||
EventUtil util) {
|
||||
this.listeners = listeners;
|
||||
this.util = util;
|
||||
}
|
||||
|
||||
public void fire(ChangeInfo change, AccountInfo editor, AccountInfo oldAssignee,
|
||||
Timestamp when) {
|
||||
if (!listeners.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
Event event = new Event(change, editor, oldAssignee, when);
|
||||
for (AssigneeChangedListener l : listeners) {
|
||||
try {
|
||||
l.onAssigneeChanged(event);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error in event listener", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void fire(Change change, Account account, Account oldAssignee,
|
||||
Timestamp when) {
|
||||
if (!listeners.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
fire(util.changeInfo(change),
|
||||
util.accountInfo(account),
|
||||
util.accountInfo(oldAssignee),
|
||||
when);
|
||||
} catch (OrmException e) {
|
||||
log.error("Couldn't fire event", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Event extends AbstractChangeEvent
|
||||
implements AssigneeChangedListener.Event {
|
||||
private final AccountInfo oldAssignee;
|
||||
|
||||
Event(ChangeInfo change, AccountInfo editor, AccountInfo oldAssignee,
|
||||
Timestamp when) {
|
||||
super(change, editor, when, NotifyHandling.ALL);
|
||||
this.oldAssignee = oldAssignee;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccountInfo getOldAssignee() {
|
||||
return oldAssignee;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user