diff options
author | Shawn O. Pearce <sop@google.com> | 2010-08-12 16:42:02 -0700 |
---|---|---|
committer | Shawn O. Pearce <sop@google.com> | 2010-08-12 16:42:02 -0700 |
commit | 78a63ddfea66014cea68a4f7541a0770e358cf68 (patch) | |
tree | 39dc954c22a4b2657552a1d41462f4919b777c66 | |
parent | dfd895e35147953d362b29b78123f8558e57d684 (diff) | |
parent | f855f399f8ce740e08ddc48c0694c1c076fa69dd (diff) | |
download | gerrit-exp-nosql.tar.gz |
Merge branch 'master' into exp-nosqlexp-nosql
* master:
Fix all of our pom.xml versions to be 2.1-SNAPSHOT
Use internal templates to simplify minor formatting commands.
Convert 3 email classes to file based templates.
Convert the Abandoned and MergeFail email classes to templates
Use a template to set the contents of the CommentEmails.
Use a template to set the footer on ChangeEmails.
Use a template to set the contents of the MergedEmails.
Use a template to set the subject line.
Add framework for using velocity templates in email classes
Add ability to deactivate a user when they leave the project.
Conflicts:
gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectDigestFilter.java
gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java
gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
Change-Id: Iac92b56e10f9cc4063fc0ec3cea6c79a5a087994
65 files changed, 1035 insertions, 399 deletions
diff --git a/Documentation/config-mail.txt b/Documentation/config-mail.txt new file mode 100644 index 00000000..168bbfe1 --- /dev/null +++ b/Documentation/config-mail.txt @@ -0,0 +1,172 @@ +Gerrit Code Review - Mail Templates +=================================== + +Gerrit uses velocity templates for the bulk of the standard mails it sends out. +There are builtin default templates which are used if they are not overridden. +These defaults are also provided as examples so that administrators may copy +them and easily modify them to tweak their contents. + + +Template Locations and Extensions: +---------------------------------- + +The default example templates reside under: `'$site_path'/etc/mail` and are +terminated with the double extension `.vm.example`. Modifying these example +files will have no effect on the behavior of Gerrit. However, copying an +example template to an equivalently named file without the `.example` extension +and modifying it will allow an administrator to customize the template. + + +Supported Mail Templates: +------------------------- + +Each mail that Gerrit sends out is controlled by at least one template, these +are listed below. Change emails are influenced by two additional templates, +one to set the subject line, and one to set the footer which gets appended to +all the change emails (see `ChangeSubject.vm` and `ChangeFooter.vm` below.) + +Abandoned.vm +~~~~~~~~~~~~ + +The `Abandoned.vm` template will determine the contents of the email related +to a change being abandoned. It is a `ChangeEmail`: see `ChangeSubject.vm` and +`ChangeFooter.vm`. + +ChangeFooter.vm +~~~~~~~~~~~~~~~ + +The `ChangeFooter.vm` template will determine the contents of the footer +text that will be appended to emails related to changes (all `ChangeEmails)`. + +ChangeSubject.vm +~~~~~~~~~~~~~~~~ + +The `ChangeSubject.vm` template will determine the contents of the email +subject line for ALL emails related to changes. + +Comment.vm +~~~~~~~~~~ + +The `Comment.vm` template will determine the contents of the email related to +a user submitting comments on changes. It is a `ChangeEmail`: see + +Merged.vm +~~~~~~~~~ + +The `Merged.vm` template will determine the contents of the email related to +a change successfully merged to the head. It is a `ChangeEmail`: see +`ChangeSubject.vm` and `ChangeFooter.vm`. + +MergeFail.vm +~~~~~~~~~~~~ + +The `MergeFail.vm` template will determine the contents of the email related +to a failure upon attempting to merge a change to the head. It is a + +NewChange.vm +~~~~~~~~~~~~ + +The `NewChange.vm` template will determine the contents of the email related +to a user submitting a new change for review. It is a `ChangeEmail`: see +`ChangeSubject.vm` and `ChangeFooter.vm`. + +RegisterNewEmail.vm +~~~~~~~~~~~~~~~~~~~ + +The `RegisterNewEmail.vm` template will determine the contents of the email +related to registering new email accounts. + +ReplacePatchSet.vm +~~~~~~~~~~~~~~~~~~ + +The `ReplacePatchSet.vm` template will determine the contents of the email +related to a user submitting a new patchset for a change. It is a +`ChangeEmail`: see `ChangeSubject.vm` and `ChangeFooter.vm`. + + +Mail Variables and Methods +-------------------------- + +Mail templates can access and display objects currently made available to them +via the velocity context. While the base objects are documented here, it is +possible to call public methods on these objects from templates. Those methods +are not documented here since they could change with every release. As these +templates are meant to be modified only by a qualified sysadmin, it is accepted +that writing templates for Gerrit emails is likely to require some basic +knowledge of the class structure to be useful. Browsing the source code might +be necessary for anything more than a minor formatting change. + +Warning +~~~~~~~ + +Be aware that modifying templates can cause them to fail to parse and therefor +not send out the actual email, or worse, calling methods on the available +objects could have internal side effects which would adversely affect the +health of your Gerrit server and/or data. + +All OutgoingEmails +~~~~~~~~~~~~~~~~~~ + +All outgoing emails have the following variables available to them: + +$email:: ++ +A reference to the class constructing the current `OutgoingEmail`. With this +reference it is possible to call any public method on the OutgoingEmail class +or the current child class inherited from it. + +$messageClass:: ++ +A String containing the messageClass + +$StringUtils:: ++ +A reference to the Apache `StringUtils` class. This can be very useful for +formatting strings. + +Change Emails +~~~~~~~~~~~~~ + +All change related emails have the following additional variables available to them: + +$change:: ++ +A reference to the current `Change` object + +$changeId:: ++ +Id of the current change (a `Change.Key`) + +$coverLetter:: ++ +The text of the `ChangeMessage` + +$branch:: ++ +A reference to the branch of this change (a `Branch.NameKey`) + +$fromName:: ++ +The name of the from user + +$projectName:: ++ +The name of this change's project + +$patchSet:: ++ +A reference to the current `PatchSet` + +$patchSetInfo:: ++ +A reference to the current `PatchSetInfo` + + +See Also +-------- + +* link:http://velocity.apache.org/[velocity] + +GERRIT +------ +Part of link:index.html[Gerrit Code Review] diff --git a/Documentation/index.txt b/Documentation/index.txt index 1e13e8d8..e4194552 100644 --- a/Documentation/index.txt +++ b/Documentation/index.txt @@ -31,6 +31,7 @@ Configuration * link:config-sso.html[Single Sign-On Systems] * link:config-apache2.html[Apache 2 Reverse Proxy] * link:config-hooks.html[Hooks] +* link:config-mail.html[Mail Templates] Developer Documentation ----------------------- diff --git a/Documentation/licenses.txt b/Documentation/licenses.txt index 6e76303f..6d543d5a 100644 --- a/Documentation/licenses.txt +++ b/Documentation/licenses.txt @@ -31,6 +31,7 @@ Apache Log4J <<apache2,Apache License 2.0>> Apache MINA <<apache2,Apache License 2.0>> Apache Tomact Servlet API <<apache2,Apache License 2.0>> Apache SSHD <<apache2,Apache License 2.0>>, see also <<sshd,NOTICE>> +Apache Velocity <<apache2,Apache License 2.0>> Apache Xerces <<apache2,Apache License 2.0>> OpenID4Java <<apache2,Apache License 2.0>> Neko HTML <<apache2,Apache License 2.0>> diff --git a/gerrit-common/pom.xml b/gerrit-common/pom.xml index adac3a80..af031913 100644 --- a/gerrit-common/pom.xml +++ b/gerrit-common/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-common</artifactId> diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewerResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewerResult.java index 19772fcf..678ec79a 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewerResult.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewerResult.java @@ -50,6 +50,9 @@ public class ReviewerResult { /** Name supplied does not match to a registered account. */ ACCOUNT_NOT_FOUND, + /** The account is inactive. */ + ACCOUNT_INACTIVE, + /** The account is not permitted to see the change. */ CHANGE_NOT_VISIBLE, diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java index 164df439..9dae1698 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java @@ -28,7 +28,7 @@ public interface SuggestService extends RemoteJsonService { void suggestProjectNameKey(String query, int limit, AsyncCallback<List<Project.NameKey>> callback); - void suggestAccount(String query, int limit, + void suggestAccount(String query, Boolean enabled, int limit, AsyncCallback<List<AccountInfo>> callback); void suggestAccountGroup(String query, int limit, diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InactiveAccountException.java b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InactiveAccountException.java new file mode 100644 index 00000000..6ae5eb6d --- /dev/null +++ b/gerrit-common/src/main/java/com/google/gerrit/common/errors/InactiveAccountException.java @@ -0,0 +1,26 @@ +// Copyright (C) 2010 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.common.errors; + +/** Error indicating the account is currently inactive. */ +public class InactiveAccountException extends Exception { + private static final long serialVersionUID = 1L; + + public static final String MESSAGE = "Account Inactive: "; + + public InactiveAccountException(String who) { + super(MESSAGE + who); + } +} diff --git a/gerrit-ehcache/pom.xml b/gerrit-ehcache/pom.xml index 8e2e2dd3..a7c6cf51 100644 --- a/gerrit-ehcache/pom.xml +++ b/gerrit-ehcache/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-ehcache</artifactId> diff --git a/gerrit-gwtdebug/pom.xml b/gerrit-gwtdebug/pom.xml index 95572275..d5a67e13 100644 --- a/gerrit-gwtdebug/pom.xml +++ b/gerrit-gwtdebug/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-gwtdebug</artifactId> diff --git a/gerrit-gwtui/pom.xml b/gerrit-gwtui/pom.xml index 29c5b01c..9a27d12b 100644 --- a/gerrit-gwtui/pom.xml +++ b/gerrit-gwtui/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-gwtui</artifactId> diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java index 3f263d23..b32a32d0 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.java @@ -46,6 +46,8 @@ public interface GerritConstants extends Constants { String nameAlreadyUsedBody(); String noSuchAccountTitle(); + String inactiveAccountBody(); + String menuAll(); String menuAllOpen(); String menuAllMerged(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties index 83a06e47..33630150 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritConstants.properties @@ -29,6 +29,8 @@ notFoundBody = The page you requested was not found. nameAlreadyUsedBody = The name is already in use. noSuchAccountTitle = Code Review - Unknown User +inactiveAccountBody = This user is currently inactive. + menuAll = All menuAllOpen = Open menuAllMerged = Merged diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java index f850a33e..23dd6357 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java @@ -188,6 +188,10 @@ public class ApprovalTable extends Composite { r.append(Util.M.accountNotFound(e.getName())); break; + case ACCOUNT_INACTIVE: + r.append(Util.M.accountInactive(e.getName())); + break; + case CHANGE_NOT_VISIBLE: r.append(Util.M.changeNotVisibleTo(e.getName())); break; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java index 51e2bc58..fd7c3631 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.java @@ -47,6 +47,7 @@ public interface ChangeMessages extends Messages { String changeQueryPageTitle(String query); String accountNotFound(String who); + String accountInactive(String who); String changeNotVisibleTo(String who); String anonymousDownload(String protocol); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties index 5d2d3a50..80f9dabc 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeMessages.properties @@ -28,6 +28,7 @@ changeQueryWindowTitle = {0} changeQueryPageTitle = Search for {0} accountNotFound = {0} is not a registered user. +accountInactive = {0} is not an active user. changeNotVisibleTo = {0} cannot access the change. anonymousDownload = Anonymous {0} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java index fa028d75..f29742ad 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/GerritCallback.java @@ -17,6 +17,7 @@ package com.google.gerrit.client.rpc; import com.google.gerrit.client.ErrorDialog; import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.NotSignedInDialog; +import com.google.gerrit.common.errors.InactiveAccountException; import com.google.gerrit.common.errors.NameAlreadyUsedException; import com.google.gerrit.common.errors.NoSuchAccountException; import com.google.gerrit.common.errors.NoSuchEntityException; @@ -37,6 +38,9 @@ public abstract class GerritCallback<T> implements AsyncCallback<T> { } else if (isNoSuchEntity(caught)) { new ErrorDialog(Gerrit.C.notFoundBody()).center(); + } else if (isInactiveAccount(caught)) { + new ErrorDialog(Gerrit.C.inactiveAccountBody()).center(); + } else if (isNoSuchAccount(caught)) { final String msg = caught.getMessage(); final String who = msg.substring(NoSuchAccountException.MESSAGE.length()); @@ -71,6 +75,11 @@ public abstract class GerritCallback<T> implements AsyncCallback<T> { && caught.getMessage().equals(NoSuchEntityException.MESSAGE); } + protected static boolean isInactiveAccount(final Throwable caught) { + return caught instanceof RemoteJsonException + && caught.getMessage().startsWith(InactiveAccountException.MESSAGE); + } + private static boolean isNoSuchAccount(final Throwable caught) { return caught instanceof RemoteJsonException && caught.getMessage().startsWith(NoSuchAccountException.MESSAGE); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java index 441878f4..bcf6438e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountSuggestOracle.java @@ -30,7 +30,8 @@ public class AccountSuggestOracle extends HighlightSuggestOracle { public void onRequestSuggestions(final Request req, final Callback callback) { RpcStatus.hide(new Runnable() { public void run() { - SuggestUtil.SVC.suggestAccount(req.getQuery(), req.getLimit(), + SuggestUtil.SVC.suggestAccount(req.getQuery(), Boolean.TRUE, + req.getLimit(), new GerritCallback<List<AccountInfo>>() { public void onSuccess(final List<AccountInfo> result) { final ArrayList<AccountSuggestion> r = diff --git a/gerrit-httpd/pom.xml b/gerrit-httpd/pom.xml index b02b1425..39b27887 100644 --- a/gerrit-httpd/pom.xml +++ b/gerrit-httpd/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-httpd</artifactId> diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectDigestFilter.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectDigestFilter.java index de1eb15c..2118b9c2 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectDigestFilter.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectDigestFilter.java @@ -146,6 +146,11 @@ class ProjectDigestFilter implements Filter { return false; } + if (!FutureUtil.get(accountCache.getAccount(who.getAccountId())).isActive()) { + rsp.sendError(SC_UNAUTHORIZED); + return false; + } + final String A1 = username + ":" + realm + ":" + passwd; final String A2 = method + ":" + uri; diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java index dc8fba55..45955207 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java @@ -84,8 +84,8 @@ class SuggestServiceImpl extends BaseServiceImplementation implements }); } - public void suggestAccount(final String query, final int limit, - final AsyncCallback<List<AccountInfo>> callback) { + public void suggestAccount(final String query, final Boolean active, + final int limit, final AsyncCallback<List<AccountInfo>> callback) { run(callback, new Action<List<AccountInfo>>() { public List<AccountInfo> run(final ReviewDb db) throws OrmException { final String a = query; @@ -95,12 +95,16 @@ class SuggestServiceImpl extends BaseServiceImplementation implements LinkedHashMap<Account.Id, AccountInfo> res = Maps.newLinkedHashMap(); for (Account p : db.accounts().suggestByFullName(a, b, n)) { - res.put(p.getId(), new AccountInfo(p)); + if (active == null || active == p.isActive()) { + res.put(p.getId(), new AccountInfo(p)); + } } if (res.size() < n) { for (Account p : db.accounts().suggestByPreferredEmail(a, b, n - res.size())) { - res.put(p.getId(), new AccountInfo(p)); + if (active == null || active == p.isActive()) { + res.put(p.getId(), new AccountInfo(p)); + } } } if (res.size() < n) { @@ -115,9 +119,11 @@ class SuggestServiceImpl extends BaseServiceImplementation implements for (Map.Entry<String, Future<Account>> ent : want.entrySet()) { Account p = FutureUtil.get(ent.getValue()); - AccountInfo info = new AccountInfo(p); - info.setPreferredEmail(ent.getKey()); - res.put(p.getId(), info); + if (active == null || active == p.isActive()) { + AccountInfo info = new AccountInfo(p); + info.setPreferredEmail(ent.getKey()); + res.put(p.getId(), info); + } } } return new ArrayList<AccountInfo>(res.values()); diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java index 5dfc09e6..eb12537a 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java @@ -17,6 +17,7 @@ package com.google.gerrit.httpd.rpc.account; import com.google.common.util.concurrent.ListenableFuture; import com.google.gerrit.common.data.GroupAdminService; import com.google.gerrit.common.data.GroupDetail; +import com.google.gerrit.common.errors.InactiveAccountException; import com.google.gerrit.common.errors.NameAlreadyUsedException; import com.google.gerrit.common.errors.NoSuchAccountException; import com.google.gerrit.common.errors.NoSuchEntityException; @@ -225,6 +226,9 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements } final Account a = findAccount(nameOrEmail); + if (!a.isActive()) { + throw new Failure(new InactiveAccountException(a.getFullName())); + } if (!control.canAdd(a.getId())) { throw new Failure(new NoSuchEntityException()); } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java index ae36388d..9d508e2f 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java @@ -94,6 +94,11 @@ class AddReviewer extends Handler<ReviewerResult> { ReviewerResult.Error.Type.ACCOUNT_NOT_FOUND, nameOrEmail)); continue; } + if (!account.isActive()) { + result.addError(new ReviewerResult.Error( + ReviewerResult.Error.Type.ACCOUNT_INACTIVE, nameOrEmail)); + continue; + } final IdentifiedUser user = identifiedUserFactory.create(account.getId()); if (!control.forUser(user).isVisible()) { diff --git a/gerrit-launcher/pom.xml b/gerrit-launcher/pom.xml index 10007772..3c9c9796 100644 --- a/gerrit-launcher/pom.xml +++ b/gerrit-launcher/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-launcher</artifactId> diff --git a/gerrit-main/pom.xml b/gerrit-main/pom.xml index 10cb14ae..a46aa4ff 100644 --- a/gerrit-main/pom.xml +++ b/gerrit-main/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-main</artifactId> diff --git a/gerrit-patch-commonsnet/pom.xml b/gerrit-patch-commonsnet/pom.xml index df64d138..5bbae035 100644 --- a/gerrit-patch-commonsnet/pom.xml +++ b/gerrit-patch-commonsnet/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-patch-commonsnet</artifactId> diff --git a/gerrit-patch-jgit/pom.xml b/gerrit-patch-jgit/pom.xml index 68a08c3d..f30eaced 100644 --- a/gerrit-patch-jgit/pom.xml +++ b/gerrit-patch-jgit/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-patch-jgit</artifactId> diff --git a/gerrit-pgm/pom.xml b/gerrit-pgm/pom.xml index 8dbf3247..d3eee423 100644 --- a/gerrit-pgm/pom.xml +++ b/gerrit-pgm/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-pgm</artifactId> diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java index 74e75483..dae08934 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/SitePathInitializer.java @@ -25,11 +25,13 @@ import static com.google.gerrit.pgm.init.InitUtil.version; import com.google.gerrit.pgm.Init; import com.google.gerrit.pgm.util.ConsoleUI; import com.google.gerrit.server.config.SitePaths; +import com.google.gerrit.server.mail.OutgoingEmail; import com.google.inject.Binding; import com.google.inject.Inject; import com.google.inject.Injector; import com.google.inject.TypeLiteral; +import java.io.File; import java.util.ArrayList; import java.util.List; @@ -66,6 +68,7 @@ public class SitePathInitializer { mkdir(site.etc_dir); mkdir(site.lib_dir); mkdir(site.logs_dir); + mkdir(site.mail_dir); mkdir(site.static_dir); for (InitStep step : steps) { @@ -82,11 +85,27 @@ public class SitePathInitializer { extract(site.gerrit_sh, Init.class, "gerrit.sh"); chmod(0755, site.gerrit_sh); + extractMailExample("Abandoned.vm"); + extractMailExample("ChangeFooter.vm"); + extractMailExample("ChangeSubject.vm"); + extractMailExample("Comment.vm"); + extractMailExample("Merged.vm"); + extractMailExample("MergeFail.vm"); + extractMailExample("NewChange.vm"); + extractMailExample("RegisterNewEmail.vm"); + extractMailExample("ReplacePatchSet.vm"); + if (!ui.isBatch()) { System.err.println(); } } + private void extractMailExample(String orig) throws Exception { + File ex = new File(site.mail_dir, orig + ".example"); + extract(ex, OutgoingEmail.class, orig); + chmod(0444, ex); + } + private static List<InitStep> stepsOf(final Injector injector) { final ArrayList<InitStep> r = new ArrayList<InitStep>(); for (Binding<InitStep> b : all(injector)) { diff --git a/gerrit-prettify/pom.xml b/gerrit-prettify/pom.xml index 053d399a..18ba6746 100644 --- a/gerrit-prettify/pom.xml +++ b/gerrit-prettify/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-prettify</artifactId> diff --git a/gerrit-reviewdb/pom.xml b/gerrit-reviewdb/pom.xml index 5626739a..d81b068b 100644 --- a/gerrit-reviewdb/pom.xml +++ b/gerrit-reviewdb/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-reviewdb</artifactId> diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java index 8468834c..ee65c55d 100644 --- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java +++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Account.java @@ -130,6 +130,10 @@ public final class Account { @Column(id = 6, name = Column.NONE) protected AccountGeneralPreferences generalPreferences; + /** Is this user active */ + @Column(id = 7) + protected boolean inactive; + /** <i>computed</i> the username selected from the identities. */ protected String userName; @@ -199,6 +203,14 @@ public final class Account { contactFiledOn = new Timestamp(System.currentTimeMillis()); } + public boolean isActive() { + return ! inactive; + } + + public void setActive(boolean active) { + inactive = ! active; + } + /** @return the computed user name for this account */ public String getUserName() { return userName; diff --git a/gerrit-server/pom.xml b/gerrit-server/pom.xml index 947930c7..d056ab3d 100644 --- a/gerrit-server/pom.xml +++ b/gerrit-server/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-server</artifactId> @@ -34,6 +34,16 @@ limitations under the License. <dependencies> <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + </dependency> + + <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity</artifactId> + </dependency> + + <dependency> <groupId>org.eclipse.jgit</groupId> <artifactId>org.eclipse.jgit</artifactId> </dependency> diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java index fcef20cf..3a241d36 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java @@ -97,7 +97,7 @@ public class AccountManager { * @param who identity of the user, with any details we received about them. * @return the result of authenticating the user. * @throws AccountException the account does not exist, and cannot be created, - * or exists, but cannot be located. + * or exists, but cannot be located, or is inactive. */ public AuthResult authenticate(AuthRequest who) throws AccountException { who = realm.authenticate(who); @@ -111,9 +111,14 @@ public class AccountManager { // return create(db, who); - } else { - // Account exists, return the identity to the caller. - // + } else { // Account exists + + Account act = db.accounts().get(id.getAccountId()); + if (act == null || !act.isActive()) { + throw new AccountException("Authentication error, account inactive"); + } + + // return the identity to the caller. update(db, who, id); return new AuthResult(id.getAccountId(), key, false); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java index e98e2971..5ebaada6 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java @@ -17,6 +17,7 @@ package com.google.gerrit.server.config; import static com.google.inject.Scopes.SINGLETON; import com.google.gerrit.common.data.ApprovalTypes; +import com.google.gerrit.lifecycle.LifecycleListener; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.reviewdb.AuthType; @@ -63,15 +64,53 @@ import com.google.gerrit.server.workflow.FunctionState; import com.google.inject.Inject; import com.google.inject.TypeLiteral; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.runtime.RuntimeConstants; import org.eclipse.jgit.lib.Config; import org.eclipse.jgit.lib.PersonIdent; +import java.util.Properties; import java.util.Set; + /** Starts global state with standard dependencies. */ public class GerritGlobalModule extends FactoryModule { private final AuthType loginType; + public static class VelocityLifecycle implements LifecycleListener { + private final SitePaths site; + + @Inject + VelocityLifecycle(final SitePaths site) { + this.site = site; + } + + @Override + public void start() { + String rl = "resource.loader"; + String pkg = "org.apache.velocity.runtime.resource.loader"; + Properties p = new Properties(); + + p.setProperty(rl, "file, class"); + p.setProperty("file." + rl + ".class", pkg + ".FileResourceLoader"); + p.setProperty("file." + rl + ".path", site.mail_dir.getAbsolutePath()); + p.setProperty("class." + rl + ".class", pkg + ".ClasspathResourceLoader"); + p.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, + "org.apache.velocity.runtime.log.SimpleLog4JLogSystem" ); + p.setProperty("runtime.log.logsystem.log4j.category", "velocity"); + + try { + Velocity.init(p); + } catch(Exception e) { + throw new RuntimeException(e); + } + } + + @Override + public void stop() { + } + } + @Inject GerritGlobalModule(final AuthConfig authConfig, @GerritServerConfig final Config config) { @@ -147,6 +186,7 @@ public class GerritGlobalModule extends FactoryModule { @Override protected void configure() { listener().to(WorkQueue.Lifecycle.class); + listener().to(VelocityLifecycle.class); } }); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java index 1faa672a..c3a5fb7a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/SitePaths.java @@ -28,6 +28,7 @@ public final class SitePaths { public final File etc_dir; public final File lib_dir; public final File logs_dir; + public final File mail_dir; public final File hooks_dir; public final File static_dir; @@ -61,6 +62,7 @@ public final class SitePaths { etc_dir = new File(site_path, "etc"); lib_dir = new File(site_path, "lib"); logs_dir = new File(site_path, "logs"); + mail_dir = new File(etc_dir, "mail"); hooks_dir = new File(site_path, "hooks"); static_dir = new File(site_path, "static"); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java index d2b5c29c..e6798497 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AbandonedSender.java @@ -30,7 +30,7 @@ public class AbandonedSender extends ReplyToChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); ccAllApprovals(); @@ -39,10 +39,7 @@ public class AbandonedSender extends ReplyToChangeSender { } @Override - protected void formatChange() { - appendText(getNameFor(fromId)); - appendText(" has abandoned change " + change.getKey().abbreviate() + ":\n"); - appendText("\n"); - formatCoverLetter(); + protected void formatChange() throws EmailException { + appendText(velocifyFile("Abandoned.vm")); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java index be62ba07..e5437cfa 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/AddReviewerSender.java @@ -32,7 +32,7 @@ public class AddReviewerSender extends NewChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); ccExistingReviewers(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java index e3a0f727..931fc37b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ChangeEmail.java @@ -53,7 +53,6 @@ public abstract class ChangeEmail extends OutgoingEmail { private ProjectState projectState; protected ChangeData changeData; - private boolean inFooter; protected ChangeEmail(EmailArguments ea, final Change c, final String mc) { super(ea, mc); @@ -75,31 +74,9 @@ public abstract class ChangeEmail extends OutgoingEmail { } /** Format the message body by calling {@link #appendText(String)}. */ - protected void format() { + protected void format() throws EmailException { formatChange(); - if (getChangeUrl() != null) { - openFooter(); - appendText("To view visit "); - appendText(getChangeUrl()); - appendText("\n"); - } - if (getSettingsUrl() != null) { - openFooter(); - appendText("To unsubscribe, visit "); - appendText(getSettingsUrl()); - appendText("\n"); - } - - if (inFooter) { - appendText("\n"); - } else { - openFooter(); - } - appendText("Gerrit-MessageType: " + messageClass + "\n"); - appendText("Gerrit-Project: " + projectName + "\n"); - appendText("Gerrit-Branch: " + change.getDest().getShortName() + "\n"); - appendText("Gerrit-Owner: " + getNameEmailFor(change.getOwner()) + "\n"); - + appendText(velocifyFile("ChangeFooter.vm")); try { HashSet<Account.Id> reviewers = new HashSet<Account.Id>(); for (PatchSetApproval p : args.db.get().patchSetApprovals().byChange( @@ -120,13 +97,11 @@ public abstract class ChangeEmail extends OutgoingEmail { } /** Format the message body by calling {@link #appendText(String)}. */ - protected abstract void formatChange(); + protected abstract void formatChange() throws EmailException; /** Setup the message headers and envelope (TO, CC, BCC). */ @Override - protected void init() { - super.init(); - + protected void init() throws EmailException { projectState = FutureUtil.get(args.projectCache.get(change.getProject())); projectName = projectState != null // ? projectState.getProject().getName() // @@ -148,6 +123,8 @@ public abstract class ChangeEmail extends OutgoingEmail { } } + super.init(); + if (changeMessage != null && changeMessage.getWrittenOn() != null) { setHeader("Date", new Date(changeMessage.getWrittenOn().getTime())); } @@ -156,27 +133,21 @@ public abstract class ChangeEmail extends OutgoingEmail { setListIdHeader(); setChangeUrlHeader(); setCommitIdHeader(); - - inFooter = false; } - private void setListIdHeader() { + private void setListIdHeader() throws EmailException { // Set a reasonable list id so that filters can be used to sort messages - // - final StringBuilder listid = new StringBuilder(); - listid.append("gerrit-"); - listid.append(projectName.replace('/', '-')); - listid.append("@"); - listid.append(getGerritHost()); - - final String listidStr = listid.toString(); - setHeader("Mailing-List", "list " + listidStr); - setHeader("List-Id", "<" + listidStr.replace('@', '.') + ">"); + setVHeader("Mailing-List", "list $email.listId"); + setVHeader("List-Id", "<$email.listId.replace('@', '.')>"); if (getSettingsUrl() != null) { - setHeader("List-Unsubscribe", "<" + getSettingsUrl() + ">"); + setVHeader("List-Unsubscribe", "<$email.settingsUrl>"); } } + public String getListId() throws EmailException { + return velocify("gerrit-$projectName.replace('/', '-')@$email.gerritHost"); + } + private void setChangeUrlHeader() { final String u = getChangeUrl(); if (u != null) { @@ -192,27 +163,12 @@ public abstract class ChangeEmail extends OutgoingEmail { } } - private void setChangeSubjectHeader() { - final StringBuilder subj = new StringBuilder(); - subj.append("["); - subj.append(change.getDest().getShortName()); - subj.append("] "); - subj.append("Change "); - subj.append(change.getKey().abbreviate()); - subj.append(": ("); - subj.append(projectName); - subj.append(") "); - if (change.getSubject().length() > 60) { - subj.append(change.getSubject().substring(0, 60)); - subj.append("..."); - } else { - subj.append(change.getSubject()); - } - setHeader("Subject", subj.toString()); + private void setChangeSubjectHeader() throws EmailException { + setHeader("Subject", velocifyFile("ChangeSubject.vm")); } /** Get a link to the change; null if the server doesn't know its own address. */ - protected String getChangeUrl() { + public String getChangeUrl() { if (change != null && getGerritUrl() != null) { final StringBuilder r = new StringBuilder(); r.append(getGerritUrl()); @@ -222,25 +178,9 @@ public abstract class ChangeEmail extends OutgoingEmail { return null; } - protected String getChangeMessageThreadId() { - final StringBuilder r = new StringBuilder(); - r.append('<'); - r.append("gerrit"); - r.append('.'); - r.append(change.getCreatedOn().getTime()); - r.append('.'); - r.append(change.getKey().get()); - r.append('@'); - r.append(getGerritHost()); - r.append('>'); - return r.toString(); - } - - private void openFooter() { - if (!inFooter) { - inFooter = true; - appendText("-- \n"); - } + public String getChangeMessageThreadId() throws EmailException { + return velocify("<gerrit.${change.createdOn.time}.$change.key.get()" + + "@$email.gerritHost>"); } /** Format the sender's "cover letter", {@link #getCoverLetter()}. */ @@ -253,7 +193,7 @@ public abstract class ChangeEmail extends OutgoingEmail { } /** Get the text of the "cover letter", from {@link ChangeMessage}. */ - protected String getCoverLetter() { + public String getCoverLetter() { if (changeMessage != null) { final String txt = changeMessage.getMessage(); if (txt != null) { @@ -265,23 +205,30 @@ public abstract class ChangeEmail extends OutgoingEmail { /** Format the change message and the affected file list. */ protected void formatChangeDetail() { + appendText(getChangeDetail()); + } + + /** Create the change message and the affected file list. */ + public String getChangeDetail() { + StringBuilder detail = new StringBuilder(); + if (patchSetInfo != null) { - appendText(patchSetInfo.getMessage().trim()); - appendText("\n"); + detail.append(patchSetInfo.getMessage().trim() + "\n"); } else { - appendText(change.getSubject().trim()); - appendText("\n"); + detail.append(change.getSubject().trim() + "\n"); } if (patchSet != null) { - appendText("---\n"); + detail.append("---\n"); for (PatchListEntry p : getPatchList().getPatches()) { - appendText(p.getChangeType().getCode() + " " + p.getNewName() + "\n"); + detail.append(p.getChangeType().getCode() + " " + p.getNewName() + "\n"); } - appendText("\n"); + detail.append("\n"); } + return detail.toString(); } + /** Get the patch list corresponding to this patch set. */ protected PatchList getPatchList() { if (patchSet != null) { @@ -423,4 +370,17 @@ public abstract class ChangeEmail extends OutgoingEmail { || projectState.controlFor(args.identifiedUserFactory.create(to)) .controlFor(change).isVisible(); } + + @Override + protected void setupVelocityContext() { + super.setupVelocityContext(); + velocityContext.put("change", change); + velocityContext.put("changeId", change.getKey()); + velocityContext.put("coverLetter", getCoverLetter()); + velocityContext.put("branch", change.getDest()); + velocityContext.put("fromName", getNameFor(fromId)); + velocityContext.put("projectName", projectName); + velocityContext.put("patchSet", patchSet); + velocityContext.put("patchSetInfo", patchSetInfo); + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java index be6360fe..d3c3b7a2 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java @@ -56,7 +56,7 @@ public class CommentSender extends ReplyToChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); ccAllApprovals(); @@ -65,20 +65,13 @@ public class CommentSender extends ReplyToChangeSender { } @Override - protected void formatChange() { - if (!"".equals(getCoverLetter()) || !inlineComments.isEmpty()) { - appendText("Comments on Patch Set " + patchSet.getPatchSetId() + ":\n"); - appendText("\n"); - formatCoverLetter(); - formatInlineComments(); - if (getChangeUrl() != null) { - appendText("To respond, visit " + getChangeUrl() + "\n"); - appendText("\n"); - } - } + protected void formatChange() throws EmailException { + appendText(velocifyFile("Comment.vm")); } - private void formatInlineComments() { + public String getInlineComments() { + StringBuilder cmts = new StringBuilder(); + final Repository repo = getRepository(); try { final PatchList patchList = repo != null ? getPatchList() : null; @@ -91,10 +84,10 @@ public class CommentSender extends ReplyToChangeSender { final short side = c.getSide(); if (!pk.equals(currentFileKey)) { - appendText("....................................................\n"); - appendText("File "); - appendText(pk.get()); - appendText("\n"); + cmts.append("....................................................\n"); + cmts.append("File "); + cmts.append(pk.get()); + cmts.append("\n"); currentFileKey = pk; if (patchList != null) { @@ -109,26 +102,27 @@ public class CommentSender extends ReplyToChangeSender { } } - appendText("Line " + lineNbr); + cmts.append("Line " + lineNbr); if (currentFileData != null) { try { final String lineStr = currentFileData.getLine(side, lineNbr); - appendText(": "); - appendText(lineStr); + cmts.append(": "); + cmts.append(lineStr); } catch (Throwable cce) { // Don't quote the line if we can't safely convert it. } } - appendText("\n"); + cmts.append("\n"); - appendText(c.getMessage().trim()); - appendText("\n\n"); + cmts.append(c.getMessage().trim()); + cmts.append("\n\n"); } } finally { if (repo != null) { repo.close(); } } + return cmts.toString(); } private Repository getRepository() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java index 5ea9e204..be830b94 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CreateChangeSender.java @@ -43,7 +43,7 @@ public class CreateChangeSender extends NewChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); bccWatchers(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java index e9b1a5b0..196db4b0 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/EmailArguments.java @@ -22,6 +22,7 @@ import com.google.gerrit.server.IdentifiedUser.GenericFactory; import com.google.gerrit.server.account.AccountCache; import com.google.gerrit.server.account.AccountProjectWatchCache; import com.google.gerrit.server.config.CanonicalWebUrl; +import com.google.gerrit.server.config.SitePaths; import com.google.gerrit.server.config.WildProjectName; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.patch.PatchListCache; @@ -51,6 +52,7 @@ class EmailArguments { final ChangeQueryBuilder.Factory queryBuilder; final Provider<ChangeQueryRewriter> queryRewriter; final Provider<ReviewDb> db; + final SitePaths site; @Inject EmailArguments(GitRepositoryManager server, ProjectCache projectCache, @@ -63,7 +65,8 @@ class EmailArguments { @CanonicalWebUrl @Nullable Provider<String> urlProvider, @WildProjectName Project.NameKey wildProject, ChangeQueryBuilder.Factory queryBuilder, - Provider<ChangeQueryRewriter> queryRewriter, Provider<ReviewDb> db) { + Provider<ChangeQueryRewriter> queryRewriter, Provider<ReviewDb> db, + SitePaths site) { this.server = server; this.projectCache = projectCache; this.accountCache = accountCache; @@ -79,5 +82,6 @@ class EmailArguments { this.queryBuilder = queryBuilder; this.queryRewriter = queryRewriter; this.db = db; + this.site = site; } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java index 00750ef3..cf8f590b 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergeFailSender.java @@ -30,23 +30,14 @@ public class MergeFailSender extends ReplyToChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); ccExistingReviewers(); } @Override - protected void formatChange() { - appendText("Change " + change.getKey().abbreviate()); - if (patchSetInfo != null && patchSetInfo.getAuthor() != null - && patchSetInfo.getAuthor().getName() != null) { - appendText(" by "); - appendText(patchSetInfo.getAuthor().getName()); - } - appendText(" FAILED to submit to "); - appendText(change.getDest().getShortName()); - appendText(".\n\n"); - formatCoverLetter(); + protected void formatChange() throws EmailException { + appendText(velocifyFile("MergeFail.vm")); } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java index caf19e47..40f47907 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java @@ -51,7 +51,7 @@ public class MergedSender extends ReplyToChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); ccAllApprovals(); @@ -61,58 +61,47 @@ public class MergedSender extends ReplyToChangeSender { } @Override - protected void formatChange() { - appendText("Change " + change.getKey().abbreviate()); - if (patchSetInfo != null && patchSetInfo.getAuthor() != null - && patchSetInfo.getAuthor().getName() != null) { - appendText(" by "); - appendText(patchSetInfo.getAuthor().getName()); - } - appendText(" submitted to "); - appendText(dest.getShortName()); - appendText(":\n\n"); - formatChangeDetail(); - formatApprovals(); + protected void formatChange() throws EmailException { + appendText(velocifyFile("Merged.vm")); } - private void formatApprovals() { - if (patchSet != null) { - try { - final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> pos = - new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>(); - - final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> neg = - new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>(); - - for (PatchSetApproval ca : args.db.get().patchSetApprovals() - .byPatchSet(patchSet.getId())) { - if (ca.getValue() > 0) { - insert(pos, ca); - } else if (ca.getValue() < 0) { - insert(neg, ca); - } + public String getApprovals() { + try { + final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> pos = + new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>(); + + final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> neg = + new HashMap<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>>(); + + for (PatchSetApproval ca : args.db.get().patchSetApprovals() + .byPatchSet(patchSet.getId())) { + if (ca.getValue() > 0) { + insert(pos, ca); + } else if (ca.getValue() < 0) { + insert(neg, ca); } - - format("Approvals", pos); - format("Objections", neg); - } catch (OrmException err) { - // Don't list the approvals } + + return format("Approvals", pos) + format("Objections", neg); + } catch (OrmException err) { + // Don't list the approvals } + return ""; } - private void format(final String type, + private String format(final String type, final Map<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> list) { + StringBuilder txt = new StringBuilder(); if (list.isEmpty()) { - return; + return ""; } - appendText(type + ":\n"); + txt.append(type + ":\n"); for (final Map.Entry<Account.Id, Map<ApprovalCategory.Id, PatchSetApproval>> ent : list .entrySet()) { final Map<ApprovalCategory.Id, PatchSetApproval> l = ent.getValue(); - appendText(" "); - appendText(getNameFor(ent.getKey())); - appendText(": "); + txt.append(" "); + txt.append(getNameFor(ent.getKey())); + txt.append(": "); boolean first = true; for (ApprovalType at : approvalTypes.getApprovalTypes()) { final PatchSetApproval ca = l.get(at.getCategory().getId()); @@ -123,24 +112,25 @@ public class MergedSender extends ReplyToChangeSender { if (first) { first = false; } else { - appendText("; "); + txt.append("; "); } final ApprovalCategoryValue v = at.getValue(ca); if (v != null) { - appendText(v.getName()); + txt.append(v.getName()); } else { - appendText(at.getCategory().getName()); - appendText("="); + txt.append(at.getCategory().getName()); + txt.append("="); if (ca.getValue() > 0) { - appendText("+"); + txt.append("+"); } - appendText("" + ca.getValue()); + txt.append("" + ca.getValue()); } } - appendText("\n"); + txt.append("\n"); } - appendText("\n"); + txt.append("\n"); + return txt.toString(); } private void insert( diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java index dc8c2c2b..9e78cabf 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java @@ -20,6 +20,7 @@ import com.google.gerrit.server.ssh.SshInfo; import com.jcraft.jsch.HostKey; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -46,7 +47,7 @@ public abstract class NewChangeSender extends ChangeEmail { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); setHeader("Message-ID", getChangeMessageThreadId()); @@ -57,74 +58,19 @@ public abstract class NewChangeSender extends ChangeEmail { } @Override - protected void formatChange() { - formatSalutation(); - formatChangeDetail(); - - appendText("\n"); - appendText(" " + getPullUrl() + "\n"); + protected void formatChange() throws EmailException { + appendText(velocifyFile("NewChange.vm")); } - private void formatSalutation() { - final String changeUrl = getChangeUrl(); - + public List<String> getReviewerNames() { if (reviewers.isEmpty()) { - formatDest(); - if (changeUrl != null) { - appendText("\n"); - appendText(" " + changeUrl + "\n"); - appendText("\n"); - } - appendText("\n"); - - } else { - appendText("Hello"); - for (final Iterator<Account.Id> i = reviewers.iterator(); i.hasNext();) { - appendText(" "); - appendText(getNameFor(i.next())); - appendText(","); - } - appendText("\n"); - appendText("\n"); - - appendText("I'd like you to do a code review."); - if (changeUrl != null) { - appendText(" Please visit\n"); - appendText("\n"); - appendText(" " + changeUrl + "\n"); - appendText("\n"); - appendText("to review the following change:\n"); - } - appendText("\n"); - - formatDest(); - appendText("\n"); + return null; } - } - - private void formatDest() { - appendText("Change " + change.getKey().abbreviate()); - appendText(" for "); - appendText(change.getDest().getShortName()); - appendText(" in "); - appendText(projectName); - appendText(":\n"); - } - - private String getPullUrl() { - final String host = getSshHost(); - if (host == null) { - return ""; + List<String> names = new ArrayList<String>(); + for (Account.Id id : reviewers) { + names.add(getNameFor(id)); } - - final StringBuilder r = new StringBuilder(); - r.append("git pull ssh://"); - r.append(host); - r.append("/"); - r.append(projectName); - r.append(" "); - r.append(patchSet.getRefName()); - return r.toString(); + return names; } public String getSshHost() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java index ea577358..587aeca8 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java @@ -18,11 +18,19 @@ import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.UserIdentity; import com.google.gerrit.server.mail.EmailHeader.AddressList; import com.google.gerrit.server.util.FutureUtil; +import com.google.gerrit.server.account.AccountState; +import com.google.gerrit.server.mail.EmailHeader.AddressList; + +import org.apache.commons.lang.StringUtils; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.exception.ResourceNotFoundException; +import org.apache.velocity.VelocityContext; import org.eclipse.jgit.util.SystemReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; @@ -47,6 +55,7 @@ public abstract class OutgoingEmail { private final List<Address> smtpRcptTo = new ArrayList<Address>(); private Address smtpFromAddress; private StringBuilder body; + protected VelocityContext velocityContext; protected final EmailArguments args; protected Account.Id fromId; @@ -114,10 +123,12 @@ public abstract class OutgoingEmail { } /** Format the message body by calling {@link #appendText(String)}. */ - protected abstract void format(); + protected abstract void format() throws EmailException; /** Setup the message headers and envelope (TO, CC, BCC). */ - protected void init() { + protected void init() throws EmailException { + setupVelocityContext(); + smtpFromAddress = args.fromAddressGenerator.from(fromId); setHeader("Date", new Date()); headers.put("From", new EmailHeader.AddressList(smtpFromAddress)); @@ -141,26 +152,32 @@ public abstract class OutgoingEmail { body = new StringBuilder(); if (fromId != null && args.fromAddressGenerator.isGenericAddress(fromId)) { - final Account account = - FutureUtil.get(args.accountCache.getAccount(fromId)); - final String name = account.getFullName(); - final String email = account.getPreferredEmail(); - - if ((name != null && !name.isEmpty()) - || (email != null && !email.isEmpty())) { - body.append("From"); - if (name != null && !name.isEmpty()) { - body.append(" ").append(name); - } - if (email != null && !email.isEmpty()) { - body.append(" <").append(email).append(">"); - } - body.append(":\n\n"); + appendText(getFromLine()); + } + } + + protected String getFromLine() { + final Account account = + FutureUtil.get(args.accountCache.getAccount(fromId)); + final String name = account.getFullName(); + final String email = account.getPreferredEmail(); + StringBuilder f = new StringBuilder(); + + if ((name != null && !name.isEmpty()) + || (email != null && !email.isEmpty())) { + f.append("From"); + if (name != null && !name.isEmpty()) { + f.append(" ").append(name); + } + if (email != null && !email.isEmpty()) { + f.append(" <").append(email).append(">"); } + f.append(":\n\n"); } + return f.toString(); } - protected String getGerritHost() { + public String getGerritHost() { if (getGerritUrl() != null) { try { return new URL(getGerritUrl()).getHost(); @@ -186,10 +203,16 @@ public abstract class OutgoingEmail { return null; } - protected String getGerritUrl() { + public String getGerritUrl() { return args.urlProvider.get(); } + /** Set a header in the outgoing message using a template. */ + protected void setVHeader(final String name, final String value) throws + EmailException { + setHeader(name, velocify(value)); + } + /** Set a header in the outgoing message. */ protected void setHeader(final String name, final String value) { headers.put(name, new EmailHeader.String(value)); @@ -224,7 +247,7 @@ public abstract class OutgoingEmail { return name; } - protected String getNameEmailFor(Account.Id accountId) { + public String getNameEmailFor(Account.Id accountId) { Account who = FutureUtil.get(args.accountCache.getAccount(accountId)); String name = who.getFullName(); String email = who.getPreferredEmail(); @@ -313,9 +336,46 @@ public abstract class OutgoingEmail { private Address toAddress(final Account.Id id) { final Account a = FutureUtil.get(args.accountCache.getAccount(id)); final String e = a.getPreferredEmail(); - if (e == null) { + if (!a.isActive() || e == null) { return null; } return new Address(a.getFullName(), e); } + + protected void setupVelocityContext() { + velocityContext = new VelocityContext(); + + velocityContext.put("email", this); + velocityContext.put("messageClass", messageClass); + velocityContext.put("StringUtils", StringUtils.class); + } + + protected String velocify(String tpl) throws EmailException { + try { + StringWriter w = new StringWriter(); + Velocity.evaluate(velocityContext, w, "OutgoingEmail", tpl); + return w.toString(); + } catch(Exception e) { + throw new EmailException("Velocity template "+ tpl.toString(), e); + } + } + + protected String velocifyFile(String name) throws EmailException { + try { + StringWriter w = new StringWriter(); + Velocity.mergeTemplate(name, velocityContext, w); + return w.toString(); + } catch(ResourceNotFoundException e) { + try { + StringWriter w = new StringWriter(); + String pkg = "com/google/gerrit/server/mail/"; + Velocity.mergeTemplate(pkg + name, velocityContext, w); + return w.toString(); + } catch(Exception e2) { + throw new EmailException("Velocity WAR template" + name + ".\n", e2); + } + } catch(Exception e) { + throw new EmailException("Velocity template " + name + ".\n", e); + } + } } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RegisterNewEmailSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RegisterNewEmailSender.java index 9b201fd4..2c779994 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/RegisterNewEmailSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/RegisterNewEmailSender.java @@ -40,7 +40,7 @@ public class RegisterNewEmailSender extends OutgoingEmail { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); setHeader("Subject", "[Gerrit Code Review] Email Verification"); add(RecipientType.TO, new Address(addr)); @@ -52,39 +52,8 @@ public class RegisterNewEmailSender extends OutgoingEmail { } @Override - protected void format() { - final StringBuilder url = new StringBuilder(); - url.append(getGerritUrl()); - url.append("#VE,"); - url.append(getEmailRegistrationToken()); - - appendText("Welcome to Gerrit Code Review at "); - appendText(getGerritHost()); - appendText(".\n"); - - appendText("\n"); - appendText("To add a verified email address to your user account, please\n"); - appendText("click on the following link:\n"); - appendText("\n"); - appendText(url.toString()); - appendText("\n"); - - appendText("\n"); - appendText("If you have received this mail in error," - + " you do not need to take any\n"); - appendText("action to cancel the account." - + " The account will not be activated, and\n"); - appendText("you will not receive any further emails.\n"); - - appendText("\n"); - appendText("If clicking the link above does not work," - + " copy and paste the URL in a\n"); - appendText("new browser window instead.\n"); - - appendText("\n"); - appendText("This is a send-only email address." - + " Replies to this message will not\n"); - appendText("be read or answered.\n"); + protected void format() throws EmailException { + appendText(velocifyFile("RegisterNewEmail.vm")); } public String getEmailRegistrationToken() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java index 841aa355..0c8ca9ae 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java @@ -22,6 +22,7 @@ import com.google.inject.assistedinject.Assisted; import com.jcraft.jsch.HostKey; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.Iterator; @@ -53,7 +54,7 @@ public class ReplacePatchSetSender extends ReplyToChangeSender { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); if (fromId != null) { @@ -67,77 +68,19 @@ public class ReplacePatchSetSender extends ReplyToChangeSender { } @Override - protected void formatChange() { - formatSalutation(); - formatChangeDetail(); - - appendText("\n"); - appendText(" " + getPullUrl() + "\n"); + protected void formatChange() throws EmailException { + appendText(velocifyFile("ReplacePatchSet.vm")); } - private void formatSalutation() { - final String changeUrl = getChangeUrl(); - + public List<String> getReviewerNames() { if (reviewers.isEmpty()) { - formatDest(); - if (changeUrl != null) { - appendText("\n"); - appendText(" " + changeUrl + "\n"); - appendText("\n"); - } - appendText("\n"); - - } else { - appendText("Hello"); - for (final Iterator<Account.Id> i = reviewers.iterator(); i.hasNext();) { - appendText(" "); - appendText(getNameFor(i.next())); - appendText(","); - } - appendText("\n"); - appendText("\n"); - - appendText("I'd like you to reexamine change " - + change.getKey().abbreviate() + "."); - if (changeUrl != null) { - appendText(" Please visit\n"); - appendText("\n"); - appendText(" " + changeUrl + "\n"); - appendText("\n"); - appendText("to look at patch set " + patchSet.getPatchSetId()); - appendText(":\n"); - } - appendText("\n"); - - formatDest(); - appendText("\n"); + return null; } - } - - private void formatDest() { - appendText("Change " + change.getKey().abbreviate()); - appendText(" (patch set " + patchSet.getPatchSetId() + ")"); - appendText(" for "); - appendText(change.getDest().getShortName()); - appendText(" in "); - appendText(projectName); - appendText(":\n"); - } - - private String getPullUrl() { - final String host = getSshHost(); - if (host == null) { - return ""; + List<String> names = new ArrayList<String>(); + for (Account.Id id : reviewers) { + names.add(getNameFor(id)); } - - final StringBuilder r = new StringBuilder(); - r.append("git pull ssh://"); - r.append(host); - r.append("/"); - r.append(projectName); - r.append(" "); - r.append(patchSet.getRefName()); - return r.toString(); + return names; } public String getSshHost() { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java index 05d2753d..4c3ed764 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplyToChangeSender.java @@ -23,7 +23,7 @@ public abstract class ReplyToChangeSender extends ChangeEmail { } @Override - protected void init() { + protected void init() throws EmailException { super.init(); final String threadId = getChangeMessageThreadId(); diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_103.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_103.java index 46c34341..54746381 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_103.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_103.java @@ -33,7 +33,7 @@ public class Schema_103 extends SchemaVersion { private static final int MAX_SCAN_SIZE = 1000; @Inject - Schema_103(Provider<Schema_40> prior) { + Schema_103(Provider<Schema_41> prior) { super(prior); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_41.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_41.java new file mode 100644 index 00000000..508db436 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_41.java @@ -0,0 +1,25 @@ +// Copyright (C) 2010 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.schema; + +import com.google.inject.Inject; +import com.google.inject.Provider; + +public class Schema_41 extends SchemaVersion { + @Inject + Schema_41(Provider<Schema_40> prior) { + super(prior); + } +} diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Abandoned.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Abandoned.vm new file mode 100644 index 00000000..557ee608 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Abandoned.vm @@ -0,0 +1,40 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The Abandoned.vm template will determine the contents of the email related +## to a change being abandoned. It is a ChangeEmail: see ChangeSubject.vm and +## ChangeFooter.vm. +## +$fromName has abandoned change $changeId.abbreviate(): + +#if ($coverLetter) +$coverLetter + +#end diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeFooter.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeFooter.vm new file mode 100644 index 00000000..c15d6efb --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeFooter.vm @@ -0,0 +1,49 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The ChangeFooter.vm template will determine the contents of the footer +## text that will be appended to ALL emails related to changes. +## +-- +#if ($email.changeUrl) +To view, visit $email.changeUrl +#set ($notblank = 1) +#end +#if ($email.settingsUrl) +To unsubscribe, visit $email.settingsUrl +#set ($notblank = 1) +#end +#if ($notblank == 1) + +#end +Gerrit-MessageType: $messageClass +Gerrit-Project: $projectName +Gerrit-Branch: $branch.shortName +Gerrit-Owner: $email.getNameEmailFor($change.owner) diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm new file mode 100644 index 00000000..2132c635 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ChangeSubject.vm @@ -0,0 +1,37 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The ChangeSubject.vm template will determine the contents of the email +## subject line for ALL emails related to changes. +## +#macro(elipses $length $str) +#if($str.length() > $length)${str.substring(0,$length)}...#else$str#end +#end +[$branch.shortName] Change $changeId.abbreviate(): ($projectName) #elipses(60, $change.subject) diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Comment.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Comment.vm new file mode 100644 index 00000000..b7ba89e2 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Comment.vm @@ -0,0 +1,47 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The Comment.vm template will determine the contents of the email related to +## a user submitting comments on changes. It is a ChangeEmail: see +## ChangeSubject.vm and ChangeFooter.vm. +## +#if ($email.coverLetter || $email.inlineComments) +Comments on Patch Set $patchSet.patchSetId: + +#if ($email.coverLetter) +$email.coverLetter + +#end +#if($email.inlineComments)$email.inlineComments#end +#if ($email.changeUrl) +To respond, visit $email.changeUrl + +#end +#end diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/MergeFail.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/MergeFail.vm new file mode 100644 index 00000000..17036a1b --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/MergeFail.vm @@ -0,0 +1,41 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The MergeFail.vm template will determine the contents of the email related +## to a failure upon attempting to merge a change to the head. It is a +## ChangeEmail: see ChangeSubject.vm and ChangeFooter.vm. +## +Change $change.key.abbreviate()#if ($patchSetInfo.author.name) + by $patchSetInfo.author.name#end FAILED to submit to ${change.dest.shortName}. + +#if ($email.coverLetter) +$email.coverLetter + +#end diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Merged.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Merged.vm new file mode 100644 index 00000000..c459c169 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/Merged.vm @@ -0,0 +1,38 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The Merged.vm template will determine the contents of the email related to +## a change successfully merged to the head. It is a ChangeEmail: see +## ChangeSubject.vm and ChangeFooter.vm. +## +Change $changeId.abbreviate()#if ($patchSetInfo.author.name) + by $patchSetInfo.author.name#end submitted to $change.dest.shortName: + +$email.changeDetail$email.approvals diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/NewChange.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/NewChange.vm new file mode 100644 index 00000000..7f610391 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/NewChange.vm @@ -0,0 +1,57 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The NewChange.vm template will determine the contents of the email related +## to a user submitting a new change for review. It is a ChangeEmail: see +## ChangeSubject.vm and ChangeFooter.vm. +## +#set ($destination = "Change $changeId.abbreviate() for $branch.shortName in $projectName:") +#if($email.reviewerNames) +Hello $StringUtils.join($email.reviewerNames, ' ,'), + +I'd like you to do a code review.#if($email.changeUrl) Please visit + + $email.changeUrl + +to review the following change: +#end + +$destination +#else +$destination +#if($email.changeUrl) + + $email.changeUrl + +#end +#end + +$email.changeDetail + git pull ssh://$email.sshHost/$projectName $patchSet.refName diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RegisterNewEmail.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RegisterNewEmail.vm new file mode 100644 index 00000000..c1de87e6 --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/RegisterNewEmail.vm @@ -0,0 +1,49 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The RegisterNewEmail.vm template will determine the contents of the email +## related to registering new email accounts. +## +Welcome to Gerrit Code Review at ${email.gerritHost}. + +To add a verified email address to your user account, please +click on the following link: + +$email.gerritUrl#VE,$email.emailRegistrationToken + +If you have received this mail in error, you do not need to take any +action to cancel the account. The account will not be activated, and +you will not receive any further emails. + +If clicking the link above does not work, copy and paste the URL in a +new browser window instead. + +This is a send-only email address. Replies to this message will not +be read or answered. diff --git a/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ReplacePatchSet.vm b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ReplacePatchSet.vm new file mode 100644 index 00000000..d13b6aff --- /dev/null +++ b/gerrit-server/src/main/resources/com/google/gerrit/server/mail/ReplacePatchSet.vm @@ -0,0 +1,57 @@ +## Copyright (C) 2010 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. +## +## +## Template Type: +## ------------- +## This is a velocity mail template, see: http://velocity.apache.org and the +## gerrit-docs:config-mail.txt for more info on modifying gerrit mail templates. +## +## Template File Names and extensions: +## ---------------------------------- +## Gerrit will use templates ending in ".vm" but will ignore templates ending +## in ".vm.example". If a .vm template does not exist, the default internal +## gerrit template which is the same as the .vm.example will be used. If you +## want to override the default template, copy the .vm.exmaple file to a .vm +## file and edit it appropriately. +## +## This Template: +## -------------- +## The ReplacePatchSet.vm template will determine the contents of the email +## related to a user submitting a new patchset for a change. It is a +## ChangeEmail: see ChangeSubject.vm and ChangeFooter.vm. +## +#set ($destination = "Change $changeId.abbreviate() (patch set $patchSet.patchSetId) for $branch.shortName in $projectName:") +#if($email.reviewerNames) +Hello $StringUtils.join($email.reviewerNames, ' ,'), + +I'd like you to reexamine change ${changeId.abbreviate()}.#if($email.changeUrl) Please visit + + $email.changeUrl + +to look at patch set $patchSet.patchSetId +#end + +$destination +#else +$destination +#if($email.changeUrl) + + $email.changeUrl + +#end +#end + +$email.changeDetail + git pull ssh://$email.sshHost/$projectName $patchSet.refName diff --git a/gerrit-sshd/pom.xml b/gerrit-sshd/pom.xml index d1adb77f..d48972f6 100644 --- a/gerrit-sshd/pom.xml +++ b/gerrit-sshd/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-sshd</artifactId> diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java index ee6a72a9..e2a37f59 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePubKeyAuth.java @@ -135,6 +135,11 @@ class DatabasePubKeyAuth implements PublickeyAuthenticator { } } + if (!createUser(sd, key).getAccount().isActive()) { + sd.authenticationError(username, "inactive-account"); + return false; + } + return success(username, session, sd, createUser(sd, key)); } diff --git a/gerrit-util-cli/pom.xml b/gerrit-util-cli/pom.xml index 20f28e10..6db5241a 100644 --- a/gerrit-util-cli/pom.xml +++ b/gerrit-util-cli/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-util-cli</artifactId> diff --git a/gerrit-util-ssl/pom.xml b/gerrit-util-ssl/pom.xml index 220ae479..39d3ce09 100644 --- a/gerrit-util-ssl/pom.xml +++ b/gerrit-util-ssl/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-util-ssl</artifactId> diff --git a/gerrit-war/pom.xml b/gerrit-war/pom.xml index 4bfa17e2..87cfaa5f 100644 --- a/gerrit-war/pom.xml +++ b/gerrit-war/pom.xml @@ -22,7 +22,7 @@ limitations under the License. <parent> <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> </parent> <artifactId>gerrit-war</artifactId> @@ -22,7 +22,7 @@ limitations under the License. <groupId>com.google.gerrit</groupId> <artifactId>gerrit-parent</artifactId> <packaging>pom</packaging> - <version>2.1.4-SNAPSHOT</version> + <version>2.1-SNAPSHOT</version> <name>Gerrit Code Review - Parent</name> <url>http://code.google.com/p/gerrit/</url> @@ -483,6 +483,12 @@ limitations under the License. </dependency> <dependency> + <groupId>org.apache.velocity</groupId> + <artifactId>velocity</artifactId> + <version>1.6.4</version> + </dependency> + + <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>1.7.2</version> |