summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn O. Pearce <sop@google.com>2009-06-08 12:26:58 -0700
committerShawn O. Pearce <sop@google.com>2009-06-08 12:26:58 -0700
commite24a97229d06ed516639336d3d3f9cda2e2aa702 (patch)
tree8acec74e72e5e919b07c3b46f603ea0cb97ec20e
parent828f3c71a5159ce53ba109e44849228eace63772 (diff)
Enable groups to manage contributor agreements
For a corporate style contributor agreement there are typically more than one account which is covered by that agreement, and the CLA is actually between the company and the project leaders, not the users who are listed out on that agreement. Permission as to who is an authorized user under that agreement should be managed by the company who made the agreement as employees enter the company, leave, or are shifted to different job functions. By creating a pair of groups in Gerrit, e.g. "Initech Users" and "Initech Admins", with the later being the owner of the former, the Initech personnel can manage their own authorized users list, without involving the Gerrit site administrators. Bug: GERRIT-17 Signed-off-by: Shawn O. Pearce <sop@google.com>
-rw-r--r--src/main/java/com/google/gerrit/client/account/AgreementInfo.java25
-rw-r--r--src/main/java/com/google/gerrit/client/account/AgreementPanel.java11
-rw-r--r--src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java6
-rw-r--r--src/main/java/com/google/gerrit/client/reviewdb/AbstractAgreement.java59
-rw-r--r--src/main/java/com/google/gerrit/client/reviewdb/AccountAgreement.java32
-rw-r--r--src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreement.java114
-rw-r--r--src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreementAccess.java31
-rw-r--r--src/main/java/com/google/gerrit/client/reviewdb/ReviewDb.java3
-rw-r--r--src/main/java/com/google/gerrit/server/ssh/Receive.java40
-rw-r--r--src/main/webapp/WEB-INF/sql/upgrade012_013_mysql.sql11
-rw-r--r--src/main/webapp/WEB-INF/sql/upgrade012_013_postgres.sql12
11 files changed, 296 insertions, 48 deletions
diff --git a/src/main/java/com/google/gerrit/client/account/AgreementInfo.java b/src/main/java/com/google/gerrit/client/account/AgreementInfo.java
index 1206665217..7aa74c8941 100644
--- a/src/main/java/com/google/gerrit/client/account/AgreementInfo.java
+++ b/src/main/java/com/google/gerrit/client/account/AgreementInfo.java
@@ -18,17 +18,22 @@ import com.google.gerrit.client.data.AccountInfoCache;
import com.google.gerrit.client.data.AccountInfoCacheFactory;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountAgreement;
+import com.google.gerrit.client.reviewdb.AccountGroup;
+import com.google.gerrit.client.reviewdb.AccountGroupAgreement;
import com.google.gerrit.client.reviewdb.ContributorAgreement;
import com.google.gerrit.client.reviewdb.ReviewDb;
+import com.google.gerrit.client.rpc.Common;
import com.google.gwtorm.client.OrmException;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AgreementInfo {
protected AccountInfoCache accounts;
- protected List<AccountAgreement> accepted;
+ protected List<AccountAgreement> userAccepted;
+ protected List<AccountGroupAgreement> groupAccepted;
protected Map<ContributorAgreement.Id, ContributorAgreement> agreements;
public AgreementInfo() {
@@ -37,9 +42,23 @@ public class AgreementInfo {
public void load(final Account.Id me, final ReviewDb db) throws OrmException {
final AccountInfoCacheFactory acc = new AccountInfoCacheFactory(db);
- accepted = db.accountAgreements().byAccount(me).toList();
+ userAccepted = db.accountAgreements().byAccount(me).toList();
+ groupAccepted = new ArrayList<AccountGroupAgreement>();
+ for (final AccountGroup.Id groupId : Common.getGroupCache()
+ .getEffectiveGroups(me)) {
+ groupAccepted.addAll(db.accountGroupAgreements().byGroup(groupId)
+ .toList());
+ }
+
agreements = new HashMap<ContributorAgreement.Id, ContributorAgreement>();
- for (final AccountAgreement a : accepted) {
+ for (final AccountAgreement a : userAccepted) {
+ acc.want(a.getReviewedBy());
+ if (!agreements.containsKey(a.getAgreementId())) {
+ agreements.put(a.getAgreementId(), db.contributorAgreements().get(
+ a.getAgreementId()));
+ }
+ }
+ for (final AccountGroupAgreement a : groupAccepted) {
acc.want(a.getReviewedBy());
if (!agreements.containsKey(a.getAgreementId())) {
agreements.put(a.getAgreementId(), db.contributorAgreements().get(
diff --git a/src/main/java/com/google/gerrit/client/account/AgreementPanel.java b/src/main/java/com/google/gerrit/client/account/AgreementPanel.java
index 5b2b1ae6b4..0f92567bce 100644
--- a/src/main/java/com/google/gerrit/client/account/AgreementPanel.java
+++ b/src/main/java/com/google/gerrit/client/account/AgreementPanel.java
@@ -16,7 +16,9 @@ package com.google.gerrit.client.account;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Link;
+import com.google.gerrit.client.reviewdb.AbstractAgreement;
import com.google.gerrit.client.reviewdb.AccountAgreement;
+import com.google.gerrit.client.reviewdb.AccountGroupAgreement;
import com.google.gerrit.client.reviewdb.ContributorAgreement;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.FancyFlexTable;
@@ -51,7 +53,7 @@ class AgreementPanel extends Composite {
});
}
- private class AgreementTable extends FancyFlexTable<AccountAgreement> {
+ private class AgreementTable extends FancyFlexTable<AbstractAgreement> {
AgreementTable() {
table.setText(0, 1, Util.C.agreementStatus());
table.setText(0, 2, Util.C.agreementName());
@@ -68,12 +70,15 @@ class AgreementPanel extends Composite {
while (1 < table.getRowCount())
table.removeRow(table.getRowCount() - 1);
- for (final AccountAgreement k : result.accepted) {
+ for (final AccountAgreement k : result.userAccepted) {
+ addOne(result, k);
+ }
+ for (final AccountGroupAgreement k : result.groupAccepted) {
addOne(result, k);
}
}
- void addOne(final AgreementInfo info, final AccountAgreement k) {
+ void addOne(final AgreementInfo info, final AbstractAgreement k) {
final int row = table.getRowCount();
table.insertRow(row);
applyDataRowStyle(row);
diff --git a/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java b/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
index 3b7e7a3091..0e9ba08c6d 100644
--- a/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
+++ b/src/main/java/com/google/gerrit/client/account/NewAgreementScreen.java
@@ -18,6 +18,7 @@ import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.Link;
import com.google.gerrit.client.reviewdb.AccountAgreement;
+import com.google.gerrit.client.reviewdb.AccountGroupAgreement;
import com.google.gerrit.client.reviewdb.ContributorAgreement;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountScreen;
@@ -72,7 +73,10 @@ public class NewAgreementScreen extends AccountScreen {
public void onSuccess(AgreementInfo result) {
if (isAttached()) {
mySigned = new HashSet<ContributorAgreement.Id>();
- for (AccountAgreement a : result.accepted) {
+ for (AccountAgreement a : result.userAccepted) {
+ mySigned.add(a.getAgreementId());
+ }
+ for (AccountGroupAgreement a : result.groupAccepted) {
mySigned.add(a.getAgreementId());
}
postRPC();
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/AbstractAgreement.java b/src/main/java/com/google/gerrit/client/reviewdb/AbstractAgreement.java
new file mode 100644
index 0000000000..3364fedf62
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/reviewdb/AbstractAgreement.java
@@ -0,0 +1,59 @@
+// Copyright (C) 2009 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.client.reviewdb;
+
+import java.sql.Timestamp;
+
+/** Base for {@link AccountAgreement} or {@link AccountGroupAgreement}. */
+public interface AbstractAgreement {
+ public static enum Status {
+ NEW('n'),
+
+ VERIFIED('V'),
+
+ REJECTED('R');
+
+ private final char code;
+
+ private Status(final char c) {
+ code = c;
+ }
+
+ public char getCode() {
+ return code;
+ }
+
+ public static Status forCode(final char c) {
+ for (final Status s : Status.values()) {
+ if (s.code == c) {
+ return s;
+ }
+ }
+ return null;
+ }
+ }
+
+ public ContributorAgreement.Id getAgreementId();
+
+ public Timestamp getAcceptedOn();
+
+ public Status getStatus();
+
+ public Timestamp getReviewedOn();
+
+ public Account.Id getReviewedBy();
+
+ public String getReviewComments();
+}
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/AccountAgreement.java b/src/main/java/com/google/gerrit/client/reviewdb/AccountAgreement.java
index 72eaeb24ff..75f52d3e55 100644
--- a/src/main/java/com/google/gerrit/client/reviewdb/AccountAgreement.java
+++ b/src/main/java/com/google/gerrit/client/reviewdb/AccountAgreement.java
@@ -20,7 +20,7 @@ import com.google.gwtorm.client.CompoundKey;
import java.sql.Timestamp;
/** Electronic acceptance of a {@link ContributorAgreement} by {@link Account} */
-public final class AccountAgreement {
+public final class AccountAgreement implements AbstractAgreement {
public static class Key extends CompoundKey<Account.Id> {
private static final long serialVersionUID = 1L;
@@ -51,36 +51,6 @@ public final class AccountAgreement {
}
}
- protected static final char NEW_CODE = 'n';
-
- public static enum Status {
- NEW(NEW_CODE),
-
- VERIFIED('V'),
-
- REJECTED('R');
-
- private final char code;
-
- private Status(final char c) {
- code = c;
- }
-
- public char getCode() {
- return code;
- }
-
- public static Status forCode(final char c) {
- for (final Status s : Status.values()) {
- if (s.code == c) {
- return s;
- }
- }
- return null;
- }
- }
-
-
@Column(name = Column.NONE)
protected Key key;
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreement.java b/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreement.java
new file mode 100644
index 0000000000..4a5d979eb0
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreement.java
@@ -0,0 +1,114 @@
+// Copyright (C) 2009 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.client.reviewdb;
+
+import com.google.gwtorm.client.Column;
+import com.google.gwtorm.client.CompoundKey;
+
+import java.sql.Timestamp;
+
+/**
+ * Acceptance of a {@link ContributorAgreement} by an {@link AccountGroup}.
+ */
+public final class AccountGroupAgreement implements AbstractAgreement {
+ public static class Key extends CompoundKey<AccountGroup.Id> {
+ private static final long serialVersionUID = 1L;
+
+ @Column
+ protected AccountGroup.Id groupId;
+
+ @Column
+ protected ContributorAgreement.Id claId;
+
+ protected Key() {
+ groupId = new AccountGroup.Id();
+ claId = new ContributorAgreement.Id();
+ }
+
+ public Key(final AccountGroup.Id group, final ContributorAgreement.Id cla) {
+ this.groupId = group;
+ this.claId = cla;
+ }
+
+ @Override
+ public AccountGroup.Id getParentKey() {
+ return groupId;
+ }
+
+ @Override
+ public com.google.gwtorm.client.Key<?>[] members() {
+ return new com.google.gwtorm.client.Key<?>[] {claId};
+ }
+ }
+
+ @Column(name = Column.NONE)
+ protected Key key;
+
+ @Column
+ protected Timestamp acceptedOn;
+
+ @Column
+ protected char status;
+
+ @Column(notNull = false)
+ protected Account.Id reviewedBy;
+
+ @Column(notNull = false)
+ protected Timestamp reviewedOn;
+
+ @Column(notNull = false, length = Integer.MAX_VALUE)
+ protected String reviewComments;
+
+ protected AccountGroupAgreement() {
+ }
+
+ public AccountGroupAgreement(final AccountGroupAgreement.Key k) {
+ key = k;
+ acceptedOn = new Timestamp(System.currentTimeMillis());
+ status = Status.NEW.getCode();
+ }
+
+ public AccountGroupAgreement.Key getKey() {
+ return key;
+ }
+
+ public ContributorAgreement.Id getAgreementId() {
+ return key.claId;
+ }
+
+ public Timestamp getAcceptedOn() {
+ return acceptedOn;
+ }
+
+ public Status getStatus() {
+ return Status.forCode(status);
+ }
+
+ public Timestamp getReviewedOn() {
+ return reviewedOn;
+ }
+
+ public Account.Id getReviewedBy() {
+ return reviewedBy;
+ }
+
+ public String getReviewComments() {
+ return reviewComments;
+ }
+
+ public void setReviewComments(final String s) {
+ reviewComments = s;
+ }
+}
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreementAccess.java b/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreementAccess.java
new file mode 100644
index 0000000000..d3efaa3964
--- /dev/null
+++ b/src/main/java/com/google/gerrit/client/reviewdb/AccountGroupAgreementAccess.java
@@ -0,0 +1,31 @@
+// Copyright (C) 2009 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.client.reviewdb;
+
+import com.google.gwtorm.client.Access;
+import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.client.PrimaryKey;
+import com.google.gwtorm.client.Query;
+import com.google.gwtorm.client.ResultSet;
+
+public interface AccountGroupAgreementAccess extends
+ Access<AccountGroupAgreement, AccountGroupAgreement.Key> {
+ @PrimaryKey("key")
+ AccountGroupAgreement get(AccountGroupAgreement.Key key) throws OrmException;
+
+ @Query("WHERE key.groupId = ? ORDER BY acceptedOn DESC")
+ ResultSet<AccountGroupAgreement> byGroup(AccountGroup.Id id)
+ throws OrmException;
+}
diff --git a/src/main/java/com/google/gerrit/client/reviewdb/ReviewDb.java b/src/main/java/com/google/gerrit/client/reviewdb/ReviewDb.java
index aa02c3461c..1ef1603830 100644
--- a/src/main/java/com/google/gerrit/client/reviewdb/ReviewDb.java
+++ b/src/main/java/com/google/gerrit/client/reviewdb/ReviewDb.java
@@ -73,6 +73,9 @@ public interface ReviewDb extends Schema {
AccountGroupMemberAuditAccess accountGroupMembersAudit();
@Relation
+ AccountGroupAgreementAccess accountGroupAgreements();
+
+ @Relation
StarredChangeAccess starredChanges();
@Relation
diff --git a/src/main/java/com/google/gerrit/server/ssh/Receive.java b/src/main/java/com/google/gerrit/server/ssh/Receive.java
index 7f7057760f..606bc487a5 100644
--- a/src/main/java/com/google/gerrit/server/ssh/Receive.java
+++ b/src/main/java/com/google/gerrit/server/ssh/Receive.java
@@ -24,9 +24,12 @@ import static com.google.gerrit.client.reviewdb.ApprovalCategory.PUSH_TAG_ANY;
import com.google.gerrit.client.Link;
import com.google.gerrit.client.data.ApprovalType;
+import com.google.gerrit.client.reviewdb.AbstractAgreement;
import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.AccountAgreement;
import com.google.gerrit.client.reviewdb.AccountExternalId;
+import com.google.gerrit.client.reviewdb.AccountGroup;
+import com.google.gerrit.client.reviewdb.AccountGroupAgreement;
import com.google.gerrit.client.reviewdb.ApprovalCategory;
import com.google.gerrit.client.reviewdb.Branch;
import com.google.gerrit.client.reviewdb.Change;
@@ -199,20 +202,37 @@ class Receive extends AbstractGitCommand {
}
private void verifyActiveContributorAgreement() throws Failure {
- AccountAgreement bestAgreement = null;
+ AbstractAgreement bestAgreement = null;
ContributorAgreement bestCla = null;
try {
- for (final AccountAgreement a : db.accountAgreements().byAccount(
- userAccount.getId()).toList()) {
- final ContributorAgreement cla =
- db.contributorAgreements().get(a.getAgreementId());
- if (cla == null) {
- continue;
+ OUTER: for (final AccountGroup.Id groupId : getGroups()) {
+ for (final AccountGroupAgreement a : db.accountGroupAgreements()
+ .byGroup(groupId)) {
+ final ContributorAgreement cla =
+ db.contributorAgreements().get(a.getAgreementId());
+ if (cla == null) {
+ continue;
+ }
+
+ bestAgreement = a;
+ bestCla = cla;
+ break OUTER;
}
+ }
- bestAgreement = a;
- bestCla = cla;
- break;
+ if (bestAgreement == null) {
+ for (final AccountAgreement a : db.accountAgreements().byAccount(
+ userAccount.getId()).toList()) {
+ final ContributorAgreement cla =
+ db.contributorAgreements().get(a.getAgreementId());
+ if (cla == null) {
+ continue;
+ }
+
+ bestAgreement = a;
+ bestCla = cla;
+ break;
+ }
}
} catch (OrmException e) {
throw new Failure(1, "fatal: database error", e);
diff --git a/src/main/webapp/WEB-INF/sql/upgrade012_013_mysql.sql b/src/main/webapp/WEB-INF/sql/upgrade012_013_mysql.sql
index 9c614b1687..30a5890b4d 100644
--- a/src/main/webapp/WEB-INF/sql/upgrade012_013_mysql.sql
+++ b/src/main/webapp/WEB-INF/sql/upgrade012_013_mysql.sql
@@ -21,4 +21,15 @@ WHERE group_id = (SELECT anonymous_group_id FROM system_config);
UPDATE account_groups SET automatic_membership = 'Y'
WHERE group_id = (SELECT registered_group_id FROM system_config);
+CREATE TABLE account_group_agreements
+(accepted_on TIMESTAMP NOT NULL
+,status CHAR(1) NOT NULL
+,reviewed_by INT
+,reviewed_on TIMESTAMP
+,review_comments TEXT
+,group_id INT NOT NULL
+,cla_id INT NOT NULL
+,PRIMARY KEY (group_id, cla_id)
+);
+
UPDATE schema_version SET version_nbr = 13;
diff --git a/src/main/webapp/WEB-INF/sql/upgrade012_013_postgres.sql b/src/main/webapp/WEB-INF/sql/upgrade012_013_postgres.sql
index 631a33f576..ad173a5da2 100644
--- a/src/main/webapp/WEB-INF/sql/upgrade012_013_postgres.sql
+++ b/src/main/webapp/WEB-INF/sql/upgrade012_013_postgres.sql
@@ -22,6 +22,18 @@ WHERE group_id = (SELECT anonymous_group_id FROM system_config);
UPDATE account_groups SET automatic_membership = 'Y'
WHERE group_id = (SELECT registered_group_id FROM system_config);
+CREATE TABLE account_group_agreements
+(accepted_on TIMESTAMP WITH TIME ZONE NOT NULL
+,status CHAR(1) NOT NULL
+,reviewed_by INT
+,reviewed_on TIMESTAMP WITH TIME ZONE
+,review_comments TEXT
+,group_id INT NOT NULL
+,cla_id INT NOT NULL
+,PRIMARY KEY (group_id, cla_id)
+);
+
ALTER TABLE account_group_members_audit OWNER TO gerrit2;
+ALTER TABLE account_group_agreements OWNER TO gerrit2;
UPDATE schema_version SET version_nbr = 13;