提交 8a84cb8e 编写于 作者: K kzantow

Address outstanding issues: XStream deserialzation from existing

installs would have had altered behavior with the FullControl auth
strategy, erroneous return while creating the default user, added help
file, added ability to skip first user or cancel the wizard altogether.
上级 08b6ff33
...@@ -43,10 +43,10 @@ import java.util.List; ...@@ -43,10 +43,10 @@ import java.util.List;
*/ */
public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationStrategy { public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationStrategy {
/** /**
* Whether to allow read access, default behavior * Whether to allow anonymouos read access, default behavior
* previously was true * previously was to do so
*/ */
private boolean allowAnonymousRead = true; private boolean authenticatedReadOnly = false;
@DataBoundConstructor @DataBoundConstructor
public FullControlOnceLoggedInAuthorizationStrategy() { public FullControlOnceLoggedInAuthorizationStrategy() {
...@@ -54,7 +54,7 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS ...@@ -54,7 +54,7 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS
@Override @Override
public ACL getRootACL() { public ACL getRootACL() {
return allowAnonymousRead ? ANONYMOUS_READ : AUTHENTICATED_READ; return !authenticatedReadOnly ? ANONYMOUS_READ : AUTHENTICATED_READ;
} }
public List<String> getGroups() { public List<String> getGroups() {
...@@ -65,12 +65,12 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS ...@@ -65,12 +65,12 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS
* If true, anonymous read access will be allowed * If true, anonymous read access will be allowed
*/ */
public boolean isAllowAnonymousRead() { public boolean isAllowAnonymousRead() {
return allowAnonymousRead; return !authenticatedReadOnly;
} }
@DataBoundSetter @DataBoundSetter
public void setAllowAnonymousRead(boolean allowAnonymousRead) { public void setAllowAnonymousRead(boolean allowAnonymousRead) {
this.allowAnonymousRead = allowAnonymousRead; this.authenticatedReadOnly = !allowAnonymousRead;
} }
private static final SparseACL AUTHENTICATED_READ = new SparseACL(null); private static final SparseACL AUTHENTICATED_READ = new SparseACL(null);
...@@ -83,7 +83,6 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS ...@@ -83,7 +83,6 @@ public class FullControlOnceLoggedInAuthorizationStrategy extends AuthorizationS
AUTHENTICATED_READ.add(ACL.EVERYONE, Jenkins.ADMINISTER, true); AUTHENTICATED_READ.add(ACL.EVERYONE, Jenkins.ADMINISTER, true);
AUTHENTICATED_READ.add(ACL.ANONYMOUS, Jenkins.ADMINISTER, false); AUTHENTICATED_READ.add(ACL.ANONYMOUS, Jenkins.ADMINISTER, false);
AUTHENTICATED_READ.add(ACL.ANONYMOUS, Permission.READ, false);
} }
/** /**
......
...@@ -286,20 +286,31 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea ...@@ -286,20 +286,31 @@ public class HudsonPrivateSecurityRealm extends AbstractPasswordBasedSecurityRea
rsp.sendError(SC_UNAUTHORIZED,"First user was already created"); rsp.sendError(SC_UNAUTHORIZED,"First user was already created");
return; return;
} }
String view = "firstUser.jelly";
User admin = null; User admin = null;
if(inSetup) { try {
admin = getUser(SetupWizard.initialSetupAdminUserName); String view = "firstUser.jelly";
view = "setupWizardFirstUser.jelly"; if(inSetup) {
} admin = getUser(SetupWizard.initialSetupAdminUserName);
User u = createAccount(req, rsp, false, view); if(admin != null) {
if (u!=null) { admin.delete(); // assume the new user may well be 'admin'
tryToMakeAdmin(u); }
view = "setupWizardFirstUser.jelly";
}
User u = createAccount(req, rsp, false, view);
if (u!=null) {
tryToMakeAdmin(u);
if(admin != null) {
admin = null;
}
Jenkins.getInstance().setInstallState(InstallState.CREATE_ADMIN_USER.getNextState());
loginAndTakeBack(req, rsp, u);
}
} finally {
if(admin != null) { if(admin != null) {
admin.delete(); admin.save(); // recreate this initial user if something failed
} }
Jenkins.getInstance().setInstallState(InstallState.CREATE_ADMIN_USER.getNextState());
loginAndTakeBack(req, rsp, u);
} }
} }
......
...@@ -14,16 +14,20 @@ import javax.servlet.ServletResponse; ...@@ -14,16 +14,20 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper; import javax.servlet.http.HttpServletRequestWrapper;
import org.kohsuke.stapler.HttpResponse;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
import hudson.BulkChange; import hudson.BulkChange;
import hudson.ExtensionList; import hudson.ExtensionList;
import hudson.model.User; import hudson.model.User;
import hudson.model.UserProperty; import hudson.model.UserProperty;
import hudson.security.AuthorizationStrategy;
import hudson.security.FullControlOnceLoggedInAuthorizationStrategy; import hudson.security.FullControlOnceLoggedInAuthorizationStrategy;
import hudson.security.HudsonPrivateSecurityRealm; import hudson.security.HudsonPrivateSecurityRealm;
import hudson.security.PermissionAdder; import hudson.security.PermissionAdder;
import hudson.security.SecurityRealm; import hudson.security.SecurityRealm;
import hudson.security.csrf.DefaultCrumbIssuer; import hudson.security.csrf.DefaultCrumbIssuer;
import hudson.util.HttpResponses;
import hudson.util.PluginServletFilter; import hudson.util.PluginServletFilter;
import jenkins.model.Jenkins; import jenkins.model.Jenkins;
import jenkins.security.s2m.AdminWhitelistRule; import jenkins.security.s2m.AdminWhitelistRule;
...@@ -36,7 +40,7 @@ public class SetupWizard { ...@@ -36,7 +40,7 @@ public class SetupWizard {
/** /**
* The security token parameter name * The security token parameter name
*/ */
public static String initialSetupAdminUserName = "initial-setup-admin-user"; public static String initialSetupAdminUserName = "admin";
private final Logger LOGGER = Logger.getLogger(SetupWizard.class.getName()); private final Logger LOGGER = Logger.getLogger(SetupWizard.class.getName());
...@@ -52,18 +56,16 @@ public class SetupWizard { ...@@ -52,18 +56,16 @@ public class SetupWizard {
String randomUUID = UUID.randomUUID().toString().replace("-", "").toLowerCase(Locale.ENGLISH); String randomUUID = UUID.randomUUID().toString().replace("-", "").toLowerCase(Locale.ENGLISH);
admin = securityRealm.createAccount(SetupWizard.initialSetupAdminUserName, randomUUID); admin = securityRealm.createAccount(SetupWizard.initialSetupAdminUserName, randomUUID);
admin.addProperty(new SetupWizard.AuthenticationKey(randomUUID)); admin.addProperty(new SetupWizard.AuthenticationKey(randomUUID));
AuthorizationStrategy as = Jenkins.getInstance().getAuthorizationStrategy();
for (PermissionAdder adder : ExtensionList.lookup(PermissionAdder.class)) {
if (adder.add(as, admin, Jenkins.ADMINISTER)) {
return;
}
}
// Lock Jenkins down: // Lock Jenkins down:
FullControlOnceLoggedInAuthorizationStrategy authStrategy = new FullControlOnceLoggedInAuthorizationStrategy(); FullControlOnceLoggedInAuthorizationStrategy authStrategy = new FullControlOnceLoggedInAuthorizationStrategy();
authStrategy.setAllowAnonymousRead(false); authStrategy.setAllowAnonymousRead(false);
j.setAuthorizationStrategy(authStrategy); j.setAuthorizationStrategy(authStrategy);
// there probably aren't any implementors yet, but just in case
for (PermissionAdder adder : ExtensionList.lookup(PermissionAdder.class)) {
adder.add(authStrategy, admin, Jenkins.ADMINISTER);
}
// Shut down all the ports we can by default: // Shut down all the ports we can by default:
j.setSlaveAgentPort(-1); // -1 to disable j.setSlaveAgentPort(-1); // -1 to disable
...@@ -114,13 +116,14 @@ public class SetupWizard { ...@@ -114,13 +116,14 @@ public class SetupWizard {
/** /**
* Remove the setupWizard filter, ensure all updates are written to disk, etc * Remove the setupWizard filter, ensure all updates are written to disk, etc
*/ */
public void doCompleteSetupWizard() { public HttpResponse doCompleteInstall(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException {
Jenkins j = Jenkins.getActiveInstance();
j.setInstallState(InstallState.INITIAL_SETUP_COMPLETED);
InstallUtil.saveLastExecVersion(); InstallUtil.saveLastExecVersion();
try { PluginServletFilter.removeFilter(FORCE_SETUP_WIZARD_FILTER);
PluginServletFilter.removeFilter(FORCE_SETUP_WIZARD_FILTER); // Also, clean up the setup wizard if it's completed
} catch (ServletException e) { j.setSetupWizard(null);
throw new AssertionError(e); // never happen because our Filter.init is no-op return HttpResponses.okJSON();
}
} }
// Stores a user property for the authentication key, which is really the auto-generated user's password // Stores a user property for the authentication key, which is really the auto-generated user's password
......
...@@ -936,12 +936,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve ...@@ -936,12 +936,7 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
*/ */
@Restricted(NoExternalUse.class) @Restricted(NoExternalUse.class)
public void setInstallState(@Nonnull InstallState newState) { public void setInstallState(@Nonnull InstallState newState) {
InstallState prior = installState;
installState = newState; installState = newState;
if(setupWizard != null && !newState.equals(prior) && newState.isSetupComplete()) {
setupWizard.doCompleteSetupWizard();
setupWizard = null;
}
} }
/** /**
...@@ -3916,6 +3911,13 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve ...@@ -3916,6 +3911,13 @@ public class Jenkins extends AbstractCIBase implements DirectlyModifiableTopLeve
public SetupWizard getSetupWizard() { public SetupWizard getSetupWizard() {
return setupWizard; return setupWizard;
} }
/**
* Sets the setup wizard
*/
public void setSetupWizard(SetupWizard setupWizard) {
this.setupWizard = setupWizard;
}
/** /**
* Exposes the current user to <tt>/me</tt> URL. * Exposes the current user to <tt>/me</tt> URL.
......
<div>
If checked, this will allow users who are not authenticated to access Jenkins in a read-only mode.
</div>
...@@ -38,6 +38,11 @@ installWizard_installIncomplete_banner=Resume Installation ...@@ -38,6 +38,11 @@ installWizard_installIncomplete_banner=Resume Installation
installWizard_installIncomplete_message=Jenknins was restarted during installation and some plugins didn't seem to get installed. installWizard_installIncomplete_message=Jenknins was restarted during installation and some plugins didn't seem to get installed.
installWizard_installIncomplete_resumeInstallationButtonLabel=Resume installWizard_installIncomplete_resumeInstallationButtonLabel=Resume
installWizard_saveFirstUser=Save and Finish installWizard_saveFirstUser=Save and Finish
installWizard_skipFirstUser=Skip
installWizard_firstUserSkippedMessage=<div class="alert alert-warning fade in">\
You've skipped creating an admin user. To log in, use the username: 'admin' and \
the security token you used to access the setup wizard.\
</div>
installWizard_addFirstUser_title=Create an Admin User installWizard_addFirstUser_title=Create an Admin User
installWizard_configureProxy_label=Configure Proxy installWizard_configureProxy_label=Configure Proxy
installWizard_configureProxy_save=Save and Continue installWizard_configureProxy_save=Save and Continue
......
...@@ -149,7 +149,7 @@ exports.incompleteInstallStatus = function(handler, correlationId) { ...@@ -149,7 +149,7 @@ exports.incompleteInstallStatus = function(handler, correlationId) {
* Call this to complete the installation without installing anything * Call this to complete the installation without installing anything
*/ */
exports.completeInstall = function(handler) { exports.completeInstall = function(handler) {
jenkins.get('/updateCenter/completeInstall', function() { jenkins.get('/setupWizard/completeInstall', function() {
handler.call({ isError: false }); handler.call({ isError: false });
}, { }, {
timeout: pluginManagerErrorTimeoutMillis, timeout: pluginManagerErrorTimeoutMillis,
......
...@@ -193,6 +193,12 @@ var createPluginSetupWizard = function(appendTarget) { ...@@ -193,6 +193,12 @@ var createPluginSetupWizard = function(appendTarget) {
currentPanel = panel; currentPanel = panel;
$container.append(html); $container.append(html);
decorate($container); decorate($container);
var $modalHeader = $container.find('.modal-header');
if($modalHeader.length > 0) {
$modalHeader.prepend(
'<button type="button" class="close" aria-label="Close"><span aria-hidden="true">&times;</span></button>');
}
if(oncomplete) { if(oncomplete) {
oncomplete(); oncomplete();
...@@ -396,7 +402,7 @@ var createPluginSetupWizard = function(appendTarget) { ...@@ -396,7 +402,7 @@ var createPluginSetupWizard = function(appendTarget) {
// Called to complete the installation // Called to complete the installation
var finishInstallation = function() { var finishInstallation = function() {
jenkins.goTo('/'); closeInstaller();
}; };
// load the plugin data, callback // load the plugin data, callback
...@@ -667,6 +673,11 @@ var createPluginSetupWizard = function(appendTarget) { ...@@ -667,6 +673,11 @@ var createPluginSetupWizard = function(appendTarget) {
securityConfig.saveFirstUser($('iframe[src]').contents().find('form:not(.no-json)'), handleSubmit, handleSubmit); securityConfig.saveFirstUser($('iframe[src]').contents().find('form:not(.no-json)'), handleSubmit, handleSubmit);
}; };
var skipFirstUser = function() {
$('button').prop({disabled:true});
setPanel(setupCompletePanel, {message: translations.installWizard_firstUserSkippedMessage});
};
// call to setup the proxy // call to setup the proxy
var setupProxy = function() { var setupProxy = function() {
setPanel(proxyConfigPanel, {}, enableButtonsAfterFrameLoad); setPanel(proxyConfigPanel, {}, enableButtonsAfterFrameLoad);
...@@ -749,6 +760,7 @@ var createPluginSetupWizard = function(appendTarget) { ...@@ -749,6 +760,7 @@ var createPluginSetupWizard = function(appendTarget) {
'.resume-installation': resumeInstallation, '.resume-installation': resumeInstallation,
'.install-done-restart': restartJenkins, '.install-done-restart': restartJenkins,
'.save-first-user:not([disabled])': saveFirstUser, '.save-first-user:not([disabled])': saveFirstUser,
'.skip-first-user': skipFirstUser,
'.show-proxy-config': setupProxy, '.show-proxy-config': setupProxy,
'.save-proxy-config': saveProxyConfig, '.save-proxy-config': saveProxyConfig,
'.skip-plugin-installs': function() { installPlugins([]); } '.skip-plugin-installs': function() { installPlugins([]); }
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-link skip-first-user" disabled>
{{translations.installWizard_skipFirstUser}}
</button>
<button type="button" class="btn btn-primary save-first-user" disabled> <button type="button" class="btn btn-primary save-first-user" disabled>
{{translations.installWizard_saveFirstUser}} {{translations.installWizard_saveFirstUser}}
</button> </button>
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
<div class="modal-body"> <div class="modal-body">
<div class="jumbotron welcome-panel success-panel"> <div class="jumbotron welcome-panel success-panel">
<h1>{{translations.installWizard_installComplete_banner}}</h1> <h1>{{translations.installWizard_installComplete_banner}}</h1>
{{{message}}}
{{#if restartRequired}} {{#if restartRequired}}
<p>{{translations.installWizard_installComplete_message}} {{translations.installWizard_installComplete_restartRequiredMessage}}</p> <p>{{translations.installWizard_installComplete_message}} {{translations.installWizard_installComplete_restartRequiredMessage}}</p>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册