diff --git a/core/src/main/java/hudson/model/MyViewsProperty.java b/core/src/main/java/hudson/model/MyViewsProperty.java index 9d7b8b651d1c..71809d788eae 100644 --- a/core/src/main/java/hudson/model/MyViewsProperty.java +++ b/core/src/main/java/hudson/model/MyViewsProperty.java @@ -29,6 +29,7 @@ import hudson.Extension; import hudson.Util; import hudson.model.Descriptor.FormException; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.ACL; import hudson.util.FormValidation; import hudson.views.MyViewsTabBar; @@ -246,6 +247,11 @@ public String getDisplayName() { public UserProperty newInstance(User user) { return new MyViewsProperty(); } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Preferences.class); + } } @Override diff --git a/core/src/main/java/hudson/model/PaneStatusProperties.java b/core/src/main/java/hudson/model/PaneStatusProperties.java index 29a460349440..4807020ca714 100644 --- a/core/src/main/java/hudson/model/PaneStatusProperties.java +++ b/core/src/main/java/hudson/model/PaneStatusProperties.java @@ -2,7 +2,9 @@ import static java.lang.String.format; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.PersistedList; import java.io.IOException; import javax.servlet.http.HttpSession; @@ -56,6 +58,10 @@ public boolean isEnabled() { return false; } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Invisible.class); + } } private static class PaneStatusPropertiesSessionFallback extends PaneStatusProperties { diff --git a/core/src/main/java/hudson/model/TimeZoneProperty.java b/core/src/main/java/hudson/model/TimeZoneProperty.java index bdf39c58527e..2675448dad80 100644 --- a/core/src/main/java/hudson/model/TimeZoneProperty.java +++ b/core/src/main/java/hudson/model/TimeZoneProperty.java @@ -4,6 +4,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import hudson.Extension; import hudson.Util; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.FormValidation; import hudson.util.ListBoxModel; import hudson.util.ListBoxModel.Option; @@ -106,6 +107,10 @@ public FormValidation doCheckTimeZoneName(@QueryParameter String timeZoneName) { } } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Account.class); + } } @CheckForNull diff --git a/core/src/main/java/hudson/model/User.java b/core/src/main/java/hudson/model/User.java index a242385cb11a..e588a79b347a 100644 --- a/core/src/main/java/hudson/model/User.java +++ b/core/src/main/java/hudson/model/User.java @@ -39,13 +39,11 @@ import hudson.XmlFile; import hudson.init.InitMilestone; import hudson.init.Initializer; -import hudson.model.Descriptor.FormException; import hudson.model.listeners.SaveableListener; import hudson.security.ACL; import hudson.security.AccessControlled; import hudson.security.SecurityRealm; import hudson.security.UserMayOrMayNotExistException2; -import hudson.util.FormApply; import hudson.util.FormValidation; import hudson.util.RunList; import hudson.util.XStream2; @@ -77,7 +75,6 @@ import jenkins.security.LastGrantedAuthoritiesProperty; import jenkins.security.UserDetailsCache; import jenkins.util.SystemProperties; -import net.sf.json.JSONObject; import org.jenkinsci.Symbol; import org.kohsuke.accmod.Restricted; import org.kohsuke.accmod.restrictions.NoExternalUse; @@ -87,7 +84,6 @@ import org.kohsuke.stapler.export.Exported; import org.kohsuke.stapler.export.ExportedBean; import org.kohsuke.stapler.interceptor.RequirePOST; -import org.kohsuke.stapler.verb.POST; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; @@ -342,6 +338,29 @@ public synchronized void addProperty(@NonNull UserProperty p) throws IOException save(); } + /** + * Expand {@link #addProperty(UserProperty)} for multiple properties to be done at once. + * Expected to be used by the categorized configuration pages to update part of the properties. + * The properties not included in the list will be let untouched. + * It will call the {@link UserProperty#setUser(User)} method and at the end, {@link #save()} once. + * + * @since TODO + */ + public synchronized void addProperties(@NonNull List multipleProperties) throws IOException { + List newProperties = new ArrayList<>(this.properties); + for (UserProperty property : multipleProperties) { + UserProperty oldProp = getProperty(property.getClass()); + if (oldProp != null) { + newProperties.remove(oldProp); + } + newProperties.add(property); + property.setUser(this); + } + + this.properties = newProperties; + this.save(); + } + /** * List of all {@link UserProperty}s exposed primarily for the remoting API. */ @@ -859,48 +878,6 @@ public Api getApi() { return new Api(this); } - /** - * Accepts submission from the configuration page. - */ - @POST - public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, FormException { - checkPermission(Jenkins.ADMINISTER); - - JSONObject json = req.getSubmittedForm(); - String oldFullName = this.fullName; - fullName = json.getString("fullName"); - description = json.getString("description"); - - List props = new ArrayList<>(); - int i = 0; - for (UserPropertyDescriptor d : UserProperty.all()) { - UserProperty p = getProperty(d.clazz); - - JSONObject o = json.optJSONObject("userProperty" + i++); - if (o != null) { - if (p != null) { - p = p.reconfigure(req, o); - } else { - p = d.newInstance(req, o); - } - } - - if (p != null) { - p.setUser(this); - props.add(p); - } - } - this.properties = props; - - save(); - - if (oldFullName != null && !oldFullName.equals(this.fullName)) { - UserDetailsCache.get().invalidate(oldFullName); - } - - FormApply.success(".").generateResponse(req, rsp, this); - } - /** * Deletes this user from Hudson. */ diff --git a/core/src/main/java/hudson/model/UserProperty.java b/core/src/main/java/hudson/model/UserProperty.java index a9b9dbae7acd..6538a5fdf661 100644 --- a/core/src/main/java/hudson/model/UserProperty.java +++ b/core/src/main/java/hudson/model/UserProperty.java @@ -24,9 +24,13 @@ package hudson.model; +import edu.umd.cs.findbugs.annotations.NonNull; import hudson.DescriptorExtensionList; import hudson.ExtensionPoint; import hudson.model.Descriptor.FormException; +import hudson.model.userproperty.UserPropertyCategory; +import java.util.ArrayList; +import java.util.List; import jenkins.model.Jenkins; import net.sf.json.JSONObject; import org.kohsuke.stapler.StaplerRequest; @@ -58,6 +62,10 @@ public abstract class UserProperty implements ReconfigurableDescribable all( return Jenkins.get().getDescriptorList(UserProperty.class); } + /** + * Returns all the registered {@link UserPropertyCategory} descriptors for a given category. + * + * @since TODO + */ + public static List allByCategoryClass(@NonNull Class categoryClass) { + DescriptorExtensionList all = all(); + + List onlyForTheCategory = new ArrayList<>(all.size()); + for (UserPropertyDescriptor descriptor : all) { + if (descriptor.getUserPropertyCategory().getClass().equals(categoryClass)) { + onlyForTheCategory.add(descriptor); + } + } + + return onlyForTheCategory; + } + @Override public UserProperty reconfigure(StaplerRequest req, JSONObject form) throws FormException { return form == null ? null : getDescriptor().newInstance(req, form); diff --git a/core/src/main/java/hudson/model/UserPropertyDescriptor.java b/core/src/main/java/hudson/model/UserPropertyDescriptor.java index 22e05ea59aff..ff3171c1fbf7 100644 --- a/core/src/main/java/hudson/model/UserPropertyDescriptor.java +++ b/core/src/main/java/hudson/model/UserPropertyDescriptor.java @@ -24,6 +24,12 @@ package hudson.model; +import edu.umd.cs.findbugs.annotations.CheckForNull; +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.userproperty.UserPropertyCategory; +import java.util.Optional; +import org.jenkinsci.Symbol; + /** * {@link Descriptor} for {@link UserProperty}. * @@ -73,4 +79,51 @@ protected UserPropertyDescriptor() { public boolean isEnabled() { return true; } + + /** + * Define the category for this user property descriptor. + * + * @return never null, always the same value for a given instance of {@link Descriptor}. + * + * @since TODO + */ + public @NonNull UserPropertyCategory getUserPropertyCategory() { + // As this method is expected to be overloaded by subclasses + // the logic here is just done to support plugins with older core version + String categoryAsString = this.getUserPropertyCategoryAsString(); + if (categoryAsString != null) { + Optional firstIfFound = UserPropertyCategory.all().stream() + .filter(cat -> { + Symbol symbolAnnotation = cat.getClass().getAnnotation(Symbol.class); + if (symbolAnnotation != null) { + for (String symbolValue : symbolAnnotation.value()) { + if (symbolValue.equalsIgnoreCase(categoryAsString)) { + return true; + } + } + } + return false; + }) + .findFirst(); + if (firstIfFound.isPresent()) { + return firstIfFound.get(); + } + } + return UserPropertyCategory.get(UserPropertyCategory.Unclassified.class); + } + + /** + * Method proposed to prevent plugins to rely on too recent core version + * while keeping the possibility to use the categories. + * + * @deprecated This should only be used when the core requirement is below the version this method was added + * + * @return String name corresponding to the symbol of {@link #getUserPropertyCategory()} + * + * @since TODO + */ + @Deprecated + protected @CheckForNull String getUserPropertyCategoryAsString() { + return null; + } } diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java new file mode 100644 index 000000000000..803b7e2d3527 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategory.java @@ -0,0 +1,204 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.ExtensionList; +import hudson.ExtensionPoint; +import hudson.model.ModelObject; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.DoNotUse; + +/** + * Grouping of related {@link UserProperty}s. + * + *

+ * To facilitate the separation of the user properties into multiple pages, tabs, and so on, + * {@link UserProperty}s are classified into categories (such as "security", "preferences", as well + * as the catch-all "unclassified".) Categories themselves are extensible — plugins may introduce + * its own category as well, although that should only happen if you are creating a big enough subsystem. + * + * @since TODO + * @see UserProperty + */ +public abstract class UserPropertyCategory implements ExtensionPoint, ModelObject { + /** + * One-line plain text message that explains what this category is about. + * This can be used in the UI to help the user pick the right category. + * + * The text should be longer than {@link #getDisplayName()} + */ + public abstract String getShortDescription(); + + /** + * Returns all the registered {@link UserPropertyCategory} descriptors. + */ + public static ExtensionList all() { + return ExtensionList.lookup(UserPropertyCategory.class); + } + + public static @NonNull T get(Class type) { + T category = all().get(type); + if (category == null) { + throw new AssertionError("Category not found. It seems the " + type + " is not annotated with @Extension and so not registered"); + } + return category; + } + + /** + * This category is used when the {@link hudson.model.UserPropertyDescriptor} has not implemented + * the {@link UserPropertyDescriptor#getUserPropertyCategory()} method + * (or the getUserPropertyCategoryAsString method for compatibility reason). + *

+ * If you do not know what to use, choose the {@link Account} instead of this one. + */ + @Extension + @Symbol("unclassified") + @Restricted(DoNotUse.class) + public static class Unclassified extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Unclassified_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Unclassified_ShortDescription(); + } + } + + /** + * User property related to account settings (e.g. timezone, email, ...). + *

+ * It could be seen as the default choice for {@link UserProperty} that are defining their category. + * Currently it has the same effect as {@link Unclassified} but the behavior could change in the future. + */ + @Extension + @Symbol("account") + public static class Account extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Account_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Account_ShortDescription(); + } + } + + /** + * Preferences related configurations (e.g. notification type, default view, ...). + */ + @Extension + @Symbol("preferences") + public static class Preferences extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Preferences_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Preferences_ShortDescription(); + } + } + + /** + * Per user feature flags (e.g. new design, ...). + */ + @Extension + @Symbol("experimental") + public static class Experimental extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Experimental_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Experimental_ShortDescription(); + } + } + + /** + * User interface related configurations (e.g. theme, language, ...). + *

+ * See also {@link jenkins.appearance.AppearanceCategory}. + */ + @Extension + @Symbol("appearance") + public static class Appearance extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Appearance_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Appearance_ShortDescription(); + } + } + + + /** + * Security related configurations (e.g. API Token, SSH keys, ...). + * With this separation, we can more easily add control on their modifications. + */ + @Extension + @Symbol("security") + public static class Security extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Security_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Security_ShortDescription(); + } + } + + /** + * For user properties that are not expected to be displayed, + * typically automatically configured by automated behavior, without direct user interaction. + */ + @Extension + @Symbol("invisible") + public static class Invisible extends UserPropertyCategory { + @Override + public String getDisplayName() { + return Messages.UserPropertyCategory_Invisible_DisplayName(); + } + + @Override + public String getShortDescription() { + return Messages.UserPropertyCategory_Invisible_ShortDescription(); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java new file mode 100644 index 000000000000..822cdc6f4c99 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAccountAction.java @@ -0,0 +1,121 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.DescriptorExtensionList; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.Descriptor; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import javax.servlet.ServletException; +import jenkins.model.Jenkins; +import jenkins.security.UserDetailsCache; +import net.sf.json.JSONObject; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryAccountAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryAccountAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryAccountAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-settings" : null; + } + + @Override + public String getUrlName() { + return "account"; + } + + public @NonNull List getMyCategoryDescriptors() { + return allByTwoCategoryClasses(UserPropertyCategory.Unclassified.class, UserPropertyCategory.Account.class); + } + + private static List allByTwoCategoryClasses( + @NonNull Class categoryClass1, + @NonNull Class categoryClass2 + ) { + DescriptorExtensionList all = UserProperty.all(); + + List filteredList = new ArrayList<>(all.size()); + for (UserPropertyDescriptor descriptor : all) { + Class currClass = descriptor.getUserPropertyCategory().getClass(); + if (currClass.equals(categoryClass1) || currClass.equals(categoryClass2)) { + filteredList.add(descriptor); + } + } + + return filteredList; + } + + @POST + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + User targetUser = this.getTargetUser(); + targetUser.checkPermission(Jenkins.ADMINISTER); + + JSONObject json = req.getSubmittedForm(); + + String oldFullName = targetUser.getFullName(); + targetUser.setFullName(json.getString("fullName")); + targetUser.setDescription(json.getString("description")); + + super.doConfigSubmit(req, rsp); + + if (!oldFullName.equals(targetUser.getFullName())) { + UserDetailsCache.get().invalidate(oldFullName); + } + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 400) + @Symbol("account") + public static class AccountActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryAccountAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java new file mode 100644 index 000000000000..caec7c1bdf88 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAction.java @@ -0,0 +1,65 @@ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.model.Descriptor; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import hudson.util.FormApply; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.ServletException; +import jenkins.model.Jenkins; +import net.sf.json.JSONObject; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.verb.POST; + +public abstract class UserPropertyCategoryAction { + + private final User targetUser; + + public UserPropertyCategoryAction(User targetUser) { + this.targetUser = targetUser; + } + + public @NonNull User getTargetUser() { + return targetUser; + } + + public @NonNull abstract List getMyCategoryDescriptors(); + + @POST + public void doConfigSubmit(StaplerRequest req, StaplerResponse rsp) throws IOException, ServletException, Descriptor.FormException { + this.targetUser.checkPermission(Jenkins.ADMINISTER); + + JSONObject json = req.getSubmittedForm(); + + List props = new ArrayList<>(); + List myCategoryDescriptors = getMyCategoryDescriptors(); + int i = 0; + for (UserPropertyDescriptor d : myCategoryDescriptors) { + UserProperty p = this.targetUser.getProperty(d.clazz); + + JSONObject o = json.optJSONObject("userProperty" + i++); + if (o != null) { + if (p != null) { + p = p.reconfigure(req, o); + } else { + p = d.newInstance(req, o); + } + } + + if (p != null) { + props.add(p); + } + } + this.targetUser.addProperties(props); + + this.targetUser.save(); + + // we are in /user///, going to /user// + FormApply.success("..").generateResponse(req, rsp, this); + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java new file mode 100644 index 000000000000..88d08a8add70 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryAppearanceAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryAppearanceAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryAppearanceAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryAppearanceAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-brush-outline" : null; + } + + @Override + public String getUrlName() { + return "appearance"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Appearance.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 350) + @Symbol("appearance") + public static class AppearanceActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryAppearanceAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java new file mode 100644 index 000000000000..bb242bacad7a --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryExperimentalAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryExperimentalAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryExperimentalAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryExperimentalAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-flask" : null; + } + + @Override + public String getUrlName() { + return "experiments"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Experimental.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 100) + @Symbol("experimental") + public static class ExperimentalActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryExperimentalAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java new file mode 100644 index 000000000000..7a74b702e6c0 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategoryPreferencesAction.java @@ -0,0 +1,76 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategoryPreferencesAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategoryPreferencesAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategoryPreferencesAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-parameters" : null; + } + + @Override + public String getUrlName() { + return "preferences"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Preferences.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 300) + @Symbol("preferences") + public static class PreferencesActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategoryPreferencesAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java b/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java new file mode 100644 index 000000000000..a6cb3e6ed3c4 --- /dev/null +++ b/core/src/main/java/hudson/model/userproperty/UserPropertyCategorySecurityAction.java @@ -0,0 +1,77 @@ +/* + * The MIT License + * + * Copyright (c) 2022, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package hudson.model.userproperty; + + +import edu.umd.cs.findbugs.annotations.NonNull; +import hudson.Extension; +import hudson.model.Action; +import hudson.model.TransientUserActionFactory; +import hudson.model.User; +import hudson.model.UserProperty; +import hudson.model.UserPropertyDescriptor; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import jenkins.model.Jenkins; +import org.jenkinsci.Symbol; +import org.kohsuke.accmod.Restricted; +import org.kohsuke.accmod.restrictions.NoExternalUse; + +@Restricted(NoExternalUse.class) +public class UserPropertyCategorySecurityAction extends UserPropertyCategoryAction implements Action { + public UserPropertyCategorySecurityAction(@NonNull User user) { + super(user); + } + + @Override + public String getDisplayName() { + return Messages.UserPropertyCategorySecurityAction_DisplayName(); + } + + @Override + public String getIconFileName() { + return getTargetUser().hasPermission(Jenkins.ADMINISTER) ? "symbol-lock-closed" : null; + } + + @Override + public String getUrlName() { + return "security"; + } + + public @NonNull List getMyCategoryDescriptors() { + return UserProperty.allByCategoryClass(UserPropertyCategory.Security.class); + } + + /** + * Inject the outer class configuration page into the sidenav and the request routing of the user + */ + @Extension(ordinal = 200) + @Symbol("security") + public static class SecurityActionFactory extends TransientUserActionFactory { + public Collection createFor(User target) { + return Collections.singleton(new UserPropertyCategorySecurityAction(target)); + } + } +} diff --git a/core/src/main/java/hudson/search/UserSearchProperty.java b/core/src/main/java/hudson/search/UserSearchProperty.java index 7e9836944c0b..a3515dd08874 100644 --- a/core/src/main/java/hudson/search/UserSearchProperty.java +++ b/core/src/main/java/hudson/search/UserSearchProperty.java @@ -5,6 +5,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import net.sf.json.JSONObject; import org.jenkinsci.Symbol; import org.kohsuke.stapler.StaplerRequest; @@ -54,6 +55,10 @@ public UserProperty newInstance(StaplerRequest req, JSONObject formData) throws return new UserSearchProperty(formData.optBoolean("insensitiveSearch")); } + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Preferences.class); + } } } diff --git a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java index 53b798d941db..bd122244c7e2 100644 --- a/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java +++ b/core/src/main/java/hudson/security/HudsonPrivateSecurityRealm.java @@ -39,6 +39,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.FederatedLoginService.FederatedIdentity; import hudson.security.captcha.CaptchaSupport; import hudson.util.FormValidation; @@ -801,7 +802,6 @@ public boolean equals(Object o) { public int hashCode() { return getUsername().hashCode(); } - } public static class ConverterImpl extends XStream2.PassthruConverter

{ @@ -884,6 +884,11 @@ public boolean isEnabled() { public UserProperty newInstance(User user) { return null; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } } diff --git a/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java b/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java index 6732f2e5d696..85332d26973c 100644 --- a/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java +++ b/core/src/main/java/jenkins/model/experimentalflags/UserExperimentalFlagsProperty.java @@ -31,6 +31,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import java.util.HashMap; import java.util.Map; import net.sf.json.JSONObject; @@ -76,13 +77,19 @@ public static final class DescriptorImpl extends UserPropertyDescriptor { public UserProperty newInstance(@Nullable StaplerRequest req, @NonNull JSONObject formData) throws FormException { JSONObject flagsObj = formData.getJSONObject("flags"); Map flags = new HashMap<>(); - for (Object key : flagsObj.keySet()) { - String value = (String) flagsObj.get((String) key); + for (String key : flagsObj.keySet()) { + String value = (String) flagsObj.get(key); if (!value.isEmpty()) { - flags.put((String) key, value); + flags.put(key, value); } } return new UserExperimentalFlagsProperty(flags); } + + @NonNull + @Override + public UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Experimental.class); + } } } diff --git a/core/src/main/java/jenkins/security/ApiTokenProperty.java b/core/src/main/java/jenkins/security/ApiTokenProperty.java index 69904a0e4785..464fdcbdf16c 100644 --- a/core/src/main/java/jenkins/security/ApiTokenProperty.java +++ b/core/src/main/java/jenkins/security/ApiTokenProperty.java @@ -33,6 +33,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.ACL; import hudson.util.HttpResponses; import hudson.util.Secret; @@ -657,6 +658,11 @@ public HttpResponse doRevokeAllExcept(@AncestorInPath User u, return HttpResponses.ok(); } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } /** diff --git a/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java b/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java index 52f74d452ffa..cb8b8accf295 100644 --- a/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java +++ b/core/src/main/java/jenkins/security/LastGrantedAuthoritiesProperty.java @@ -6,6 +6,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.security.SecurityRealm; import java.io.IOException; import java.util.ArrayList; @@ -171,6 +172,11 @@ public boolean isEnabled() { public UserProperty newInstance(User user) { return null; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Invisible.class); + } } private static final Logger LOGGER = Logger.getLogger(LastGrantedAuthoritiesProperty.class.getName()); diff --git a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java index d7420910cb64..968ee9320f58 100644 --- a/core/src/main/java/jenkins/security/seed/UserSeedProperty.java +++ b/core/src/main/java/jenkins/security/seed/UserSeedProperty.java @@ -31,6 +31,7 @@ import hudson.model.User; import hudson.model.UserProperty; import hudson.model.UserPropertyDescriptor; +import hudson.model.userproperty.UserPropertyCategory; import hudson.util.HttpResponses; import java.io.IOException; import java.security.SecureRandom; @@ -153,5 +154,10 @@ public synchronized HttpResponse doRenewSessionSeed(@AncestorInPath @NonNull Use public boolean isEnabled() { return !DISABLE_USER_SEED && !HIDE_USER_SEED_SECTION; } + + @Override + public @NonNull UserPropertyCategory getUserPropertyCategory() { + return UserPropertyCategory.get(UserPropertyCategory.Security.class); + } } } diff --git a/core/src/main/resources/hudson/model/Messages.properties b/core/src/main/resources/hudson/model/Messages.properties index 9cd382511856..d56c57ff5ee0 100644 --- a/core/src/main/resources/hudson/model/Messages.properties +++ b/core/src/main/resources/hudson/model/Messages.properties @@ -422,3 +422,5 @@ ManagementLink.Category.MISC=Other ManagementLink.Category.UNCATEGORIZED=Uncategorized FileParameterValue.IndexTitle=File Parameters + +UserPreferencesProperty.DisplayName=Preferences diff --git a/core/src/main/resources/hudson/model/User/configure.jelly b/core/src/main/resources/hudson/model/User/configure.jelly deleted file mode 100644 index 9b4100248559..000000000000 --- a/core/src/main/resources/hudson/model/User/configure.jelly +++ /dev/null @@ -1,67 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/core/src/main/resources/hudson/model/User/sidepanel.jelly b/core/src/main/resources/hudson/model/User/sidepanel.jelly index 834061995daf..f8024b0c21b8 100644 --- a/core/src/main/resources/hudson/model/User/sidepanel.jelly +++ b/core/src/main/resources/hudson/model/User/sidepanel.jelly @@ -33,7 +33,6 @@ THE SOFTWARE. - diff --git a/core/src/main/resources/hudson/model/userproperty/Messages.properties b/core/src/main/resources/hudson/model/userproperty/Messages.properties new file mode 100644 index 000000000000..5e52b8d2906c --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/Messages.properties @@ -0,0 +1,48 @@ +# The MIT License +# +# Copyright (c) 2022, CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +UserPropertyCategory.Unclassified.DisplayName=Unclassified +UserPropertyCategory.Unclassified.ShortDescription=User properties without a category yet + +UserPropertyCategory.Account.DisplayName=Account +UserPropertyCategory.Account.ShortDescription=User properties related to the user account configuration (e.g. timezone, email, ...) + +UserPropertyCategory.Preferences.DisplayName=Preferences +UserPropertyCategory.Preferences.ShortDescription=User properties related to the user preferences (e.g. notification type, default view, ...) + +UserPropertyCategory.Experimental.DisplayName=Experiments +UserPropertyCategory.Experimental.ShortDescription=Per user flags to enable/disable experimental features (e.g. new design, ...) + +UserPropertyCategory.Appearance.DisplayName=Appearance +UserPropertyCategory.Appearance.ShortDescription=User properties related to the appearance of Jenkins + +UserPropertyCategory.Security.DisplayName=Security +UserPropertyCategory.Security.ShortDescription=User properties related to the security of the user account (e.g. API token, SSH keys, ...) + +UserPropertyCategory.Invisible.DisplayName=Invisible +UserPropertyCategory.Invisible.ShortDescription=User properties that do not require a configuration page + +UserPropertyCategoryAccountAction.DisplayName=Account +UserPropertyCategoryAppearanceAction.DisplayName=Appearance +UserPropertyCategoryExperimentalAction.DisplayName=Experiments +UserPropertyCategoryPreferencesAction.DisplayName=Preferences +UserPropertyCategorySecurityAction.DisplayName=Security diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly new file mode 100644 index 000000000000..8d2a8e9368e7 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.jelly @@ -0,0 +1,72 @@ + + + + + + + + + +

+ ${%title} +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+
+
diff --git a/core/src/main/resources/jenkins/model/experimentalflags/Messages_sv_SE.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.properties similarity index 94% rename from core/src/main/resources/jenkins/model/experimentalflags/Messages_sv_SE.properties rename to core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.properties index 4f1b584608af..41e4d5b9689f 100644 --- a/core/src/main/resources/jenkins/model/experimentalflags/Messages_sv_SE.properties +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index.properties @@ -20,4 +20,6 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -UserExperimentalFlagsProperty.DisplayName=Experiment +title=Account +Full\ name=Full Name +Description=Description diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_bg.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_bg.properties new file mode 100644 index 000000000000..8654e841998b --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_bg.properties @@ -0,0 +1,28 @@ +# The MIT License +# +# Bulgarian translation: Copyright (c) 2015, 2016, Alexander Shopov +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=\ + Описание +Full\ name=\ + Пълно име +Save=\ + Запазване diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ca.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ca.properties new file mode 100644 index 000000000000..aad7c2e559ef --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ca.properties @@ -0,0 +1,4 @@ +# This file is under the MIT License by authors + +Description=Descripció +Full\ name=Nom diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_cs.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_cs.properties new file mode 100644 index 000000000000..541815f7d164 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_cs.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Popis +Save=Uložit +Full\ name=Jméno diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_da.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_da.properties new file mode 100644 index 000000000000..a5abfe2acc7a --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_da.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. Kohsuke Kawaguchi. Knud Poulsen. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Dit navn +Save=Gem +Description=Beskrivelse diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_de.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_de.properties new file mode 100644 index 000000000000..06240b1aa6ce --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_de.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Simon Wiest +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Ihr Name +Description=Beschreibung +Save=Speichern diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_es.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_es.properties new file mode 100644 index 000000000000..f7839a14fe3d --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_es.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Nombre +Save=Guardar +Description=Descripción + diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fi.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fi.properties new file mode 100644 index 000000000000..03769c1d17c4 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fi.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Kuvaus +Save=Tallenna diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fr.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fr.properties new file mode 100644 index 000000000000..3b677fa5d67b --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_fr.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Eric Lefevre-Ardant +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Votre nom +Description=Présentation +Save=Sauvegarder diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_hu.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_hu.properties new file mode 100644 index 000000000000..6e8cb34dc914 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_hu.properties @@ -0,0 +1,4 @@ +# This file is under the MIT License by authors + +Description=Leírás +Full\ name=Ön neve diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_it.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_it.properties new file mode 100644 index 000000000000..d3523f2f3116 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_it.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Italian localization plugin for Jenkins +# Copyright © 2020 Alessandro Menti +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Descrizione +Full\ name=Nome completo +Save=Salva diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ja.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ja.properties new file mode 100644 index 000000000000..be1c04668bbf --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ja.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Seiji Sogabe, id:cactusman +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=あなたの名前 +Description=説明 +Save=保存 diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ko.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ko.properties new file mode 100644 index 000000000000..fd0ca539d7d9 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ko.properties @@ -0,0 +1,4 @@ +# This file is under the MIT License by authors + +Description=소개 +Full\ name=이름 diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_lv.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_lv.properties new file mode 100644 index 000000000000..b16f28220290 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_lv.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Tavs vārds +description.title=Apraksts +Save=Saglabāt diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nb_NO.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nb_NO.properties new file mode 100644 index 000000000000..58a3343fb3d8 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nb_NO.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Beskrivelse +Save=Lagre +Full\ name=Ditt navn diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nl.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nl.properties new file mode 100644 index 000000000000..7756763a1a74 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_nl.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, id:sorokh +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Uw naam +Description=Omschrijving +Save=Opslaan diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pl.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pl.properties new file mode 100644 index 000000000000..f90e9574abde --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pl.properties @@ -0,0 +1,26 @@ +# The MIT License +# +# Copyright (c) 2004-2016, Sun Microsystems, Damian Szczepanik +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Opis +Full\ name=Twoje imię i nazwisko +# User ‘{0}’ Configuration +Save=Zapisz diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pt_BR.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pt_BR.properties new file mode 100644 index 000000000000..c46179879578 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_pt_BR.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Reginaldo L. Russinholi, Cleiber Silva +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Seu nome +Description=Descrição +Save=Salvar diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ru.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ru.properties new file mode 100644 index 000000000000..b05ddbbb49a8 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_ru.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Mike Salnikov +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=Полное имя +Description=Описание +Save=Сохранить diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sk.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sk.properties new file mode 100644 index 000000000000..8c8f98e91b07 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sk.properties @@ -0,0 +1,4 @@ +# This file is under the MIT License by authors + +Description=Popis +Full\ name=Meno diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sr.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sr.properties new file mode 100644 index 000000000000..241621057f54 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sr.properties @@ -0,0 +1,5 @@ +# This file is under the MIT License by authors + +Full\ name=Име и презиме +Description=Опис +Save=Сачувај diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sv_SE.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sv_SE.properties new file mode 100644 index 000000000000..6e75a39365c2 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_sv_SE.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2010, Sun Microsystems, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Description=Beskrivning +Save=Spara +Full\ name=Ditt namn diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_tr.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_tr.properties new file mode 100644 index 000000000000..ead6d67dee06 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_tr.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2009, Sun Microsystems, Inc., Kohsuke Kawaguchi, Oguz Dag +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +Full\ name=İsminiz +Description=Açıklama +Save=Kaydet diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_uk.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_uk.properties new file mode 100644 index 000000000000..3dc2751ccdeb --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_uk.properties @@ -0,0 +1,4 @@ +# This file is under the MIT License by authors + +Description=Опис +Full\ name=Ваше ім''я diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_zh_TW.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_zh_TW.properties new file mode 100644 index 000000000000..8a05a4258d59 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAccountAction/index_zh_TW.properties @@ -0,0 +1,25 @@ +# The MIT License +# +# Copyright (c) 2004-2013, Sun Microsystems, Inc., Chunghwa Telecom Co., Ltd., +# and Pei-Tang Huang +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +Full\ name=全名 +Description=說明 +Save=儲存 diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.jelly b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.jelly new file mode 100644 index 000000000000..0d90ad4b2d76 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.jelly @@ -0,0 +1,74 @@ + + + + + + + + + +

+ ${%title} +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ ${%warningNoItems} +
+
+
+ + + + + +
+ +
+
+
diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.properties new file mode 100644 index 000000000000..f24a3f6e3851 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryAppearanceAction/index.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2022, CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +title=Appearance +warningNoItems=No appearance items are available for configuration. diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly new file mode 100644 index 000000000000..0d90ad4b2d76 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.jelly @@ -0,0 +1,74 @@ + + + + + + + + + +

+ ${%title} +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ ${%warningNoItems} +
+
+
+ + + + + +
+ +
+
+
diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.properties new file mode 100644 index 000000000000..4e5e6b02073d --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryExperimentalAction/index.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2022, CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +title=Experiments +warningNoItems=No experiments are currently available. diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.jelly b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.jelly new file mode 100644 index 000000000000..6971e5abf8d0 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.jelly @@ -0,0 +1,74 @@ + + + + + + + + + +

+ ${%title} +

+ + + + + + + + + + + + + + + + + + + + + + + +
+ ${%warningNoItems} +
+
+
+ + + + + +
+ +
+
+
diff --git a/core/src/main/resources/jenkins/model/experimentalflags/Messages_fr.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.properties similarity index 94% rename from core/src/main/resources/jenkins/model/experimentalflags/Messages_fr.properties rename to core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.properties index 8e48740af070..89bd19371237 100644 --- a/core/src/main/resources/jenkins/model/experimentalflags/Messages_fr.properties +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategoryPreferencesAction/index.properties @@ -20,4 +20,5 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -UserExperimentalFlagsProperty.DisplayName=Expérimentations +title=Preferences +warningNoItems=No preferences available. diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.jelly b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.jelly new file mode 100644 index 000000000000..0d90501fbbb0 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.jelly @@ -0,0 +1,75 @@ + + + + + + + + + +

+ ${%title} +

+ + + + + + + + + + + + + + + + + + + + + + + + +
+ ${%warningNoItems} +
+
+
+ + + + + +
+ +
+
+
diff --git a/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.properties b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.properties new file mode 100644 index 000000000000..be9c8e93e5f2 --- /dev/null +++ b/core/src/main/resources/hudson/model/userproperty/UserPropertyCategorySecurityAction/index.properties @@ -0,0 +1,24 @@ +# The MIT License +# +# Copyright (c) 2022, CloudBees, Inc. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. + +title=Security +warningNoItems=No security configuration available. diff --git a/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/index.jelly b/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/index.jelly index 88939feeaca3..559e2370a720 100644 --- a/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/index.jelly +++ b/core/src/main/resources/hudson/security/HudsonPrivateSecurityRealm/index.jelly @@ -63,7 +63,7 @@ THE SOFTWARE. diff --git a/core/src/main/resources/jenkins/model/experimentalflags/Messages.properties b/core/src/main/resources/jenkins/model/experimentalflags/Messages.properties index ddf8f546e32b..13e00e615459 100644 --- a/core/src/main/resources/jenkins/model/experimentalflags/Messages.properties +++ b/core/src/main/resources/jenkins/model/experimentalflags/Messages.properties @@ -20,4 +20,4 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. -UserExperimentalFlagsProperty.DisplayName=Experiments +UserExperimentalFlagsProperty.DisplayName=Feature preview diff --git a/core/src/main/resources/jenkins/model/experimentalflags/UserExperimentalFlagsProperty/config.jelly b/core/src/main/resources/jenkins/model/experimentalflags/UserExperimentalFlagsProperty/config.jelly index 4fe6097089bb..a70fddf3403e 100644 --- a/core/src/main/resources/jenkins/model/experimentalflags/UserExperimentalFlagsProperty/config.jelly +++ b/core/src/main/resources/jenkins/model/experimentalflags/UserExperimentalFlagsProperty/config.jelly @@ -40,7 +40,7 @@ THE SOFTWARE. ${%FlagDisplayName} - ${%FlagDescription} + ${%FlagDescription} ${%FlagConfig} diff --git a/test/src/test/java/hudson/model/UserPropertyTest.java b/test/src/test/java/hudson/model/UserPropertyTest.java index 0d2b7d5b1374..91c977d4ec28 100644 --- a/test/src/test/java/hudson/model/UserPropertyTest.java +++ b/test/src/test/java/hudson/model/UserPropertyTest.java @@ -6,6 +6,7 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; +import static org.htmlunit.html.HtmlFormUtil.submit; import static org.junit.Assert.assertNotNull; import java.io.File; @@ -35,12 +36,17 @@ public class UserPropertyTest { @Rule public JenkinsRule j = new JenkinsRule(); + public User configRoundtrip(User u) throws Exception { + submit(j.createWebClient().goTo(u.getUrl()+"/account/").getFormByName("config")); + return u; + } + @Test @Issue("JENKINS-9062") public void test() throws Exception { User u = User.get("foo"); u.addProperty(new UserProperty1()); - j.configRoundtrip(u); + configRoundtrip(u); for (UserProperty p : u.getAllProperties()) assertNotNull(p); } @@ -82,7 +88,7 @@ public void nestedUserReference() throws Exception { List fileLines = Files.readAllLines(testFile.toPath(), StandardCharsets.US_ASCII); assertThat(fileLines, hasSize(1)); - j.configRoundtrip(user); + configRoundtrip(user); user = User.get("nestedUserReference", false, Collections.emptyMap()); assertThat("nested reference should exist after user configuration change", user, nestedUserSet()); diff --git a/test/src/test/java/hudson/model/UserTest.java b/test/src/test/java/hudson/model/UserTest.java index 4f5d6e8f4365..b27adbdc15e7 100644 --- a/test/src/test/java/hudson/model/UserTest.java +++ b/test/src/test/java/hudson/model/UserTest.java @@ -64,12 +64,14 @@ import jenkins.model.IdStrategy; import jenkins.model.Jenkins; import jenkins.security.ApiTokenProperty; +import org.htmlunit.FailingHttpStatusCodeException; import org.htmlunit.WebAssert; import org.htmlunit.WebRequest; import org.htmlunit.WebResponse; import org.htmlunit.html.HtmlForm; import org.htmlunit.html.HtmlPage; import org.htmlunit.util.WebConnectionWrapper; +import org.jenkinsci.plugins.matrixauth.PermissionEntry; import org.junit.Rule; import org.junit.Test; import org.junit.experimental.categories.Category; @@ -403,20 +405,23 @@ public void testDoConfigSubmit() throws Exception { User user = realm.createAccount("John Smith", "password"); User user2 = realm.createAccount("John Smith2", "password"); user2.save(); - auth.add(Jenkins.ADMINISTER, user.getId()); - auth.add(Jenkins.READ, user2.getId()); + auth.add(Jenkins.ADMINISTER, PermissionEntry.user(user.getId())); + auth.add(Jenkins.READ, PermissionEntry.user(user2.getId())); SecurityContextHolder.getContext().setAuthentication(user.impersonate2()); - HtmlForm form = j.createWebClient().withBasicCredentials(user.getId(), "password").goTo(user2.getUrl() + "/configure").getFormByName("config"); + HtmlForm form = j.createWebClient().withBasicCredentials(user.getId(), "password").goTo(user2.getUrl() + "/account/").getFormByName("config"); form.getInputByName("_.fullName").setValue("Alice Smith"); j.submit(form); assertEquals("User should have full name Alice Smith.", "Alice Smith", user2.getFullName()); SecurityContextHolder.getContext().setAuthentication(user2.impersonate2()); - assertThrows("User should not have permission to configure another user.", AccessDeniedException3.class, () -> user.doConfigSubmit(null, null)); - form = j.createWebClient().withBasicCredentials(user2.getId(), "password").goTo(user2.getUrl() + "/configure").getFormByName("config"); + try (JenkinsRule.WebClient webClient = j.createWebClient().withBasicCredentials(user2.getId(), "password")) { + FailingHttpStatusCodeException failingHttpStatusCodeException = assertThrows("User should not have permission to configure another user.", FailingHttpStatusCodeException.class, () -> webClient.goTo(user.getUrl() + "/account/")); + assertThat(failingHttpStatusCodeException.getStatusCode(), is(403)); + form = webClient.goTo(user2.getUrl() + "/account/").getFormByName("config"); + form.getInputByName("_.fullName").setValue("John"); + j.submit(form); + } - form.getInputByName("_.fullName").setValue("John"); - j.submit(form); - assertEquals("User should be albe to configure himself.", "John", user2.getFullName()); + assertEquals("User should be able to configure himself.", "John", user2.getFullName()); } @@ -771,7 +776,7 @@ public WebResponse getResponse(WebRequest request) throws IOException { return r; } }; - wc.login("alice").goTo("me/configure"); + wc.login("alice").goTo("me/account/"); assertThat(failingResources, empty()); } diff --git a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java index d0f58f92d5ec..92745bf5f9b0 100644 --- a/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java +++ b/test/src/test/java/hudson/security/HudsonPrivateSecurityRealmTest.java @@ -651,7 +651,7 @@ public void changingPassword_mustInvalidateAllSessions() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); HtmlPasswordInput password1 = configurePage.getElementByName("user.password"); HtmlPasswordInput password2 = configurePage.getElementByName("user.password2"); @@ -683,7 +683,7 @@ public void notChangingPassword_hasNoImpactOnSeed() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); // not changing password this time HtmlForm form = configurePage.getFormByName("config"); j.submit(form); @@ -713,7 +713,7 @@ public void changingPassword_withSeedDisable_hasNoImpact() throws Exception { wc_anotherTab.login(alice.getId()); assertUserConnected(wc_anotherTab, alice.getId()); - HtmlPage configurePage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage configurePage = wc.goTo(alice.getUrl() + "/security/"); HtmlPasswordInput password1 = configurePage.getElementByName("user.password"); HtmlPasswordInput password2 = configurePage.getElementByName("user.password2"); diff --git a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java index 59f89e8f4977..c746fc7cc4d5 100644 --- a/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java +++ b/test/src/test/java/jenkins/security/ApiCrumbExclusionTest.java @@ -108,7 +108,7 @@ private void makeRequestAndFail(int expectedCode) { } private void checkWeCanChangeMyDescription(int expectedCode) throws IOException, SAXException { - HtmlPage page = wc.goTo("me/configure"); + HtmlPage page = wc.goTo("me/account/"); HtmlForm form = page.getFormByName("config"); form.getTextAreaByName("_.description").setText("random description: " + Math.random()); diff --git a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java index 30361ed8658c..162ac231b664 100644 --- a/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java +++ b/test/src/test/java/jenkins/security/ApiTokenPropertyTest.java @@ -80,7 +80,7 @@ public void basics() throws Exception { assertEquals(u, wc.executeOnServer(User::current)); // Make sure the UI shows the token to the user - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); HtmlForm form = config.getFormByName("config"); assertEquals(token, form.getInputByName("_.apiToken").getValue()); @@ -126,7 +126,7 @@ public void adminsShouldBeUnableToSeeTokensByDefault() throws Exception { // Make sure the UI does not show the token to another user WebClient wc = createClientForUser("bar"); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); HtmlForm form = config.getFormByName("config"); assertEquals(Messages.ApiTokenProperty_ChangeToken_TokenIsHidden(), form.getInputByName("_.apiToken").getValue()); } diff --git a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java index 873194dfb089..940715b0fe6a 100644 --- a/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java +++ b/test/src/test/java/jenkins/security/BasicHeaderApiTokenAuthenticatorTest.java @@ -70,7 +70,7 @@ public void legacyToken_regularCase() throws Throwable { // default SecurityListener will save the user when adding the LastGrantedAuthoritiesProperty // and so the user is persisted wc.login("user1"); - HtmlPage page = wc.goTo("user/user1/configure"); + HtmlPage page = wc.goTo("user/user1/security/"); String tokenValue = ((HtmlTextInput) page.getDocumentElement().querySelector("#apiToken")).getText(); token.set(tokenValue); } @@ -118,7 +118,7 @@ public void legacyToken_withoutLastGrantedAuthorities() throws Throwable { { JenkinsRule.WebClient wc = j.createWebClient(); wc.login("user1"); - HtmlPage page = wc.goTo("user/user1/configure"); + HtmlPage page = wc.goTo("user/user1/security/"); String tokenValue = ((HtmlTextInput) page.getDocumentElement().querySelector("#apiToken")).getText(); token.set(tokenValue); } diff --git a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java index 4d29e609860f..5c1c7318c3a9 100644 --- a/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java +++ b/test/src/test/java/jenkins/security/LastGrantedAuthoritiesPropertyTest.java @@ -43,7 +43,7 @@ public void basicFlow() throws Exception { assertAuthorities(u.impersonate2(), "alice:authenticated:development:us"); // visiting the configuration page shouldn't change authorities - HtmlPage pg = wc.goTo("user/alice/configure"); + HtmlPage pg = wc.goTo("user/alice/account/"); j.submit(pg.getFormByName("config")); p = u.getProperty(LastGrantedAuthoritiesProperty.class); diff --git a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java index ea1dec6081ae..d76d382e10c1 100644 --- a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java +++ b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsRestartTest.java @@ -103,7 +103,7 @@ public void roundtripWithRestart() throws Throwable { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue.get()); checkUserIsConnected(restWc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid.get())); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenName)); @@ -113,7 +113,7 @@ public void roundtripWithRestart() throws Throwable { restWc.goToXml("whoAmI/api/xml"); } - HtmlPage configWithStats = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithStats = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithStats.getWebResponse().getStatusCode()); HtmlSpan useCounterSpan = configWithStats.getDocumentElement().getOneHtmlElementByAttribute("span", "class", "token-use-counter"); assertThat(useCounterSpan.getTextContent(), containsString("" + NUM_CALL_WITH_TOKEN)); @@ -131,7 +131,7 @@ public void roundtripWithRestart() throws Throwable { WebClient wc = j.createWebClient().login(u.getId()); checkUserIsConnected(wc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid.get())); assertThat(config.getWebResponse().getContentAsString(), containsString(TOKEN_NAME)); @@ -144,7 +144,7 @@ public void roundtripWithRestart() throws Throwable { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue.get()); checkUserIsNotConnected(restWc); - HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithoutToken.getWebResponse().getStatusCode()); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenUuid.get()))); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(TOKEN_NAME))); diff --git a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java index 68185e6efac3..0eb010e77d77 100644 --- a/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java +++ b/test/src/test/java/jenkins/security/apitoken/ApiTokenStatsTest.java @@ -91,7 +91,7 @@ public void roundtrip() throws Exception { WebClient restWc = j.createWebClient().withBasicCredentials(u.getId(), tokenValue); checkUserIsConnected(restWc, u.getId()); - HtmlPage config = wc.goTo(u.getUrl() + "/configure"); + HtmlPage config = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, config.getWebResponse().getStatusCode()); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenUuid)); assertThat(config.getWebResponse().getContentAsString(), containsString(tokenName)); @@ -102,7 +102,7 @@ public void roundtrip() throws Exception { restWc.goToXml("whoAmI/api/xml"); } - HtmlPage configWithStats = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithStats = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithStats.getWebResponse().getStatusCode()); HtmlSpan useCounterSpan = configWithStats.getDocumentElement().getOneHtmlElementByAttribute("span", "class", "token-use-counter"); assertThat(useCounterSpan.getTextContent(), containsString("" + NUM_CALL_WITH_TOKEN)); @@ -112,7 +112,7 @@ public void roundtrip() throws Exception { // token is no more valid checkUserIsNotConnected(restWc); - HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/configure"); + HtmlPage configWithoutToken = wc.goTo(u.getUrl() + "/security/"); assertEquals(200, configWithoutToken.getWebResponse().getStatusCode()); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenUuid))); assertThat(configWithoutToken.getWebResponse().getContentAsString(), not(containsString(tokenName))); diff --git a/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java b/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java index d87761ad391c..a9a3c8830a53 100644 --- a/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java +++ b/test/src/test/java/jenkins/security/seed/UserSeedPropertyTest.java @@ -256,7 +256,7 @@ public void userSeedSection_isCorrectlyDisplayed() throws Exception { User alice = User.getById(ALICE, false); assertNotNull(alice); - HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/security/"); htmlPage.getDocumentElement().getOneHtmlElementByAttribute("div", "class", "user-seed-panel"); } @@ -280,7 +280,7 @@ public void userSeedSection_isCorrectlyHidden_withSpecificSetting() throws Excep User alice = User.getById(ALICE, false); assertNotNull(alice); - HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/configure"); + HtmlPage htmlPage = wc.goTo(alice.getUrl() + "/security/"); assertThrows("Seed section should not be displayed", ElementNotFoundException.class, () -> htmlPage.getDocumentElement().getOneHtmlElementByAttribute("div", "class", "user-seed-panel")); } finally { diff --git a/war/src/main/resources/images/symbols/flask.svg b/war/src/main/resources/images/symbols/flask.svg new file mode 100644 index 000000000000..9c4c478d820d --- /dev/null +++ b/war/src/main/resources/images/symbols/flask.svg @@ -0,0 +1 @@ +Flask \ No newline at end of file