]> source.dussan.org Git - gitblit.git/commitdiff
Renamed GitblitUserService, sendMail method, sendmail.groovy, and RepositoryModel...
authorJames Moger <james.moger@gitblit.com>
Wed, 21 Dec 2011 00:35:54 +0000 (19:35 -0500)
committerJames Moger <james.moger@gitblit.com>
Wed, 21 Dec 2011 00:36:56 +0000 (19:36 -0500)
18 files changed:
docs/01_setup.mkd
docs/04_releases.mkd
groovy/sendemail.groovy [deleted file]
groovy/sendmail.groovy [new file with mode: 0644]
resources/bootstrap.gb.css
src/com/gitblit/FederationPullExecutor.java
src/com/gitblit/GitBlit.java
src/com/gitblit/GitblitUserService.java [new file with mode: 0644]
src/com/gitblit/UserServiceWrapper.java [deleted file]
src/com/gitblit/client/EditRepositoryDialog.java
src/com/gitblit/models/RepositoryModel.java
src/com/gitblit/wicket/GitBlitWebApp.properties
src/com/gitblit/wicket/pages/EditRepositoryPage.html
src/com/gitblit/wicket/pages/EditRepositoryPage.java
src/com/gitblit/wicket/pages/EditTeamPage.html
src/com/gitblit/wicket/pages/EditUserPage.html
src/com/gitblit/wicket/panels/RepositoriesPanel.java
test-gitblit.properties

index 1cc89bf2ae7c99ea969da9471b82a7cef40bd194..7ea575655d96258fd0ff6e510ee725c7bbda0855 100644 (file)
@@ -217,6 +217,18 @@ User passwords are CASE-SENSITIVE and may be *plain*, *md5*, or *combined-md5* f
 There are two actual *roles* in Gitblit: *#admin*, which grants administrative powers to that user, and *#notfederated*, which prevents an account from being pulled by another Gitblit instance.  Administrators automatically have access to all repositories.  All other *roles* are repository names.  If a repository is access-restricted, the user must have the repository's name within his/her roles to bypass the access restriction.  This is how users are granted access to a restricted repository.\r
 \r
 ## Authentication and Authorization Customization\r
+\r
+### Choice 1: Customize Authentication Only\r
+This is the simplest choice where you implement custom authentication and delegate all other standard user and team operations to one of Gitblit's user service implementations.  This choice insulates your customization from changes in User and Team model classes and additional API that may be added to IUserService.\r
+\r
+Please subclass [com.gitblit.GitblitUserService](https://github.com/gitblit/gitblit/blob/master/src/com/gitblit/GitblitUserService.java) and override the *setup()* and *authenticate()* methods.  \r
+Make sure to set the *serviceImpl* field in your *setup()* method.\r
+\r
+You may use your subclass by specifying its fully qualified classname in the *realm.userService* setting.\r
+\r
+Your subclass must be on Gitblit's classpath and must have a public default constructor.  \r
+\r
+### Choice 2: Customize Everything\r
 Instead of maintaining a `users.conf` or `users.properties` file, you may want to integrate Gitblit into an existing environment.\r
 \r
 You may use your own custom *com.gitblit.IUserService* implementation by specifying its fully qualified classname in the *realm.userService* setting.\r
@@ -232,19 +244,21 @@ The preferred hook mechanism is Groovy.  This mechanism only executes when pushi
 \r
 The Groovy hook mechanism allows for dynamic extension of Gitblit to execute custom tasks on receiving and processing push events.  The scripts run within the context of your Gitblit instance and therefore have access to Gitblit's internals at runtime.\r
 \r
-### Rules & Requirements\r
+### Rules, Requirements, & Behaviors\r
 1. Your Groovy scripts must be stored in the *groovy.scriptsFolder* as specified in `gitblit.properties` or `web.xml`.\r
 2. All script files must have the *.groovy* extension. Because of this you may omit the extension when specifying the script.\r
 3. Scripts must be explicitly specified to be executed, no scripts are *automatically* executed by name or extension.\r
-4. A script can be specified to run on *all repositories* by adding the script file name to *groovy.preReceiveScripts* or *groovy.postReceiveScripts* in `gitblit.properties` or `web.xml`.\r
+4. A script can be specified to run on *all repositories* by adding the script file name to *groovy.preReceiveScripts* or *groovy.postReceiveScripts* in `gitblit.properties` or `web.xml`.  Be mindful of access retrictions and global properties like *mail.mailingLists* if specifying *sendmail* to run on all repositories.\r
 5. Scripts may also be specified per-repository in the repository's settings.\r
-6. Global/shared scripts are executed first in their listed order, followed by per-repository scripts in their listed order.\r
-7. A script may only be defined once in a pre-receive list and once in a post-receive list.  \r
+6. Globally specified scripts are excluded from the list of available scripts in a repository's settings \r
+7. Globally specified scripts are executed first, in their listed order, followed by per-repository scripts, in their listed order.\r
+8. A script may only be defined once in a pre-receive list and once in a post-receive list.  \r
 You may execute the same script on pre-receive and post-receive, just not multiple times within a pre-receive or post-receive event.\r
-8. Gitblit does not differentiate between what can be a pre-receive script and what can be a post-receive script.\r
-9. If a script *returns false* then the hook chain is aborted and none of the subsequent scripts will execute.\r
+9. Gitblit does not differentiate between what can be a pre-receive script and what can be a post-receive script.\r
+10. If a script *returns false* then the pre-receive or post-receive hook chain is aborted and none of the subsequent scripts will execute.\r
+\r
+Some sample scripts are included in the GO and WAR distributions to show you how you can tap into Gitblit with the provided bound variables.  Additional implementation details may be specified in the header comment of these examples.\r
 \r
-Some sample scripts are included in the GO and WAR distributions to show you how you can tap into Gitblit with the provided bound variables.  Additional implementation details may be specified in the header comment of these examples.  \r
 Hook contributions and improvements are welcome.\r
 \r
 ### Pre-Receive\r
index 1ec0641149916fee3db4b0341f1eafe9367af81f..292ff9877dc6553b533985ac6876db998dc30b74 100644 (file)
@@ -4,16 +4,18 @@
 **%VERSION%** ([go](http://code.google.com/p/gitblit/downloads/detail?name=%GO%) | [war](http://code.google.com/p/gitblit/downloads/detail?name=%WAR%) | [express](http://code.google.com/p/gitblit/downloads/detail?name=%EXPRESS%) | [fedclient](http://code.google.com/p/gitblit/downloads/detail?name=%FEDCLIENT%) | [manager](http://code.google.com/p/gitblit/downloads/detail?name=%MANAGER%) | [api](http://code.google.com/p/gitblit/downloads/detail?name=%API%)) based on [%JGIT%][jgit] &nbsp; *released %BUILDDATE%*\r
 \r
 - updated: Gitblit GO is now monolithic like the WAR build. (issue 30)  \r
-Either the dependencies are downloaded on first execution OR the dependencies are bundled, either way you would need the dependencies.  This change helps adoption of GO in environments without an internet connection or with a restricted connection.\r
+This change helps adoption of GO in environments without an internet connection or with a restricted connection.\r
 - added: Groovy 1.8.4 and sample pre- and post- push Groovy hook scripts.  Hook scripts can be set per-repository or globally for all repositories.  \r
 Unfortunately this adds another 6 MB to the 8MB Gitblit package, but it allows for a *very* powerful, flexible, platform-independent hook script mechanism.  \r
     **New:** *groovy.scriptsFolder = groovy*  \r
     **New:** *groovy.preReceiveScripts =*  \r
     **New:** *groovy.postReceiveScripts =*\r
-- added: New key for mailing lists.  This is _currently_ used in conjunction with the example *sendemail.groovy* post-receive hook script.  \r
+- added: New key for mailing lists.  This is used in conjunction with the *sendmail.groovy* hook script.  \r
     **New:** *mail.mailingLists =*\r
+- added: GitblitUserService.  This is a wrapper object for the built-in user service implementations.  For those wanting to only implement *custom authentication* it is recommended to subclass GitblitUserService and override the appropriate methods.  Going forward, this will insulate customized behavior from new IUserService API and changes in model classes.\r
 - added: new default user service implementation: com.gitblit.ConfigUserService (users.conf)  \r
-This user service implementation allows for serialization and deserialization of more sophisticated Gitblit User objects and will open the door for more advanced Gitblit features. For upgrading installations, a `users.conf` file will automatically be created for you from your existing `users.properties` file on your first launch of Gitblit.  You will have to manually set *realm.userService=users.conf* to switch to the new user service.  The original `users.properties` file and it's corresponding implementation are deprecated.  \r
+This user service implementation allows for serialization and deserialization of more sophisticated Gitblit User objects and will open the door for more advanced Gitblit features. For upgrading installations, a `users.conf` file will automatically be created for you from your existing `users.properties` file on your first launch of Gitblit.  You will have to manually set *realm.userService=users.conf* to switch to the new user service.  \r
+The original `users.properties` file and it's corresponding implementation are **deprecated**.  \r
     **New:** *realm.userService = users.conf*\r
 - added: Teams for specifying user-repository access in bulk\r
 - added: Gitblit Express bundle to get started running Gitblit on RedHat's OpenShift cloud\r
@@ -25,9 +27,9 @@ This user service implementation allows for serialization and deserialization of
    **New:** *web.datestampLongFormat = EEEE, MMMM d, yyyy*  \r
 - fixed: several a bugs in FileUserService related to cleaning up old repository permissions on a rename or delete\r
 - added: optional flash-based 1-step *copy to clipboard* of the primary repository url\r
-- added: javascript-based 3-step (click, ctrl+c, enter) *copy to clipboard* of the primary repository url\r
+- added: javascript-based 3-step (click, ctrl+c, enter) *copy to clipboard* of the primary repository url  \r
    **New:** *web.allowFlashCopyToClipboard = true*  \r
-- improved: empty repositories now link to the *empty repository* page which gives some direction to the user for the next step in using Gitblit.  This page displays the primary push/clone url of the repository and gives sample syntax for the git command-line client. (issue 31)\r
+- improved: empty repositories now link to a new *empty repository* page which gives some direction to the user for the next step in using Gitblit.  This page displays the primary push/clone url of the repository and gives sample syntax for the git command-line client. (issue 31)\r
 - improved: unit testing framework has been migrated to JUnit4 syntax and the test suite has been redesigned to run all unit tests, including rpc, federation, and git push/clone tests\r
 \r
 ### Older Releases\r
diff --git a/groovy/sendemail.groovy b/groovy/sendemail.groovy
deleted file mode 100644 (file)
index 69e2b93..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-/*\r
- * Copyright 2011 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-import com.gitblit.GitBlit\r
-import com.gitblit.Keys\r
-import com.gitblit.models.RepositoryModel\r
-import com.gitblit.models.UserModel\r
-import com.gitblit.utils.JGitUtils\r
-import org.eclipse.jgit.lib.Repository\r
-import org.eclipse.jgit.lib.Config\r
-import org.eclipse.jgit.revwalk.RevCommit\r
-import org.eclipse.jgit.transport.ReceiveCommand\r
-import org.eclipse.jgit.transport.ReceiveCommand.Result\r
-import org.slf4j.Logger\r
-\r
-/**\r
- * Sample Gitblit Post-Receive Hook: sendemail\r
- *\r
- * The Post-Receive hook is executed AFTER the pushed commits have been applied\r
- * to the Git repository.  This is the appropriate point to trigger an\r
- * integration build or to send a notification.\r
- * \r
- * This script is only executed when pushing to *Gitblit*, not to other Git\r
- * tooling you may be using.\r
- * \r
- * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties\r
- * or web.xml then it will be executed by any repository when it receives a\r
- * push.  If you choose to share your script then you may have to consider\r
- * tailoring control-flow based on repository access restrictions.\r
- *\r
- * Scripts may also be specified per-repository in the repository settings page.\r
- * Shared scripts will be excluded from this list of available scripts.\r
- * \r
- * This script is dynamically reloaded and it is executed within it's own\r
- * exception handler so it will not crash another script nor crash Gitblit.\r
- *\r
- * If you want this hook script to fail and abort all subsequent scripts in the\r
- * chain, "return false" at the appropriate failure points.\r
- * \r
- * Bound Variables:\r
- *  gitblit            Gitblit Server                  com.gitblit.GitBlit\r
- *  repository Gitblit Repository              com.gitblit.models.RepositoryModel\r
- *  user               Gitblit User                    com.gitblit.models.UserModel\r
- *  commands   JGit commands                   Collection<org.eclipse.jgit.transport.ReceiveCommand>\r
- *     url                     Base url for Gitblit    String\r
- *  logger             Logger instance                 org.slf4j.Logger\r
- *  \r
- */\r
-\r
-// Indicate we have started the script\r
-logger.info("sendemail hook triggered by ${user.username} for ${repository.name}")\r
-\r
-/*\r
- * Primitive example email notification with example repository-specific checks.\r
- * This requires the mail settings to be properly configured in Gitblit.\r
- */\r
-\r
-Repository r = gitblit.getRepository(repository.name)\r
-\r
-// reuse some existing repository config settings, if available\r
-Config config = r.getConfig()\r
-def mailinglist = config.getString('hooks', null, 'mailinglist')\r
-def emailprefix = config.getString('hooks', null, 'emailprefix')\r
-\r
-// set default values\r
-def toAddresses = []\r
-if (emailprefix == null)\r
-emailprefix = '[Gitblit]'\r
-\r
-if (mailinglist != null) {\r
-       def addrs = mailinglist.split('(,|\\s)')\r
-       toAddresses.addAll(addrs)\r
-}\r
-\r
-// add all mailing lists defined in gitblit.properties or web.xml\r
-toAddresses.addAll(gitblit.getStrings(Keys.mail.mailingLists))\r
-\r
-// add all mail recipients for the repository\r
-toAddresses.addAll(repository.mailRecipients)\r
-\r
-// special custom cases\r
-switch(repository.name) {\r
-       case 'ex@mple.git':\r
-               toAddresses.add 'dev-team@somewhere.com'\r
-               toAddresses.add 'qa-team@somewhere.com'\r
-               break\r
-}\r
-\r
-// define the summary and commit urls\r
-def repo = repository.name.replace('/', gitblit.getString(Keys.web.forwardSlashCharacter, '/'))\r
-def summaryUrl\r
-def commitUrl\r
-if (gitblit.getBoolean(Keys.web.mountParameters, true)) {      \r
-       summaryUrl = url + "/summary/$repo"\r
-       commitUrl = url + "/commit/$repo/"\r
-} else {\r
-       summaryUrl = url + "/summary?r=$repo"\r
-       commitUrl = url + "/commit?r=$repo&h="\r
-}\r
-\r
-// construct a simple text summary of the changes contained in the push\r
-def commitCount = 0\r
-def changes = ''\r
-def table = { it.authorIdent.name.padRight(25, ' ') + it.shortMessage + "\n$commitUrl" + it.id.name }\r
-for (command in commands) {\r
-       def ref = command.refName.substring('refs/heads/'.length())\r
-       switch (command.type) {\r
-               case ReceiveCommand.Type.CREATE:\r
-                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
-                       commitCount += commits.size()\r
-                       // new branch commits table\r
-                       changes += "created $ref ($commits.size commits)\n\n"\r
-                       changes += commits.collect(table).join('\n\n')\r
-                       changes += '\n'\r
-                       break\r
-               case ReceiveCommand.Type.UPDATE:\r
-                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
-                       commitCount += commits.size()\r
-                       // fast-forward branch commits table\r
-                       changes += "updated $ref ($commits.size commits)\n\n"\r
-                       changes += commits.collect(table).join('\n\n')\r
-                       changes += '\n'\r
-                       break\r
-               case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:\r
-                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
-                       commitCount += commits.size()\r
-                       // non-fast-forward branch commits table\r
-                       changes += "updated $ref [NON fast-forward] ($commits.size commits)\n\n"\r
-                       changes += commits.collect(table).join('\n\n')\r
-                       changes += '\n'\r
-                       break\r
-               case ReceiveCommand.Type.DELETE:\r
-                       // deleted branch\r
-                       changes += "deleted $ref\n\n"\r
-                       break\r
-               default:\r
-                       break\r
-       }\r
-}\r
-// close the repository reference\r
-r.close()\r
-\r
-// tell Gitblit to send the message (Gitblit filters duplicate addresses)\r
-gitblit.sendEmail("$emailprefix $user.username pushed $commitCount commits => $repository.name", "$summaryUrl\n\n$changes", toAddresses)
\ No newline at end of file
diff --git a/groovy/sendmail.groovy b/groovy/sendmail.groovy
new file mode 100644 (file)
index 0000000..b43f9de
--- /dev/null
@@ -0,0 +1,154 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+import com.gitblit.GitBlit\r
+import com.gitblit.Keys\r
+import com.gitblit.models.RepositoryModel\r
+import com.gitblit.models.UserModel\r
+import com.gitblit.utils.JGitUtils\r
+import org.eclipse.jgit.lib.Repository\r
+import org.eclipse.jgit.lib.Config\r
+import org.eclipse.jgit.revwalk.RevCommit\r
+import org.eclipse.jgit.transport.ReceiveCommand\r
+import org.eclipse.jgit.transport.ReceiveCommand.Result\r
+import org.slf4j.Logger\r
+\r
+/**\r
+ * Sample Gitblit Post-Receive Hook: sendmail\r
+ *\r
+ * The Post-Receive hook is executed AFTER the pushed commits have been applied\r
+ * to the Git repository.  This is the appropriate point to trigger an\r
+ * integration build or to send a notification.\r
+ * \r
+ * This script is only executed when pushing to *Gitblit*, not to other Git\r
+ * tooling you may be using.\r
+ * \r
+ * If this script is specified in *groovy.postReceiveScripts* of gitblit.properties\r
+ * or web.xml then it will be executed by any repository when it receives a\r
+ * push.  If you choose to share your script then you may have to consider\r
+ * tailoring control-flow based on repository access restrictions.\r
+ *\r
+ * Scripts may also be specified per-repository in the repository settings page.\r
+ * Shared scripts will be excluded from this list of available scripts.\r
+ * \r
+ * This script is dynamically reloaded and it is executed within it's own\r
+ * exception handler so it will not crash another script nor crash Gitblit.\r
+ *\r
+ * If you want this hook script to fail and abort all subsequent scripts in the\r
+ * chain, "return false" at the appropriate failure points.\r
+ * \r
+ * Bound Variables:\r
+ *  gitblit            Gitblit Server                  com.gitblit.GitBlit\r
+ *  repository Gitblit Repository              com.gitblit.models.RepositoryModel\r
+ *  user               Gitblit User                    com.gitblit.models.UserModel\r
+ *  commands   JGit commands                   Collection<org.eclipse.jgit.transport.ReceiveCommand>\r
+ *     url                     Base url for Gitblit    String\r
+ *  logger             Logger instance                 org.slf4j.Logger\r
+ *  \r
+ */\r
+\r
+// Indicate we have started the script\r
+logger.info("sendmail hook triggered by ${user.username} for ${repository.name}")\r
+\r
+/*\r
+ * Primitive email notification.\r
+ * This requires the mail settings to be properly configured in Gitblit.\r
+ */\r
+\r
+Repository r = gitblit.getRepository(repository.name)\r
+\r
+// reuse existing repository config settings, if available\r
+Config config = r.getConfig()\r
+def mailinglist = config.getString('hooks', null, 'mailinglist')\r
+def emailprefix = config.getString('hooks', null, 'emailprefix')\r
+\r
+// set default values\r
+def toAddresses = []\r
+if (emailprefix == null)\r
+emailprefix = '[Gitblit]'\r
+\r
+if (mailinglist != null) {\r
+       def addrs = mailinglist.split(/(,|\s)/)\r
+       toAddresses.addAll(addrs)\r
+}\r
+\r
+// add all mailing lists defined in gitblit.properties or web.xml\r
+toAddresses.addAll(gitblit.getStrings(Keys.mail.mailingLists))\r
+\r
+// add all mailing lists for the repository\r
+toAddresses.addAll(repository.mailingLists)\r
+\r
+// define the summary and commit urls\r
+def repo = repository.name.replace('/', gitblit.getString(Keys.web.forwardSlashCharacter, '/'))\r
+def summaryUrl\r
+def commitUrl\r
+if (gitblit.getBoolean(Keys.web.mountParameters, true)) {      \r
+       summaryUrl = url + "/summary/$repo"\r
+       commitUrl = url + "/commit/$repo/"\r
+} else {\r
+       summaryUrl = url + "/summary?r=$repo"\r
+       commitUrl = url + "/commit?r=$repo&h="\r
+}\r
+\r
+// construct a simple text summary of the changes contained in the push\r
+def commitCount = 0\r
+def changes = ''\r
+def table = { it.authorIdent.name.padRight(25, ' ') + it.shortMessage + "\n$commitUrl" + it.id.name }\r
+for (command in commands) {\r
+       def ref = command.refName\r
+       if (ref.startsWith('refs/heads/')) {\r
+               ref  = command.refName.substring('refs/heads/'.length())\r
+       } else if (ref.startsWith('refs/tags/')) {\r
+               ref  = command.refName.substring('refs/tags/'.length())\r
+       }\r
+               \r
+       switch (command.type) {\r
+               case ReceiveCommand.Type.CREATE:\r
+                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
+                       commitCount += commits.size()\r
+                       // new branch commits table\r
+                       changes += "$ref created ($commits.size commits)\n\n"\r
+                       changes += commits.collect(table).join('\n\n')\r
+                       changes += '\n'\r
+                       break\r
+               case ReceiveCommand.Type.UPDATE:\r
+                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
+                       commitCount += commits.size()\r
+                       // fast-forward branch commits table\r
+                       changes += "$ref updated ($commits.size commits)\n\n"\r
+                       changes += commits.collect(table).join('\n\n')\r
+                       changes += '\n'\r
+                       break\r
+               case ReceiveCommand.Type.UPDATE_NONFASTFORWARD:\r
+                       def commits = JGitUtils.getRevLog(r, command.oldId.name, command.newId.name)\r
+                       commitCount += commits.size()\r
+                       // non-fast-forward branch commits table\r
+                       changes += "$ref updated [NON fast-forward] ($commits.size commits)\n\n"\r
+                       changes += commits.collect(table).join('\n\n')\r
+                       changes += '\n'\r
+                       break\r
+               case ReceiveCommand.Type.DELETE:\r
+                       // deleted branch\r
+                       changes += "$ref deleted\n\n"\r
+                       break\r
+               default:\r
+                       break\r
+       }\r
+}\r
+// close the repository reference\r
+r.close()\r
+\r
+// tell Gitblit to send the message (Gitblit filters duplicate addresses)\r
+gitblit.sendMail("$emailprefix $user.username pushed $commitCount commits => $repository.name", "$summaryUrl\n\n$changes", toAddresses)
\ No newline at end of file
index 6eeec389a2b34315c7cdeb3c8263e88f2949673d..08951f2a87ea9fe04b6f6d4412ec76c8cd9ee5d5 100644 (file)
@@ -690,6 +690,10 @@ td.treeLinks {
        width: 13em;\r
 }\r
 \r
+span.help-inline {\r
+       color: #777;\r
+}\r
+\r
 span.metricsTitle {\r
        font-size: 2em;\r
 }\r
index c3b7d8b800c57b83063bacef1c36652017d51d5b..2976c402758b085945430e3dd33d5669a07a114b 100644 (file)
@@ -113,7 +113,7 @@ public class FederationPullExecutor implements Runnable {
                                                String message = "Federation pull of " + registration.name + " @ "\r
                                                                + registration.url + " is now at " + is.name();\r
                                                GitBlit.self()\r
-                                                               .sendEmailToAdministrators(\r
+                                                               .sendMailToAdministrators(\r
                                                                                "Pull Status of " + registration.name + " is " + is.name(),\r
                                                                                message);\r
                                        }\r
index f0122791fb9ac18bccb5e44f53c1a5278d70dcb3..835aa132f9f9569e451d038145747835922d26f4 100644 (file)
@@ -743,8 +743,8 @@ public class GitBlit implements ServletContextListener {
                                        "gitblit", null, "preReceiveScript")));\r
                        model.postReceiveScripts = new ArrayList<String>(Arrays.asList(config.getStringList(\r
                                        "gitblit", null, "postReceiveScript")));\r
-                       model.mailRecipients = new ArrayList<String>(Arrays.asList(config.getStringList(\r
-                                       "gitblit", null, "mailRecipient")));\r
+                       model.mailingLists = new ArrayList<String>(Arrays.asList(config.getStringList(\r
+                                       "gitblit", null, "mailingList")));\r
                }\r
                r.close();\r
                return model;\r
@@ -971,8 +971,8 @@ public class GitBlit implements ServletContextListener {
                        config.setStringList("gitblit", null, "postReceiveScript",\r
                                        repository.postReceiveScripts);\r
                }\r
-               if (repository.mailRecipients != null) {\r
-                       config.setStringList("gitblit", null, "mailRecipient", repository.mailRecipients);\r
+               if (repository.mailingLists != null) {\r
+                       config.setStringList("gitblit", null, "mailingList", repository.mailingLists);\r
                }\r
                try {\r
                        config.save();\r
@@ -1485,7 +1485,7 @@ public class GitBlit implements ServletContextListener {
         * @param subject\r
         * @param message\r
         */\r
-       public void sendEmailToAdministrators(String subject, String message) {\r
+       public void sendMailToAdministrators(String subject, String message) {\r
                try {\r
                        Message mail = mailExecutor.createMessageForAdministrators();\r
                        if (mail != null) {\r
@@ -1505,8 +1505,8 @@ public class GitBlit implements ServletContextListener {
         * @param message\r
         * @param toAddresses\r
         */\r
-       public void sendEmail(String subject, String message, ArrayList<String> toAddresses) {\r
-               this.sendEmail(subject, message, toAddresses.toArray(new String[0]));\r
+       public void sendMail(String subject, String message, ArrayList<String> toAddresses) {\r
+               this.sendMail(subject, message, toAddresses.toArray(new String[0]));\r
        }\r
 \r
        /**\r
@@ -1516,7 +1516,7 @@ public class GitBlit implements ServletContextListener {
         * @param message\r
         * @param toAddresses\r
         */\r
-       public void sendEmail(String subject, String message, String... toAddresses) {\r
+       public void sendMail(String subject, String message, String... toAddresses) {\r
                try {\r
                        Message mail = mailExecutor.createMessage(toAddresses);\r
                        if (mail != null) {\r
@@ -1634,11 +1634,7 @@ public class GitBlit implements ServletContextListener {
                                loginService = (IUserService) realmClass.newInstance();\r
                        }\r
                } catch (Throwable t) {\r
-                       loginService = new UserServiceWrapper() {\r
-                               @Override\r
-                               public void setupService(IStoredSettings settings) {\r
-                               }\r
-                       };\r
+                       loginService = new GitblitUserService();\r
                }\r
                setUserService(loginService);\r
                mailExecutor = new MailExecutor(settings);\r
diff --git a/src/com/gitblit/GitblitUserService.java b/src/com/gitblit/GitblitUserService.java
new file mode 100644 (file)
index 0000000..97e1a40
--- /dev/null
@@ -0,0 +1,217 @@
+/*\r
+ * Copyright 2011 gitblit.com.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *     http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+package com.gitblit;\r
+\r
+import java.io.File;\r
+import java.io.IOException;\r
+import java.text.MessageFormat;\r
+import java.util.List;\r
+\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+import com.gitblit.models.TeamModel;\r
+import com.gitblit.models.UserModel;\r
+\r
+/**\r
+ * This class wraps the default user service and is recommended as the starting\r
+ * point for custom user service implementations.\r
+ * \r
+ * This does seem a little convoluted, but the idea is to allow IUserService to\r
+ * evolve with new methods and implementations without breaking custom\r
+ * authentication implementations.\r
+ * \r
+ * The most common implementation of a custom IUserService is to only override\r
+ * authentication and then delegate all other functionality to one of Gitblit's\r
+ * user services. This class optimizes that use-case.\r
+ * \r
+ * Extending GitblitUserService allows for authentication customization without\r
+ * having to keep-up-with IUSerService API changes.\r
+ * \r
+ * @author James Moger\r
+ * \r
+ */\r
+public class GitblitUserService implements IUserService {\r
+\r
+       protected IUserService serviceImpl;\r
+\r
+       private final Logger logger = LoggerFactory.getLogger(GitblitUserService.class);\r
+\r
+       public GitblitUserService() {\r
+       }\r
+\r
+       @Override\r
+       public void setup(IStoredSettings settings) {\r
+               File realmFile = GitBlit.getFileOrFolder(Keys.realm.userService, "users.conf");\r
+               serviceImpl = createUserService(realmFile);\r
+       }\r
+\r
+       @SuppressWarnings("deprecation")\r
+       protected IUserService createUserService(File realmFile) {\r
+               IUserService service = null;\r
+               if (realmFile.getName().toLowerCase().endsWith(".properties")) {\r
+                       // v0.5.0 - v0.7.0 properties-based realm file\r
+                       service = new FileUserService(realmFile);\r
+               } else if (realmFile.getName().toLowerCase().endsWith(".conf")) {\r
+                       // v0.8.0+ config-based realm file\r
+                       service = new ConfigUserService(realmFile);\r
+               }\r
+\r
+               assert service != null;\r
+\r
+               if (realmFile.exists()) {\r
+                       // Create the Administrator account for a new realm file\r
+                       try {\r
+                               realmFile.createNewFile();\r
+                       } catch (IOException x) {\r
+                               logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmFile), x);\r
+                       }\r
+                       UserModel admin = new UserModel("admin");\r
+                       admin.password = "admin";\r
+                       admin.canAdmin = true;\r
+                       admin.excludeFromFederation = true;\r
+                       service.updateUserModel(admin);\r
+               }\r
+\r
+               if (service instanceof FileUserService) {\r
+                       // automatically create a users.conf realm file from the original\r
+                       // users.properties file\r
+                       File usersConfig = new File(realmFile.getParentFile(), "users.conf");\r
+                       if (!usersConfig.exists()) {\r
+                               logger.info(MessageFormat.format("Automatically creating {0} based on {1}",\r
+                                               usersConfig.getAbsolutePath(), realmFile.getAbsolutePath()));\r
+                               ConfigUserService configService = new ConfigUserService(usersConfig);\r
+                               for (String username : serviceImpl.getAllUsernames()) {\r
+                                       UserModel userModel = serviceImpl.getUserModel(username);\r
+                                       configService.updateUserModel(userModel);\r
+                               }\r
+                       }\r
+                       // issue suggestion about switching to users.conf\r
+                       logger.warn("Please consider using \"users.conf\" instead of the deprecated \"users.properties\" file");\r
+               }\r
+               return service;\r
+       }\r
+\r
+       @Override\r
+       public boolean supportsCookies() {\r
+               return serviceImpl.supportsCookies();\r
+       }\r
+\r
+       @Override\r
+       public char[] getCookie(UserModel model) {\r
+               return serviceImpl.getCookie(model);\r
+       }\r
+\r
+       @Override\r
+       public UserModel authenticate(char[] cookie) {\r
+               return serviceImpl.authenticate(cookie);\r
+       }\r
+\r
+       @Override\r
+       public UserModel authenticate(String username, char[] password) {\r
+               return serviceImpl.authenticate(username, password);\r
+       }\r
+\r
+       @Override\r
+       public UserModel getUserModel(String username) {\r
+               return serviceImpl.getUserModel(username);\r
+       }\r
+\r
+       @Override\r
+       public boolean updateUserModel(UserModel model) {\r
+               return serviceImpl.updateUserModel(model);\r
+       }\r
+\r
+       @Override\r
+       public boolean updateUserModel(String username, UserModel model) {\r
+               return serviceImpl.updateUserModel(username, model);\r
+       }\r
+\r
+       @Override\r
+       public boolean deleteUserModel(UserModel model) {\r
+               return serviceImpl.deleteUserModel(model);\r
+       }\r
+\r
+       @Override\r
+       public boolean deleteUser(String username) {\r
+               return serviceImpl.deleteUser(username);\r
+       }\r
+\r
+       @Override\r
+       public List<String> getAllUsernames() {\r
+               return serviceImpl.getAllUsernames();\r
+       }\r
+\r
+       @Override\r
+       public List<String> getAllTeamNames() {\r
+               return serviceImpl.getAllTeamNames();\r
+       }\r
+\r
+       @Override\r
+       public List<String> getTeamnamesForRepositoryRole(String role) {\r
+               return serviceImpl.getTeamnamesForRepositoryRole(role);\r
+       }\r
+\r
+       @Override\r
+       public boolean setTeamnamesForRepositoryRole(String role, List<String> teamnames) {\r
+               return serviceImpl.setTeamnamesForRepositoryRole(role, teamnames);\r
+       }\r
+\r
+       @Override\r
+       public TeamModel getTeamModel(String teamname) {\r
+               return serviceImpl.getTeamModel(teamname);\r
+       }\r
+\r
+       @Override\r
+       public boolean updateTeamModel(TeamModel model) {\r
+               return serviceImpl.updateTeamModel(model);\r
+       }\r
+\r
+       @Override\r
+       public boolean updateTeamModel(String teamname, TeamModel model) {\r
+               return serviceImpl.updateTeamModel(teamname, model);\r
+       }\r
+\r
+       @Override\r
+       public boolean deleteTeamModel(TeamModel model) {\r
+               return serviceImpl.deleteTeamModel(model);\r
+       }\r
+\r
+       @Override\r
+       public boolean deleteTeam(String teamname) {\r
+               return serviceImpl.deleteTeam(teamname);\r
+       }\r
+\r
+       @Override\r
+       public List<String> getUsernamesForRepositoryRole(String role) {\r
+               return serviceImpl.getUsernamesForRepositoryRole(role);\r
+       }\r
+\r
+       @Override\r
+       public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {\r
+               return serviceImpl.setUsernamesForRepositoryRole(role, usernames);\r
+       }\r
+\r
+       @Override\r
+       public boolean renameRepositoryRole(String oldRole, String newRole) {\r
+               return serviceImpl.renameRepositoryRole(oldRole, newRole);\r
+       }\r
+\r
+       @Override\r
+       public boolean deleteRepositoryRole(String role) {\r
+               return serviceImpl.deleteRepositoryRole(role);\r
+       }\r
+}\r
diff --git a/src/com/gitblit/UserServiceWrapper.java b/src/com/gitblit/UserServiceWrapper.java
deleted file mode 100644 (file)
index 88eab48..0000000
+++ /dev/null
@@ -1,221 +0,0 @@
-/*\r
- * Copyright 2011 gitblit.com.\r
- *\r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- *\r
- *     http://www.apache.org/licenses/LICENSE-2.0\r
- *\r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-package com.gitblit;\r
-\r
-import java.io.File;\r
-import java.io.IOException;\r
-import java.text.MessageFormat;\r
-import java.util.List;\r
-\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-import com.gitblit.models.TeamModel;\r
-import com.gitblit.models.UserModel;\r
-\r
-/**\r
- * This class wraps the default user service and is recommended as the starting\r
- * point for custom user service implementations.\r
- * \r
- * This does seem a little convoluted, but the idea is to allow IUserService to\r
- * evolve and be replaced without hampering custom implementations.\r
- * \r
- * The most common need for a custom IUserService is to override authentication\r
- * and then delegate to one of Gitblit's user services. Subclassing this allows\r
- * for authentication customization without having to keep-up-with IUSerService\r
- * API changes.\r
- * \r
- * @author James Moger\r
- * \r
- */\r
-public abstract class UserServiceWrapper implements IUserService {\r
-\r
-       protected IUserService defaultService;\r
-\r
-       private final Logger logger = LoggerFactory.getLogger(UserServiceWrapper.class);\r
-\r
-       public UserServiceWrapper() {\r
-       }\r
-\r
-       @SuppressWarnings("deprecation")\r
-       @Override\r
-       public final void setup(IStoredSettings settings) {\r
-               File realmFile = GitBlit.getFileOrFolder(Keys.realm.userService, "users.conf");\r
-               if (realmFile.exists()) {\r
-                       // load the existing realm file\r
-                       if (realmFile.getName().toLowerCase().endsWith(".properties")) {\r
-                               // load the v0.5.0 - v0.7.0 properties-based realm file\r
-                               defaultService = new FileUserService(realmFile);\r
-\r
-                               // automatically create a users.conf realm file from the\r
-                               // original users.properties file\r
-                               File usersConfig = new File(realmFile.getParentFile(), "users.conf");\r
-                               if (!usersConfig.exists()) {\r
-                                       logger.info(MessageFormat.format("Automatically creating {0} based on {1}",\r
-                                                       usersConfig.getAbsolutePath(), realmFile.getAbsolutePath()));\r
-                                       ConfigUserService configService = new ConfigUserService(usersConfig);\r
-                                       for (String username : defaultService.getAllUsernames()) {\r
-                                               UserModel userModel = defaultService.getUserModel(username);\r
-                                               configService.updateUserModel(userModel);\r
-                                       }\r
-                               }\r
-\r
-                               // issue suggestion about switching to users.conf\r
-                               logger.warn("Please consider using \"users.conf\" instead of the deprecated \"users.properties\" file");\r
-                       } else if (realmFile.getName().toLowerCase().endsWith(".conf")) {\r
-                               // load the config-based realm file\r
-                               defaultService = new ConfigUserService(realmFile);\r
-                       }\r
-               } else {\r
-                       // Create a new realm file and add the default admin\r
-                       // account. This is necessary for bootstrapping a dynamic\r
-                       // environment like running on a cloud service.\r
-                       // As of v0.8.0 the default realm file is ConfigUserService.\r
-                       try {\r
-                               realmFile = GitBlit.getFileOrFolder(Keys.realm.userService, "users.conf");\r
-                               realmFile.createNewFile();\r
-                               defaultService = new ConfigUserService(realmFile);\r
-                               UserModel admin = new UserModel("admin");\r
-                               admin.password = "admin";\r
-                               admin.canAdmin = true;\r
-                               admin.excludeFromFederation = true;\r
-                               defaultService.updateUserModel(admin);\r
-                       } catch (IOException x) {\r
-                               logger.error(MessageFormat.format("COULD NOT CREATE REALM FILE {0}!", realmFile), x);\r
-                       }\r
-               }\r
-\r
-               // call subclass setup\r
-               setupService(settings);\r
-       }\r
-\r
-       /**\r
-        * Subclasses must implement this method.\r
-        * \r
-        * @param settings\r
-        */\r
-       public abstract void setupService(IStoredSettings settings);\r
-\r
-       @Override\r
-       public boolean supportsCookies() {\r
-               return defaultService.supportsCookies();\r
-       }\r
-\r
-       @Override\r
-       public char[] getCookie(UserModel model) {\r
-               return defaultService.getCookie(model);\r
-       }\r
-\r
-       @Override\r
-       public UserModel authenticate(char[] cookie) {\r
-               return defaultService.authenticate(cookie);\r
-       }\r
-\r
-       @Override\r
-       public UserModel authenticate(String username, char[] password) {\r
-               return defaultService.authenticate(username, password);\r
-       }\r
-\r
-       @Override\r
-       public UserModel getUserModel(String username) {\r
-               return defaultService.getUserModel(username);\r
-       }\r
-\r
-       @Override\r
-       public boolean updateUserModel(UserModel model) {\r
-               return defaultService.updateUserModel(model);\r
-       }\r
-\r
-       @Override\r
-       public boolean updateUserModel(String username, UserModel model) {\r
-               return defaultService.updateUserModel(username, model);\r
-       }\r
-\r
-       @Override\r
-       public boolean deleteUserModel(UserModel model) {\r
-               return defaultService.deleteUserModel(model);\r
-       }\r
-\r
-       @Override\r
-       public boolean deleteUser(String username) {\r
-               return defaultService.deleteUser(username);\r
-       }\r
-\r
-       @Override\r
-       public List<String> getAllUsernames() {\r
-               return defaultService.getAllUsernames();\r
-       }\r
-\r
-       @Override\r
-       public List<String> getAllTeamNames() {\r
-               return defaultService.getAllTeamNames();\r
-       }\r
-\r
-       @Override\r
-       public List<String> getTeamnamesForRepositoryRole(String role) {\r
-               return defaultService.getTeamnamesForRepositoryRole(role);\r
-       }\r
-\r
-       @Override\r
-       public boolean setTeamnamesForRepositoryRole(String role, List<String> teamnames) {\r
-               return defaultService.setTeamnamesForRepositoryRole(role, teamnames);\r
-       }\r
-\r
-       @Override\r
-       public TeamModel getTeamModel(String teamname) {\r
-               return defaultService.getTeamModel(teamname);\r
-       }\r
-\r
-       @Override\r
-       public boolean updateTeamModel(TeamModel model) {\r
-               return defaultService.updateTeamModel(model);\r
-       }\r
-\r
-       @Override\r
-       public boolean updateTeamModel(String teamname, TeamModel model) {\r
-               return defaultService.updateTeamModel(teamname, model);\r
-       }\r
-\r
-       @Override\r
-       public boolean deleteTeamModel(TeamModel model) {\r
-               return defaultService.deleteTeamModel(model);\r
-       }\r
-\r
-       @Override\r
-       public boolean deleteTeam(String teamname) {\r
-               return defaultService.deleteTeam(teamname);\r
-       }\r
-\r
-       @Override\r
-       public List<String> getUsernamesForRepositoryRole(String role) {\r
-               return defaultService.getUsernamesForRepositoryRole(role);\r
-       }\r
-\r
-       @Override\r
-       public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {\r
-               return defaultService.setUsernamesForRepositoryRole(role, usernames);\r
-       }\r
-\r
-       @Override\r
-       public boolean renameRepositoryRole(String oldRole, String newRole) {\r
-               return defaultService.renameRepositoryRole(oldRole, newRole);\r
-       }\r
-\r
-       @Override\r
-       public boolean deleteRepositoryRole(String role) {\r
-               return defaultService.deleteRepositoryRole(role);\r
-       }\r
-}\r
index 44b6fc6a01129320b751cda62426ffc1152f0509..b72786233334899be71967db797f5a538611c2cd 100644 (file)
@@ -89,7 +89,7 @@ public class EditRepositoryDialog extends JDialog {
 \r
        private JCheckBox isFrozen;\r
 \r
-       private JTextField mailRecipientsField;\r
+       private JTextField mailingListsField;\r
 \r
        private JComboBox accessRestriction;\r
 \r
@@ -164,8 +164,8 @@ public class EditRepositoryDialog extends JDialog {
                                anRepository.skipSummaryMetrics);\r
                isFrozen = new JCheckBox(Translation.get("gb.isFrozenDescription"), anRepository.isFrozen);\r
 \r
-               mailRecipientsField = new JTextField(anRepository.mailRecipients == null ? ""\r
-                               : StringUtils.flattenStrings(anRepository.mailRecipients, " "), 50);\r
+               mailingListsField = new JTextField(anRepository.mailingLists == null ? ""\r
+                               : StringUtils.flattenStrings(anRepository.mailingLists, " "), 50);\r
 \r
                accessRestriction = new JComboBox(AccessRestrictionType.values());\r
                accessRestriction.setRenderer(new AccessRestrictionRenderer());\r
@@ -198,7 +198,7 @@ public class EditRepositoryDialog extends JDialog {
                fieldsPanel\r
                                .add(newFieldPanel(Translation.get("gb.skipSummaryMetrics"), skipSummaryMetrics));\r
                fieldsPanel.add(newFieldPanel(Translation.get("gb.isFrozen"), isFrozen));\r
-               fieldsPanel.add(newFieldPanel(Translation.get("gb.mailRecipients"), mailRecipientsField));\r
+               fieldsPanel.add(newFieldPanel(Translation.get("gb.mailingLists"), mailingListsField));\r
 \r
                usersPalette = new JPalette<String>();\r
                JPanel accessPanel = new JPanel(new BorderLayout(5, 5));\r
@@ -371,8 +371,17 @@ public class EditRepositoryDialog extends JDialog {
                repository.skipSummaryMetrics = skipSummaryMetrics.isSelected();\r
                repository.isFrozen = isFrozen.isSelected();\r
 \r
-               repository.mailRecipients = StringUtils.getStringsFromValue(mailRecipientsField.getText()\r
-                               .trim(), " ");\r
+               String ml = mailingListsField.getText();\r
+               if (!StringUtils.isEmpty(ml)) {\r
+                       Set<String> list = new HashSet<String>();\r
+                       for (String address : ml.split("(,|\\s)")) {\r
+                               if (StringUtils.isEmpty(address)) {\r
+                                       continue;\r
+                               }\r
+                               list.add(address.toLowerCase());\r
+                       }\r
+                       repository.mailingLists = new ArrayList<String>(list);\r
+               }\r
 \r
                repository.accessRestriction = (AccessRestrictionType) accessRestriction.getSelectedItem();\r
                repository.federationStrategy = (FederationStrategy) federationStrategy.getSelectedItem();\r
index fc1de8acd16301e61def9206e416d19bab04c364..7e33ab062b63a89a8d76aa1922af08c095aebdfb 100644 (file)
@@ -57,7 +57,7 @@ public class RepositoryModel implements Serializable, Comparable<RepositoryModel
        public String size;\r
        public List<String> preReceiveScripts;\r
        public List<String> postReceiveScripts;\r
-       public List<String> mailRecipients;\r
+       public List<String> mailingLists;\r
 \r
        public RepositoryModel() {\r
                this("", "", "", new Date(0));\r
index 4eeb887c6e36c9de074d18302d109f5e6356a854..c0b0010d56a9b1cd4b5cdc293f8794a6b6e521d7 100644 (file)
@@ -196,8 +196,8 @@ gb.newTeam = new team
 gb.permittedTeams = permitted teams\r
 gb.emptyRepository = empty repository\r
 gb.repositoryUrl = repository url\r
-gb.mailRecipients = mail recipients\r
-gb.mailRecipientsDescription = space-delimited, used by sendemail Groovy hook\r
+gb.mailingLists = mailing lists\r
+gb.mailingListsDescription = used by the sendmail hook\r
 gb.preReceiveScripts = pre-receive scripts\r
 gb.postReceiveScripts = post-receive scripts\r
-gb.groovyHookScripts = hook scripts
\ No newline at end of file
+gb.hookScripts = hook scripts
\ No newline at end of file
index 3e2212251d163a152fcbc33d68c4e5973278d1d6..310f59e5bba3db18fc77c4748f61d56f37b24a6c 100644 (file)
                <table class="plain">\r
                        <tbody class="settings">\r
                                <tr><td colspan="2"><h3><wicket:message key="gb.general"></wicket:message></h3></td></tr>\r
-                               <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input class="span6" type="text" wicket:id="name" id="name" size="40" tabindex="1" /> &nbsp;<i><wicket:message key="gb.nameDescription"></wicket:message></i></td></tr>\r
+                               <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input class="span6" type="text" wicket:id="name" id="name" size="40" tabindex="1" /> &nbsp;<span class="help-inline"><wicket:message key="gb.nameDescription"></wicket:message></span></td></tr>\r
                                <tr><th><wicket:message key="gb.description"></wicket:message></th><td class="edit"><input class="span6" type="text" wicket:id="description" size="40" tabindex="2" /></td></tr>\r
                                <tr><th><wicket:message key="gb.origin"></wicket:message></th><td class="edit"><input class="span7" type="text" wicket:id="origin" size="80" tabindex="3" /></td></tr>\r
-                               <tr><th><wicket:message key="gb.owner"></wicket:message></th><td class="edit"><select wicket:id="owner" tabindex="4" /> &nbsp;<i><wicket:message key="gb.ownerDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useTickets" tabindex="5" /> &nbsp;<i><wicket:message key="gb.useTicketsDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> &nbsp;<i><wicket:message key="gb.useDocsDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.showRemoteBranches"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="showRemoteBranches" tabindex="7" /> &nbsp;<i><wicket:message key="gb.showRemoteBranchesDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.showReadme"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="showReadme" tabindex="8" /> &nbsp;<i><wicket:message key="gb.showReadmeDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.skipSizeCalculation"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="skipSizeCalculation" tabindex="9" /> &nbsp;<i><wicket:message key="gb.skipSizeCalculationDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.skipSummaryMetrics"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="skipSummaryMetrics" tabindex="10" /> &nbsp;<i><wicket:message key="gb.skipSummaryMetricsDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="isFrozen" tabindex="11" /> &nbsp;<i><wicket:message key="gb.isFrozenDescription"></wicket:message></i></td></tr>\r
-                               <tr><th><wicket:message key="gb.mailRecipients"></wicket:message></th><td class="edit"><input class="span9" type="text" wicket:id="mailRecipients" size="40" tabindex="12" /> &nbsp;<i><wicket:message key="gb.mailRecipientsDescription"></wicket:message></i></td></tr>\r
+                               <tr><th><wicket:message key="gb.owner"></wicket:message></th><td class="edit"><select wicket:id="owner" tabindex="4" /> &nbsp;<span class="help-inline"><wicket:message key="gb.ownerDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.enableTickets"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useTickets" tabindex="5" /> &nbsp;<span class="help-inline"><wicket:message key="gb.useTicketsDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.enableDocs"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="useDocs" tabindex="6" /> &nbsp;<span class="help-inline"><wicket:message key="gb.useDocsDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.showRemoteBranches"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="showRemoteBranches" tabindex="7" /> &nbsp;<span class="help-inline"><wicket:message key="gb.showRemoteBranchesDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.showReadme"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="showReadme" tabindex="8" /> &nbsp;<span class="help-inline"><wicket:message key="gb.showReadmeDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.skipSizeCalculation"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="skipSizeCalculation" tabindex="9" /> &nbsp;<span class="help-inline"><wicket:message key="gb.skipSizeCalculationDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.skipSummaryMetrics"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="skipSummaryMetrics" tabindex="10" /> &nbsp;<span class="help-inline"><wicket:message key="gb.skipSummaryMetricsDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="isFrozen" tabindex="11" /> &nbsp;<span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></td></tr>\r
+                               <tr><th><wicket:message key="gb.mailingLists"></wicket:message></th><td class="edit"><input class="span12" type="text" wicket:id="mailingLists" size="40" tabindex="12" /> &nbsp;<span class="help-inline"><wicket:message key="gb.mailingListsDescription"></wicket:message></span></td></tr>\r
                                <tr><td colspan="2"><h3><wicket:message key="gb.accessRestriction"></wicket:message></h3></td></tr>     \r
                                <tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span6" wicket:id="accessRestriction" tabindex="13" /></td></tr>                                \r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.permittedUsers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>\r
@@ -33,7 +33,7 @@
                                <tr><td colspan="2"><h3><wicket:message key="gb.hookScripts"></wicket:message></h3></td></tr>   \r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.preReceiveScripts"></wicket:message></th><td style="padding:2px;"><span wicket:id="preReceiveScripts"></span></td></tr>\r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.postReceiveScripts"></wicket:message></th><td style="padding:2px;"><span wicket:id="postReceiveScripts"></span></td></tr>\r
-                               <tr><th></th><td class="editButton"><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="15" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="16" /> </td></tr>\r
+                               <tr><td colspan='2'><div class="actions" "><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="15" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="16" /></div></td></tr>\r
                        </tbody>\r
                </table>\r
        </form> \r
index 492addc38eee3abd1d33efca0ef3d3ed5ad3c60d..f595053932602ae8090e740ff09bdb45fb2b3312 100644 (file)
@@ -19,9 +19,11 @@ import java.text.MessageFormat;
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
 import java.util.Collections;\r
+import java.util.HashSet;\r
 import java.util.Iterator;\r
 import java.util.List;\r
 import java.util.Map;\r
+import java.util.Set;\r
 \r
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.extensions.markup.html.form.palette.Palette;\r
@@ -55,7 +57,7 @@ public class EditRepositoryPage extends RootSubPage {
 \r
        private boolean isAdmin;\r
 \r
-       private IModel<String> mailRecipients;\r
+       private IModel<String> mailingLists;\r
 \r
        public EditRepositoryPage() {\r
                // create constructor\r
@@ -118,7 +120,8 @@ public class EditRepositoryPage extends RootSubPage {
                }\r
                final Palette<String> preReceivePalette = new Palette<String>("preReceiveScripts",\r
                                new ListModel<String>(preReceiveScripts), new CollectionModel<String>(GitBlit\r
-                                               .self().getAvailableScripts()), new ChoiceRenderer<String>("", ""), 12, true);\r
+                                               .self().getAvailableScripts()), new ChoiceRenderer<String>("", ""), 12,\r
+                               true);\r
 \r
                // post-receive palette\r
                if (repositoryModel.postReceiveScripts != null) {\r
@@ -126,7 +129,8 @@ public class EditRepositoryPage extends RootSubPage {
                }\r
                final Palette<String> postReceivePalette = new Palette<String>("postReceiveScripts",\r
                                new ListModel<String>(postReceiveScripts), new CollectionModel<String>(GitBlit\r
-                                               .self().getAvailableScripts()), new ChoiceRenderer<String>("", ""), 12, true);\r
+                                               .self().getAvailableScripts()), new ChoiceRenderer<String>("", ""), 12,\r
+                               true);\r
 \r
                CompoundPropertyModel<RepositoryModel> model = new CompoundPropertyModel<RepositoryModel>(\r
                                repositoryModel);\r
@@ -191,11 +195,17 @@ public class EditRepositoryPage extends RootSubPage {
                                                }\r
                                        }\r
 \r
-                                       // set mail recipients\r
-                                       String ml = mailRecipients.getObject();\r
+                                       // set mailing lists\r
+                                       String ml = mailingLists.getObject();\r
                                        if (!StringUtils.isEmpty(ml)) {\r
-                                               List<String> list = StringUtils.getStringsFromValue(ml.trim(), " ");\r
-                                               repositoryModel.mailRecipients = list;\r
+                                               Set<String> list = new HashSet<String>();\r
+                                               for (String address : ml.split("(,|\\s)")) {\r
+                                                       if (StringUtils.isEmpty(address)) {\r
+                                                               continue;\r
+                                                       }\r
+                                                       list.add(address.toLowerCase());\r
+                                               }\r
+                                               repositoryModel.mailingLists = new ArrayList<String>(list);\r
                                        }\r
 \r
                                        // pre-receive scripts\r
@@ -275,9 +285,9 @@ public class EditRepositoryPage extends RootSubPage {
                form.add(new CheckBox("showReadme"));\r
                form.add(new CheckBox("skipSizeCalculation"));\r
                form.add(new CheckBox("skipSummaryMetrics"));\r
-               mailRecipients = new Model<String>(repositoryModel.mailRecipients == null ? ""\r
-                               : StringUtils.flattenStrings(repositoryModel.mailRecipients, " "));\r
-               form.add(new TextField<String>("mailRecipients", mailRecipients));\r
+               mailingLists = new Model<String>(repositoryModel.mailingLists == null ? ""\r
+                               : StringUtils.flattenStrings(repositoryModel.mailingLists, " "));\r
+               form.add(new TextField<String>("mailingLists", mailingLists));\r
                form.add(usersPalette);\r
                form.add(teamsPalette);\r
                form.add(federationSetsPalette);\r
index 84a53e3cc06d70572f2c381a59b582d194d44c63..614f0aa1e32ae6a708d51732eba8af6271e4c2ae 100644 (file)
@@ -9,13 +9,13 @@
        <!-- User Table -->\r
        <form style="padding-top:5px;" wicket:id="editForm">\r
                <table class="plain">\r
-                       <tbody>\r
+                       <tbody class="settings">\r
                                <tr><th><wicket:message key="gb.teamName"></wicket:message></th><td class="edit"><input type="text" wicket:id="name" id="name" size="30" tabindex="1" /></td></tr>\r
                                <tr><td colspan="2"><hr></hr></td></tr>\r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.teamMembers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>\r
                                <tr><td colspan="2"><hr></hr></td></tr>\r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>\r
-                               <tr><th></th><td class="editButton"><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="3" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="4" /></td></tr>\r
+                               <tr><td colspan='2'><div class="actions"><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="3" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="4" /></div></td></tr>\r
                        </tbody>\r
                </table>\r
        </form> \r
index 978393bbdcc0a86a4b56bfd30b8355e7c854b9db..319a2b65ffb1ede149904a1afee10309021204b1 100644 (file)
@@ -9,17 +9,17 @@
        <!-- User Table -->\r
        <form style="padding-top:5px;" wicket:id="editForm">\r
                <table class="plain">\r
-                       <tbody>\r
+                       <tbody class="settings">\r
                                <tr><th><wicket:message key="gb.username"></wicket:message></th><td class="edit"><input type="text" wicket:id="username" id="username" size="30" tabindex="1" /></td></tr>\r
                                <tr><th><wicket:message key="gb.password"></wicket:message></th><td class="edit"><input type="password" wicket:id="password" size="30" tabindex="2" /></td></tr>\r
                                <tr><th><wicket:message key="gb.confirmPassword"></wicket:message></th><td class="edit"><input type="password" wicket:id="confirmPassword" size="30" tabindex="3" /></td></tr>\r
-                               <tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> &nbsp;<i><wicket:message key="gb.canAdminDescription"></wicket:message></i></td></tr>                              \r
-                               <tr><th><wicket:message key="gb.excludeFromFederation"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="excludeFromFederation" tabindex="7" /> &nbsp;<i><wicket:message key="gb.excludeFromFederationDescription"></wicket:message></i></td></tr>                               \r
+                               <tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> &nbsp;<span class="help-inline"><wicket:message key="gb.canAdminDescription"></wicket:message></span></td></tr>                            \r
+                               <tr><th><wicket:message key="gb.excludeFromFederation"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="excludeFromFederation" tabindex="7" /> &nbsp;<span class="help-inline"><wicket:message key="gb.excludeFromFederationDescription"></wicket:message></span></td></tr>                             \r
                                <tr><td colspan="2"><hr></hr></td></tr>\r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.teamMemberships"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr>\r
                                <tr><td colspan="2"><hr></hr></td></tr>\r
                                <tr><th style="vertical-align: top;"><wicket:message key="gb.restrictedRepositories"></wicket:message></th><td style="padding:2px;"><span wicket:id="repositories"></span></td></tr>\r
-                               <tr><th></th><td class="editButton"><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="8" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="9" /></td></tr>\r
+                               <tr><td colspan='2'><div class="actions"><input class="btn" type="submit" value="Cancel" wicket:message="value:gb.cancel" wicket:id="cancel" tabindex="8" /> &nbsp; <input class="btn primary" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" tabindex="9" /></div></td></tr>\r
                        </tbody>\r
                </table>\r
        </form> \r
index fc90316fb7861fa6950fe0b1ce49451f4c2ba3f9..118ad6da98ea171481c794bb2f33a9b6d7bec3f0 100644 (file)
@@ -25,6 +25,7 @@ import java.util.Iterator;
 import java.util.List;\r
 import java.util.Map;\r
 \r
+import org.apache.wicket.Component;\r
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;\r
 import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;\r
@@ -157,7 +158,7 @@ public class RepositoriesPanel extends BasePanel {
                                }\r
 \r
                                // repository swatch\r
-                               Label swatch = new Label("repositorySwatch", " ");\r
+                               Component swatch = new Label("repositorySwatch", "&nbsp;").setEscapeModelStrings(false);\r
                                WicketUtils.setCssBackground(swatch, entry.name);\r
                                row.add(swatch);\r
                                swatch.setVisible(showSwatch);\r
index 5fcc7382ba7f673df130d017a5dadc0442e7a32d..a815198b6b1cb8b22e76d6461ba95a05c54077bd 100644 (file)
@@ -7,7 +7,7 @@ git.searchRepositoriesSubfolders = true
 git.enableGitServlet = true
 groovy.scriptsFolder = groovy
 groovy.preReceiveScripts = blockpush
-groovy.postReceiveScripts = sendemail jenkins
+groovy.postReceiveScripts = sendmail jenkins
 web.authenticateViewPages = false
 web.authenticateAdminPages = true
 web.allowCookieAuthentication = true