diff options
author | James Moger <james.moger@gitblit.com> | 2012-04-06 18:01:58 -0400 |
---|---|---|
committer | James Moger <james.moger@gitblit.com> | 2012-04-06 18:01:58 -0400 |
commit | 6cca8699f98a606ff19e88d40a8a2535fdc340e7 (patch) | |
tree | b4725b6edbed868e10e6edaae049a7423f4f3008 /src | |
parent | d58f8efd44c73a649aa92e590cb138ee4507ac99 (diff) | |
download | gitblit-6cca8699f98a606ff19e88d40a8a2535fdc340e7.tar.gz gitblit-6cca8699f98a606ff19e88d40a8a2535fdc340e7.zip |
Skeleton LdapUserService based on John Cryiger's implementation
Diffstat (limited to 'src')
-rw-r--r-- | src/com/gitblit/ConfigUserService.java | 25 | ||||
-rw-r--r-- | src/com/gitblit/FileUserService.java | 27 | ||||
-rw-r--r-- | src/com/gitblit/GitBlit.java | 16 | ||||
-rw-r--r-- | src/com/gitblit/GitblitUserService.java | 38 | ||||
-rw-r--r-- | src/com/gitblit/IStoredSettings.java | 18 | ||||
-rw-r--r-- | src/com/gitblit/IUserService.java | 16 | ||||
-rw-r--r-- | src/com/gitblit/LdapUserService.java | 200 | ||||
-rw-r--r-- | src/com/gitblit/utils/ConnectionUtils.java | 89 | ||||
-rw-r--r-- | src/com/gitblit/wicket/GitBlitWebApp.properties | 4 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/BasePage.java | 6 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/ChangePasswordPage.java | 6 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/EditTeamPage.java | 5 | ||||
-rw-r--r-- | src/com/gitblit/wicket/pages/EditUserPage.java | 18 | ||||
-rw-r--r-- | src/com/gitblit/wicket/panels/UsersPanel.java | 3 |
14 files changed, 458 insertions, 13 deletions
diff --git a/src/com/gitblit/ConfigUserService.java b/src/com/gitblit/ConfigUserService.java index 8f47f7a0..828ba762 100644 --- a/src/com/gitblit/ConfigUserService.java +++ b/src/com/gitblit/ConfigUserService.java @@ -100,6 +100,27 @@ public class ConfigUserService implements IUserService { }
/**
+ * Does the user service support changes to credentials?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ @Override
+ public boolean supportsCredentialChanges() {
+ return true;
+ }
+
+ /**
+ * Does the user service support changes to team memberships?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ public boolean supportsTeamMembershipChanges() {
+ return true;
+ }
+
+ /**
* Does the user service support cookie authentication?
*
* @return true or false
@@ -656,7 +677,9 @@ public class ConfigUserService implements IUserService { // write users
for (UserModel model : users.values()) {
- config.setString(USER, model.username, PASSWORD, model.password);
+ if (!StringUtils.isEmpty(model.password)) {
+ config.setString(USER, model.username, PASSWORD, model.password);
+ }
// user roles
List<String> roles = new ArrayList<String>();
diff --git a/src/com/gitblit/FileUserService.java b/src/com/gitblit/FileUserService.java index 7842c31d..b8d4a40e 100644 --- a/src/com/gitblit/FileUserService.java +++ b/src/com/gitblit/FileUserService.java @@ -74,6 +74,27 @@ public class FileUserService extends FileSettings implements IUserService { }
/**
+ * Does the user service support changes to credentials?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ @Override
+ public boolean supportsCredentialChanges() {
+ return true;
+ }
+
+ /**
+ * Does the user service support changes to team memberships?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ public boolean supportsTeamMembershipChanges() {
+ return true;
+ }
+
+ /**
* Does the user service support cookie authentication?
*
* @return true or false
@@ -233,7 +254,9 @@ public class FileUserService extends FileSettings implements IUserService { }
StringBuilder sb = new StringBuilder();
- sb.append(model.password);
+ if (!StringUtils.isEmpty(model.password)) {
+ sb.append(model.password);
+ }
sb.append(',');
for (String role : roles) {
sb.append(role);
@@ -658,6 +681,8 @@ public class FileUserService extends FileSettings implements IUserService { team.addRepositories(repositories);
team.addUsers(users);
team.addMailingLists(mailingLists);
+ team.preReceiveScripts.addAll(preReceive);
+ team.postReceiveScripts.addAll(postReceive);
teams.put(team.name.toLowerCase(), team);
} else {
// user definition
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java index 7b557d79..6ed54dc6 100644 --- a/src/com/gitblit/GitBlit.java +++ b/src/com/gitblit/GitBlit.java @@ -377,6 +377,22 @@ public class GitBlit implements ServletContextListener { this.userService = userService;
this.userService.setup(settings);
}
+
+ /**
+ *
+ * @return true if the user service supports credential changes
+ */
+ public boolean supportsCredentialChanges() {
+ return userService.supportsCredentialChanges();
+ }
+
+ /**
+ *
+ * @return true if the user service supports team membership changes
+ */
+ public boolean supportsTeamMembershipChanges() {
+ return userService.supportsTeamMembershipChanges();
+ }
/**
* Authenticate a user based on a username and password.
diff --git a/src/com/gitblit/GitblitUserService.java b/src/com/gitblit/GitblitUserService.java index 7462af08..1514b6b9 100644 --- a/src/com/gitblit/GitblitUserService.java +++ b/src/com/gitblit/GitblitUserService.java @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
+import com.gitblit.utils.DeepCopier;
/**
* This class wraps the default user service and is recommended as the starting
@@ -112,6 +113,16 @@ public class GitblitUserService implements IUserService { }
@Override
+ public boolean supportsCredentialChanges() {
+ return serviceImpl.supportsCredentialChanges();
+ }
+
+ @Override
+ public boolean supportsTeamMembershipChanges() {
+ return serviceImpl.supportsTeamMembershipChanges();
+ }
+
+ @Override
public boolean supportsCookies() {
return serviceImpl.supportsCookies();
}
@@ -143,9 +154,27 @@ public class GitblitUserService implements IUserService { @Override
public boolean updateUserModel(String username, UserModel model) {
- return serviceImpl.updateUserModel(username, model);
+ if (supportsCredentialChanges()) {
+ if (!supportsTeamMembershipChanges()) {
+ // teams are externally controlled
+ model = DeepCopier.copy(model);
+ model.teams.clear();
+ }
+ return serviceImpl.updateUserModel(username, model);
+ }
+ if (model.username.equals(username)) {
+ // passwords are not persisted by the backing user service
+ model.password = null;
+ if (!supportsTeamMembershipChanges()) {
+ // teams are externally controlled
+ model = DeepCopier.copy(model);
+ model.teams.clear();
+ }
+ return serviceImpl.updateUserModel(username, model);
+ }
+ logger.error("Users can not be renamed!");
+ return false;
}
-
@Override
public boolean deleteUserModel(UserModel model) {
return serviceImpl.deleteUserModel(model);
@@ -198,6 +227,11 @@ public class GitblitUserService implements IUserService { @Override
public boolean updateTeamModel(String teamname, TeamModel model) {
+ if (!supportsTeamMembershipChanges()) {
+ // teams are externally controlled
+ model = DeepCopier.copy(model);
+ model.users.clear();
+ }
return serviceImpl.updateTeamModel(teamname, model);
}
diff --git a/src/com/gitblit/IStoredSettings.java b/src/com/gitblit/IStoredSettings.java index 2d8b6055..2f45f09d 100644 --- a/src/com/gitblit/IStoredSettings.java +++ b/src/com/gitblit/IStoredSettings.java @@ -157,6 +157,24 @@ public abstract class IStoredSettings { }
return defaultValue;
}
+
+ /**
+ * Returns the string value for the specified key. If the key does not
+ * exist an exception is thrown.
+ *
+ * @param key
+ * @return key value
+ */
+ public String getRequiredString(String name) {
+ Properties props = getSettings();
+ if (props.containsKey(name)) {
+ String value = props.getProperty(name);
+ if (value != null) {
+ return value.trim();
+ }
+ }
+ throw new RuntimeException("Property (" + name + ") does not exist");
+ }
/**
* Returns a list of space-separated strings from the specified key.
diff --git a/src/com/gitblit/IUserService.java b/src/com/gitblit/IUserService.java index a5e04e3e..334bbedd 100644 --- a/src/com/gitblit/IUserService.java +++ b/src/com/gitblit/IUserService.java @@ -40,6 +40,22 @@ public interface IUserService { void setup(IStoredSettings settings);
/**
+ * Does the user service support changes to credentials?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ boolean supportsCredentialChanges();
+
+ /**
+ * Does the user service support changes to team memberships?
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ boolean supportsTeamMembershipChanges();
+
+ /**
* Does the user service support cookie authentication?
*
* @return true or false
diff --git a/src/com/gitblit/LdapUserService.java b/src/com/gitblit/LdapUserService.java new file mode 100644 index 00000000..3ec45e17 --- /dev/null +++ b/src/com/gitblit/LdapUserService.java @@ -0,0 +1,200 @@ +/*
+ * Copyright 2012 John Crygier
+ * Copyright 2012 gitblit.com
+ *
+ * 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.gitblit;
+
+import java.io.File;
+import java.text.MessageFormat;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.gitblit.models.TeamModel;
+import com.gitblit.models.UserModel;
+import com.gitblit.utils.ConnectionUtils.BlindSSLSocketFactory;
+import com.gitblit.utils.StringUtils;
+
+/**
+ * Implementation of an LDAP user service.
+ *
+ * @author John Crygier
+ */
+public class LdapUserService extends GitblitUserService {
+
+ public static final Logger logger = LoggerFactory.getLogger(LdapUserService.class);
+ private final String CONTEXT_FACTORY = "com.sun.jndi.ldap.LdapCtxFactory";
+
+ private IStoredSettings settings;
+
+ public LdapUserService() {
+ super();
+ }
+
+ @Override
+ public void setup(IStoredSettings settings) {
+ this.settings = settings;
+ String file = settings.getString(Keys.realm.ldap_backingUserService, "users.conf");
+ File realmFile = GitBlit.getFileOrFolder(file);
+
+ serviceImpl = createUserService(realmFile);
+ logger.info("LDAP User Service backed by " + serviceImpl.toString());
+ }
+
+ /**
+ * Credentials are defined in the LDAP server and can not be manipulated
+ * from Gitblit.
+ *
+ * @return false
+ * @since 1.0.0
+ */
+ @Override
+ public boolean supportsCredentialChanges() {
+ return false;
+ }
+
+ /**
+ * If the LDAP server will maintain team memberships then LdapUserService
+ * will not allow team membership changes. In this scenario all team
+ * changes must be made on the LDAP server by the LDAP administrator.
+ *
+ * @return true or false
+ * @since 1.0.0
+ */
+ public boolean supportsTeamMembershipChanges() {
+ return !settings.getBoolean(Keys.realm.ldap_maintainTeams, false);
+ }
+
+ /**
+ * Does the user service support cookie authentication?
+ *
+ * @return true or false
+ */
+ @Override
+ public boolean supportsCookies() {
+ // TODO cookies need to be reviewed
+ return false;
+ }
+
+ @Override
+ public UserModel authenticate(String username, char[] password) {
+ String domainUser = getDomainUsername(username);
+ DirContext ctx = getDirContext(domainUser, new String(password));
+ // TODO do we need a bind here?
+ if (ctx != null) {
+ String simpleUsername = getSimpleUsername(username);
+ UserModel user = getUserModel(simpleUsername);
+ if (user == null) {
+ // create user object for new authenticated user
+ user = new UserModel(simpleUsername.toLowerCase());
+ }
+ user.password = new String(password);
+
+ if (!supportsTeamMembershipChanges()) {
+ // Teams are specified in LDAP server
+ // TODO search LDAP for team memberships
+ Set<String> foundTeams = new HashSet<String>();
+ for (String team : foundTeams) {
+ TeamModel model = getTeamModel(team);
+ if (model == null) {
+ // create the team
+ model = new TeamModel(team.toLowerCase());
+ updateTeamModel(model);
+ }
+ // add team to the user
+ user.teams.add(model);
+ }
+ }
+
+ try {
+ ctx.close();
+ } catch (NamingException e) {
+ logger.error("Can not close context", e);
+ }
+ return user;
+ }
+ return null;
+ }
+
+ protected DirContext getDirContext() {
+ String username = settings.getString(Keys.realm.ldap_username, "");
+ String password = settings.getString(Keys.realm.ldap_password, "");
+ return getDirContext(username, password);
+ }
+
+ protected DirContext getDirContext(String username, String password) {
+ try {
+ String server = settings.getRequiredString(Keys.realm.ldap_server);
+ Hashtable<String, String> env = new Hashtable<String, String>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, CONTEXT_FACTORY);
+ env.put(Context.PROVIDER_URL, server);
+ if (server.startsWith("ldaps:")) {
+ env.put("java.naming.ldap.factory.socket", BlindSSLSocketFactory.class.getName());
+ }
+ // TODO consider making this a setting
+ env.put("com.sun.jndi.ldap.read.timeout", "5000");
+
+ if (!StringUtils.isEmpty(username)) {
+ // authenticated login
+ env.put(Context.SECURITY_AUTHENTICATION, "simple");
+ env.put(Context.SECURITY_PRINCIPAL, getDomainUsername(username));
+ env.put(Context.SECURITY_CREDENTIALS, password == null ? "":password.trim());
+ }
+ return new InitialDirContext(env);
+ } catch (NamingException e) {
+ logger.warn(MessageFormat.format("Error connecting to LDAP with credentials. Please check {0}, {1}, and {2}",
+ Keys.realm.ldap_server, Keys.realm.ldap_username, Keys.realm.ldap_password), e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns a simple username without any domain prefixes.
+ *
+ * @param username
+ * @return a simple username
+ */
+ protected String getSimpleUsername(String username) {
+ int lastSlash = username.lastIndexOf('\\');
+ if (lastSlash > -1) {
+ username = username.substring(lastSlash + 1);
+ }
+ return username;
+ }
+
+ /**
+ * Returns a username with a domain prefix as long as the username does not
+ * already have a comain prefix.
+ *
+ * @param username
+ * @return a domain username
+ */
+ protected String getDomainUsername(String username) {
+ String domain = settings.getString(Keys.realm.ldap_domain, null);
+ String domainUsername = username;
+ if (!StringUtils.isEmpty(domain) && (domainUsername.indexOf('\\') == -1)) {
+ domainUsername = domain + "\\" + username;
+ }
+ return domainUsername.trim();
+ }
+}
diff --git a/src/com/gitblit/utils/ConnectionUtils.java b/src/com/gitblit/utils/ConnectionUtils.java index 9ad62d0e..f0b41118 100644 --- a/src/com/gitblit/utils/ConnectionUtils.java +++ b/src/com/gitblit/utils/ConnectionUtils.java @@ -16,16 +16,22 @@ package com.gitblit.utils;
import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
import java.net.URL;
import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
+import javax.net.SocketFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
@@ -87,6 +93,89 @@ public class ConnectionUtils { }
return conn;
}
+
+ // Copyright (C) 2009 The Android Open Source Project
+ //
+ // Licensed under the Apache License, Version 2.0 (the "License");
+ // you may not use this file except in compliance with the License.
+ // You may obtain a copy of the License at
+ //
+ // http://www.apache.org/licenses/LICENSE-2.0
+ //
+ // Unless required by applicable law or agreed to in writing, software
+ // distributed under the License is distributed on an "AS IS" BASIS,
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ // See the License for the specific language governing permissions and
+ // limitations under the License.
+ public static class BlindSSLSocketFactory extends SSLSocketFactory {
+ private static final BlindSSLSocketFactory INSTANCE;
+
+ static {
+ try {
+ final SSLContext context = SSLContext.getInstance("SSL");
+ final TrustManager[] trustManagers = { new DummyTrustManager() };
+ final SecureRandom rng = new SecureRandom();
+ context.init(null, trustManagers, rng);
+ INSTANCE = new BlindSSLSocketFactory(context.getSocketFactory());
+ } catch (GeneralSecurityException e) {
+ throw new RuntimeException("Cannot create BlindSslSocketFactory", e);
+ }
+ }
+
+ public static SocketFactory getDefault() {
+ return INSTANCE;
+ }
+
+ private final SSLSocketFactory sslFactory;
+
+ private BlindSSLSocketFactory(final SSLSocketFactory sslFactory) {
+ this.sslFactory = sslFactory;
+ }
+
+ @Override
+ public Socket createSocket(Socket s, String host, int port, boolean autoClose)
+ throws IOException {
+ return sslFactory.createSocket(s, host, port, autoClose);
+ }
+
+ @Override
+ public String[] getDefaultCipherSuites() {
+ return sslFactory.getDefaultCipherSuites();
+ }
+
+ @Override
+ public String[] getSupportedCipherSuites() {
+ return sslFactory.getSupportedCipherSuites();
+ }
+
+ @Override
+ public Socket createSocket() throws IOException {
+ return sslFactory.createSocket();
+ }
+
+ @Override
+ public Socket createSocket(String host, int port) throws IOException,
+ UnknownHostException {
+ return sslFactory.createSocket(host, port);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress host, int port) throws IOException {
+ return sslFactory.createSocket(host, port);
+ }
+
+ @Override
+ public Socket createSocket(String host, int port, InetAddress localHost,
+ int localPort) throws IOException, UnknownHostException {
+ return sslFactory.createSocket(host, port, localHost, localPort);
+ }
+
+ @Override
+ public Socket createSocket(InetAddress address, int port,
+ InetAddress localAddress, int localPort) throws IOException {
+ return sslFactory.createSocket(address, port, localAddress, localPort);
+ }
+ }
/**
* DummyTrustManager trusts all certificates.
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties index e73addc8..295db8a3 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.properties +++ b/src/com/gitblit/wicket/GitBlitWebApp.properties @@ -270,4 +270,6 @@ gb.noProposals = Sorry, {0} is not accepting proposals at this time. gb.noFederation = Sorry, {0} is not configured to federate with any Gitblit instances.
gb.proposalFailed = Sorry, {0} did not receive any proposal data!
gb.proposalError = Sorry, {0} reports that an unexpected error occurred!
-gb.failedToSendProposal = Failed to send proposal!
\ No newline at end of file +gb.failedToSendProposal = Failed to send proposal!
+gb.userServiceDoesNotPermitAddUser = {0} does not permit adding a user account!
+gb.userServiceDoesNotPermitPasswordChanges = {0} does not permit password changes!
\ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/BasePage.java b/src/com/gitblit/wicket/pages/BasePage.java index 3852818a..94ed6334 100644 --- a/src/com/gitblit/wicket/pages/BasePage.java +++ b/src/com/gitblit/wicket/pages/BasePage.java @@ -254,9 +254,11 @@ public abstract class BasePage extends WebPage { add(new Label("username", GitBlitWebSession.get().getUser().toString() + ":"));
add(new LinkPanel("loginLink", null, markupProvider.getString("gb.logout"),
LogoutPage.class));
+ boolean editCredentials = GitBlit.self().supportsCredentialChanges();
// quick and dirty hack for showing a separator
- add(new Label("separator", "|"));
- add(new BookmarkablePageLink<Void>("changePasswordLink", ChangePasswordPage.class));
+ add(new Label("separator", "|").setVisible(editCredentials));
+ add(new BookmarkablePageLink<Void>("changePasswordLink",
+ ChangePasswordPage.class).setVisible(editCredentials));
} else {
// login
add(new Label("username").setVisible(false));
diff --git a/src/com/gitblit/wicket/pages/ChangePasswordPage.java b/src/com/gitblit/wicket/pages/ChangePasswordPage.java index 4fb5d237..cbe732ff 100644 --- a/src/com/gitblit/wicket/pages/ChangePasswordPage.java +++ b/src/com/gitblit/wicket/pages/ChangePasswordPage.java @@ -50,6 +50,12 @@ public class ChangePasswordPage extends RootSubPage { // no authentication enabled
throw new RestartResponseException(getApplication().getHomePage());
}
+
+ if (!GitBlit.self().supportsCredentialChanges()) {
+ error(MessageFormat.format(getString("gb.userServiceDoesNotPermitPasswordChanges"),
+ GitBlit.getString(Keys.realm.userService, "users.conf")), true);
+ }
+
setupPage(getString("gb.changePassword"), GitBlitWebSession.get().getUser().username);
StatelessForm<Void> form = new StatelessForm<Void>("passwordForm") {
diff --git a/src/com/gitblit/wicket/pages/EditTeamPage.java b/src/com/gitblit/wicket/pages/EditTeamPage.java index 890ea8f7..96bd188f 100644 --- a/src/com/gitblit/wicket/pages/EditTeamPage.java +++ b/src/com/gitblit/wicket/pages/EditTeamPage.java @@ -217,9 +217,12 @@ public class EditTeamPage extends RootSubPage { // do not let the browser pre-populate these fields
form.add(new SimpleAttributeModifier("autocomplete", "off"));
+ // not all user services support manipulating team memberships
+ boolean editMemberships = GitBlit.self().supportsTeamMembershipChanges();
+
// field names reflective match TeamModel fields
form.add(new TextField<String>("name"));
- form.add(users);
+ form.add(users.setEnabled(editMemberships));
mailingLists = new Model<String>(teamModel.mailingLists == null ? ""
: StringUtils.flattenStrings(teamModel.mailingLists, " "));
form.add(new TextField<String>("mailingLists", mailingLists));
diff --git a/src/com/gitblit/wicket/pages/EditUserPage.java b/src/com/gitblit/wicket/pages/EditUserPage.java index 36f7578d..e7b42877 100644 --- a/src/com/gitblit/wicket/pages/EditUserPage.java +++ b/src/com/gitblit/wicket/pages/EditUserPage.java @@ -54,6 +54,10 @@ public class EditUserPage extends RootSubPage { public EditUserPage() {
// create constructor
super();
+ if (!GitBlit.self().supportsCredentialChanges()) {
+ error(MessageFormat.format(getString("gb.userServiceDoesNotPermitAddUser"),
+ GitBlit.getString(Keys.realm.userService, "users.conf")), true);
+ }
isCreate = true;
setupPage(new UserModel(""));
}
@@ -200,20 +204,26 @@ public class EditUserPage extends RootSubPage { // do not let the browser pre-populate these fields
form.add(new SimpleAttributeModifier("autocomplete", "off"));
+
+ // not all user services support manipulating username and password
+ boolean editCredentials = GitBlit.self().supportsCredentialChanges();
+
+ // not all user services support manipulating team memberships
+ boolean editTeams = GitBlit.self().supportsTeamMembershipChanges();
// field names reflective match UserModel fields
- form.add(new TextField<String>("username"));
+ form.add(new TextField<String>("username").setEnabled(editCredentials));
PasswordTextField passwordField = new PasswordTextField("password");
passwordField.setResetPassword(false);
- form.add(passwordField);
+ form.add(passwordField.setEnabled(editCredentials));
PasswordTextField confirmPasswordField = new PasswordTextField("confirmPassword",
confirmPassword);
confirmPasswordField.setResetPassword(false);
- form.add(confirmPasswordField);
+ form.add(confirmPasswordField.setEnabled(editCredentials));
form.add(new CheckBox("canAdmin"));
form.add(new CheckBox("excludeFromFederation"));
form.add(repositories);
- form.add(teams);
+ form.add(teams.setEnabled(editTeams));
form.add(new Button("save"));
Button cancel = new Button("cancel") {
diff --git a/src/com/gitblit/wicket/panels/UsersPanel.java b/src/com/gitblit/wicket/panels/UsersPanel.java index ad2ed922..4b0edb34 100644 --- a/src/com/gitblit/wicket/panels/UsersPanel.java +++ b/src/com/gitblit/wicket/panels/UsersPanel.java @@ -39,7 +39,8 @@ public class UsersPanel extends BasePanel { super(wicketId);
Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
- adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class));
+ adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class)
+ .setVisible(GitBlit.self().supportsCredentialChanges()));
add(adminLinks.setVisible(showAdmin));
final List<UserModel> users = GitBlit.self().getAllUsers();
|