mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-02 11:35:57 +01:00
Add cli commands for users and groups (#1993)
Adds cli commands to manage users and groups. Co-authored-by: Matthias Thieroff <matthias.thieroff@cloudogu.com>
This commit is contained in:
@@ -1,2 +1,2 @@
|
||||
- type: added
|
||||
description: Add cli support with repository actions ([#1987](https://github.com/scm-manager/scm-manager/pull/1987))
|
||||
description: Add cli support for repositories, users and groups ([#1987](https://github.com/scm-manager/scm-manager/pull/1987), [#1993](https://github.com/scm-manager/scm-manager/pull/1993))
|
||||
|
||||
@@ -111,7 +111,15 @@ public class TemplateRenderer {
|
||||
* @return table for templating content
|
||||
*/
|
||||
public Table createTable() {
|
||||
return new Table(getSpecOrDie().resourceBundle());
|
||||
return new Table(getBundle());
|
||||
}
|
||||
|
||||
protected CliContext getContext() {
|
||||
return context;
|
||||
}
|
||||
|
||||
protected ResourceBundle getBundle() {
|
||||
return getSpecOrDie().resourceBundle();
|
||||
}
|
||||
|
||||
private CommandLine.Model.CommandSpec getSpecOrDie() {
|
||||
@@ -137,7 +145,7 @@ public class TemplateRenderer {
|
||||
UnaryOperator<String> upper = value -> value.toUpperCase(context.getLocale());
|
||||
finalModel.put("upper", upper);
|
||||
|
||||
ResourceBundle resourceBundle = getSpecOrDie().resourceBundle();
|
||||
ResourceBundle resourceBundle = getBundle();
|
||||
if (resourceBundle != null) {
|
||||
finalModel.put("i18n", new I18n(resourceBundle));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.repository.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "group")
|
||||
public class GroupCommand {}
|
||||
30
scm-core/src/main/java/sonia/scm/user/cli/UserCommand.java
Normal file
30
scm-core/src/main/java/sonia/scm/user/cli/UserCommand.java
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
@CommandLine.Command(name = "user")
|
||||
public class UserCommand {}
|
||||
@@ -49,7 +49,12 @@ class CommandValidatorTest {
|
||||
|
||||
@Test
|
||||
void shouldValidateCommand() {
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle("sonia.scm.cli.i18n", Locale.ENGLISH);
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle("sonia.scm.cli.i18n", Locale.ENGLISH, new ResourceBundle.Control() {
|
||||
@Override
|
||||
public Locale getFallbackLocale(String baseName, Locale locale) {
|
||||
return Locale.ROOT;
|
||||
}
|
||||
});
|
||||
when(context.getLocale()).thenReturn(Locale.ENGLISH);
|
||||
CommandLine commandLine = new CommandLine(Command.class, new TestingCommandFactory());
|
||||
commandLine.setResourceBundle(resourceBundle);
|
||||
@@ -63,7 +68,12 @@ class CommandValidatorTest {
|
||||
|
||||
@Test
|
||||
void shouldValidateCommandWithGermanLocale() {
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle("sonia.scm.cli.i18n", Locale.GERMAN);
|
||||
ResourceBundle resourceBundle = ResourceBundle.getBundle("sonia.scm.cli.i18n", Locale.GERMAN, new ResourceBundle.Control() {
|
||||
@Override
|
||||
public Locale getFallbackLocale(String baseName, Locale locale) {
|
||||
return Locale.ROOT;
|
||||
}
|
||||
});
|
||||
when(context.getLocale()).thenReturn(Locale.GERMAN);
|
||||
CommandLine commandLine = new CommandLine(Command.class, new TestingCommandFactory());
|
||||
commandLine.setResourceBundle(resourceBundle);
|
||||
@@ -79,7 +89,7 @@ class CommandValidatorTest {
|
||||
public static class Command implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private CommandValidator commandValidator;
|
||||
private final CommandValidator commandValidator;
|
||||
|
||||
@Email
|
||||
@CommandLine.Option(names = "--mail")
|
||||
|
||||
@@ -29,6 +29,7 @@ import picocli.AutoComplete;
|
||||
import picocli.CommandLine;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
public class CliProcessor {
|
||||
@@ -50,7 +51,7 @@ public class CliProcessor {
|
||||
CommandFactory factory = new CommandFactory(injector, context);
|
||||
CommandLine cli = new CommandLine(ScmManagerCommand.class, factory);
|
||||
cli.getCommandSpec().addMixin("help", usageHelp);
|
||||
cli.setResourceBundle(ResourceBundle.getBundle("sonia.scm.cli.i18n", context.getLocale()));
|
||||
cli.setResourceBundle(getBundle("sonia.scm.cli.i18n", context.getLocale()));
|
||||
for (RegisteredCommandNode c : registry.createCommandTree()) {
|
||||
CommandLine commandline = createCommandline(context, factory, c);
|
||||
cli.getCommandSpec().addSubcommand(c.getName(), commandline);
|
||||
@@ -69,7 +70,7 @@ public class CliProcessor {
|
||||
ResourceBundle resourceBundle = commandLine.getCommandSpec().resourceBundle();
|
||||
if (resourceBundle != null) {
|
||||
String resourceBundleBaseName = resourceBundle.getBaseBundleName();
|
||||
commandLine.setResourceBundle(ResourceBundle.getBundle(resourceBundleBaseName, context.getLocale()));
|
||||
commandLine.setResourceBundle(getBundle(resourceBundleBaseName, context.getLocale()));
|
||||
}
|
||||
for (RegisteredCommandNode child : command.getChildren()) {
|
||||
if (!commandLine.getCommandSpec().subcommands().containsKey(child.getName())) {
|
||||
@@ -80,4 +81,13 @@ public class CliProcessor {
|
||||
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
private ResourceBundle getBundle(String baseName, Locale locale) {
|
||||
return ResourceBundle.getBundle(baseName, locale, new ResourceBundle.Control() {
|
||||
@Override
|
||||
public Locale getFallbackLocale(String baseName, Locale locale) {
|
||||
return Locale.ROOT;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "add-member", aliases = "add")
|
||||
class GroupAddMemberCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", arity = "1", descriptionKey = "scm.group.add-member.name")
|
||||
private String name;
|
||||
@CommandLine.Parameters(index = "1..", arity = "1..", descriptionKey = "scm.group.add-member.members")
|
||||
private String[] members;
|
||||
|
||||
@Inject
|
||||
GroupAddMemberCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Group existingGroup = manager.get(name);
|
||||
if (existingGroup == null) {
|
||||
templateRenderer.renderNotFoundError();
|
||||
} else {
|
||||
Arrays.stream(members).forEach(existingGroup::add);
|
||||
manager.modify(existingGroup);
|
||||
Group modifiedGroup = manager.get(name);
|
||||
templateRenderer.render(modifiedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setMembers(String[] members) {
|
||||
this.members = members;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
class GroupCommandBean {
|
||||
|
||||
private String name;
|
||||
private String description;
|
||||
private List<String> members;
|
||||
private String membersList;
|
||||
private boolean external;
|
||||
private String creationDate;
|
||||
private String lastModified;
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.mapstruct.AfterMapping;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import org.mapstruct.MappingTarget;
|
||||
import sonia.scm.group.Group;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Mapper
|
||||
interface GroupCommandBeanMapper {
|
||||
|
||||
@Mapping(target = "membersList", ignore = true)
|
||||
GroupCommandBean map(Group group);
|
||||
|
||||
@AfterMapping
|
||||
default void mapMembersList(@MappingTarget GroupCommandBean bean) {
|
||||
if (bean.getMembers() != null) {
|
||||
bean.setMembersList(String.join(", ", bean.getMembers()));
|
||||
}
|
||||
}
|
||||
|
||||
default String mapTimestampToISODate(Long timestamp) {
|
||||
if (timestamp != null) {
|
||||
return DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(timestamp));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "create")
|
||||
class GroupCreateCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@CommandLine.Parameters(descriptionKey = "scm.group.create.name")
|
||||
private String name;
|
||||
|
||||
@CommandLine.Option(names = {"--description", "-d"}, descriptionKey = "scm.group.create.desc")
|
||||
private String description;
|
||||
|
||||
@CommandLine.Option(names = {"--member", "-m"}, descriptionKey = "scm.group.create.member")
|
||||
private String[] members;
|
||||
|
||||
@CommandLine.Option(names = {"--external", "-e"}, descriptionKey = "scm.group.create.external")
|
||||
private boolean external;
|
||||
|
||||
@Inject
|
||||
GroupCreateCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Group newGroup = new Group("xml", name, members);
|
||||
newGroup.setDescription(description);
|
||||
newGroup.setExternal(external);
|
||||
Group createdGroup = manager.create(newGroup);
|
||||
templateRenderer.render(createdGroup);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setMembers(String[] members) {
|
||||
this.members = members;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
|
||||
@CommandLine.Command(name = "delete", aliases = "rm")
|
||||
@ParentCommand(GroupCommand.class)
|
||||
class GroupDeleteCommand implements Runnable {
|
||||
|
||||
private static final String PROMPT_TEMPLATE = "{{i18n.groupDeletePrompt}}";
|
||||
|
||||
@CommandLine.Parameters(descriptionKey = "scm.group.delete.group", paramLabel = "name")
|
||||
private String name;
|
||||
|
||||
@CommandLine.Option(names = {"--yes", "-y"}, descriptionKey = "scm.group.delete.prompt")
|
||||
private boolean shouldDelete;
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@Inject
|
||||
GroupDeleteCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!shouldDelete) {
|
||||
templateRenderer.renderToStderr(PROMPT_TEMPLATE, Collections.emptyMap());
|
||||
return;
|
||||
}
|
||||
Group group = manager.get(name);
|
||||
if (group != null) {
|
||||
manager.delete(group);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setShouldDelete(boolean shouldDelete) {
|
||||
this.shouldDelete = shouldDelete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "get")
|
||||
class GroupGetCommand implements Runnable{
|
||||
|
||||
@CommandLine.Parameters(paramLabel = "name")
|
||||
private String name;
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@Inject
|
||||
GroupGetCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Group group = manager.get(name);
|
||||
if (group != null) {
|
||||
templateRenderer.render(group);
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.cli.Table;
|
||||
import sonia.scm.cli.TemplateRenderer;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "list", aliases = "ls")
|
||||
class GroupListCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final TemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
private final GroupCommandBeanMapper beanMapper;
|
||||
@CommandLine.Spec
|
||||
private CommandLine.Model.CommandSpec spec;
|
||||
|
||||
@CommandLine.Option(names = {"--short", "-s"})
|
||||
private boolean useShortTemplate;
|
||||
|
||||
private static final String TABLE_TEMPLATE = String.join("\n",
|
||||
"{{#rows}}",
|
||||
"{{#cols}}{{#row.first}}{{#upper}}{{value}}{{/upper}}{{/row.first}}{{^row.first}}{{value}}{{/row.first}}{{^last}} {{/last}}{{/cols}}",
|
||||
"{{/rows}}"
|
||||
);
|
||||
|
||||
private static final String SHORT_TEMPLATE = String.join("\n",
|
||||
"{{#groups}}",
|
||||
"{{name}}",
|
||||
"{{/groups}}"
|
||||
);
|
||||
|
||||
@Inject
|
||||
GroupListCommand(TemplateRenderer templateRenderer, GroupManager manager, GroupCommandBeanMapper beanMapper) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
this.beanMapper = beanMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<GroupCommandBean> groupCommandBeans = manager.getAll().stream().map(beanMapper::map).collect(toList());
|
||||
if (useShortTemplate) {
|
||||
templateRenderer.renderToStdout(SHORT_TEMPLATE, ImmutableMap.of("groups", groupCommandBeans));
|
||||
} else {
|
||||
Table table = templateRenderer.createTable();
|
||||
table.addHeader("scm.group.name", "scm.group.external");
|
||||
String yes = spec.resourceBundle().getString("yes");
|
||||
String no = spec.resourceBundle().getString("no");
|
||||
for (GroupCommandBean bean : groupCommandBeans) {
|
||||
table.addRow(bean.getName(), bean.isExternal()? yes: no);
|
||||
}
|
||||
templateRenderer.renderToStdout(TABLE_TEMPLATE, ImmutableMap.of("rows", table, "groups", groupCommandBeans));
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setUseShortTemplate(boolean useShortTemplate) {
|
||||
this.useShortTemplate = useShortTemplate;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setSpec(CommandLine.Model.CommandSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "modify")
|
||||
class GroupModifyCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@CommandLine.Parameters(descriptionKey = "scm.group.modify.name")
|
||||
private String name;
|
||||
|
||||
@CommandLine.Option(names = {"--description", "-d"}, descriptionKey = "scm.group.modify.desc")
|
||||
private String description;
|
||||
|
||||
@CommandLine.Option(names = {"--member", "-m"}, descriptionKey = "scm.group.modify.member")
|
||||
private String[] members;
|
||||
|
||||
@CommandLine.Option(names = {"--external", "-e"}, descriptionKey = "scm.group.modify.external")
|
||||
private Boolean external;
|
||||
|
||||
@Inject
|
||||
GroupModifyCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Group existingGroup = manager.get(name);
|
||||
if (existingGroup == null) {
|
||||
templateRenderer.renderNotFoundError();
|
||||
} else {
|
||||
if (description != null) {
|
||||
existingGroup.setDescription(description);
|
||||
}
|
||||
if (external != null) {
|
||||
existingGroup.setExternal(external);
|
||||
}
|
||||
if (members != null) {
|
||||
existingGroup.setMembers(asList(members));
|
||||
}
|
||||
manager.modify(existingGroup);
|
||||
Group modifiedGroup = manager.get(name);
|
||||
templateRenderer.render(modifiedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setMembers(String[] members) {
|
||||
this.members = members;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setExternal(boolean external) {
|
||||
this.external = external;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.repository.cli.GroupCommand;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Arrays;
|
||||
|
||||
@ParentCommand(GroupCommand.class)
|
||||
@CommandLine.Command(name = "remove-member", aliases = "remove")
|
||||
class GroupRemoveMemberCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final GroupTemplateRenderer templateRenderer;
|
||||
private final GroupManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", arity = "1", descriptionKey = "scm.group.remove-member.name")
|
||||
private String name;
|
||||
@CommandLine.Parameters(index = "1..", arity = "1..", descriptionKey = "scm.group.remove-member.members")
|
||||
private String[] members;
|
||||
|
||||
@Inject
|
||||
GroupRemoveMemberCommand(GroupTemplateRenderer templateRenderer, GroupManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Group existingGroup = manager.get(name);
|
||||
if (existingGroup == null) {
|
||||
templateRenderer.renderNotFoundError();
|
||||
} else {
|
||||
Arrays.stream(members).forEach(existingGroup::remove);
|
||||
manager.modify(existingGroup);
|
||||
Group modifiedGroup = manager.get(name);
|
||||
templateRenderer.render(modifiedGroup);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setMembers(String[] members) {
|
||||
this.members = members;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import sonia.scm.cli.CliContext;
|
||||
import sonia.scm.cli.ExitCode;
|
||||
import sonia.scm.cli.Table;
|
||||
import sonia.scm.cli.TemplateRenderer;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
|
||||
class GroupTemplateRenderer extends TemplateRenderer {
|
||||
|
||||
private static final String NOT_FOUND_TEMPLATE = "{{i18n.groupNotFound}}";
|
||||
|
||||
private static final String DETAILS_TABLE_TEMPLATE = String.join("\n",
|
||||
"{{#rows}}",
|
||||
"{{#cols}}{{value}}{{/cols}}",
|
||||
"{{/rows}}"
|
||||
);
|
||||
|
||||
private final GroupCommandBeanMapper mapper;
|
||||
|
||||
@Inject
|
||||
GroupTemplateRenderer(CliContext context, TemplateEngineFactory templateEngineFactory, GroupCommandBeanMapper mapper) {
|
||||
super(context, templateEngineFactory);
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
void render(Group group) {
|
||||
GroupCommandBean groupBean = mapper.map(group);
|
||||
Table table = createTable();
|
||||
String yes = getBundle().getString("yes");
|
||||
String no = getBundle().getString("no");
|
||||
table.addLabelValueRow("scm.group.name", groupBean.getName());
|
||||
table.addLabelValueRow("scm.group.description", groupBean.getDescription());
|
||||
table.addLabelValueRow("scm.group.members", groupBean.getMembersList());
|
||||
table.addLabelValueRow("scm.group.external", groupBean.isExternal() ? yes : no);
|
||||
table.addLabelValueRow("creationDate", groupBean.getCreationDate());
|
||||
table.addLabelValueRow("lastModified", groupBean.getLastModified());
|
||||
|
||||
renderToStdout(DETAILS_TABLE_TEMPLATE, ImmutableMap.of("rows", table, "repo", groupBean));
|
||||
}
|
||||
|
||||
void renderNotFoundError() {
|
||||
renderToStderr(NOT_FOUND_TEMPLATE, Collections.emptyMap());
|
||||
getContext().exit(ExitCode.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class RepositoryGetCommand implements Runnable {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setRepository(String repository) {
|
||||
void setRepository(String repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "activate")
|
||||
class UserActivateCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@Inject
|
||||
UserActivateCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
User user = manager.get(username);
|
||||
|
||||
if (user != null) {
|
||||
if (user.isExternal()) {
|
||||
templateRenderer.renderExternalActivateError();
|
||||
} else {
|
||||
user.setActive(true);
|
||||
manager.modify(user);
|
||||
templateRenderer.render(user);
|
||||
}
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
class UserCommandBean {
|
||||
|
||||
private String name;
|
||||
private String displayName;
|
||||
private String mail;
|
||||
private boolean external;
|
||||
private boolean active;
|
||||
private String creationDate;
|
||||
private String lastModified;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
@Mapper
|
||||
interface UserCommandBeanMapper {
|
||||
|
||||
UserCommandBean map(User modelObject);
|
||||
|
||||
default String mapTimestampToISODate(Long timestamp) {
|
||||
if (timestamp != null) {
|
||||
return DateTimeFormatter.ISO_INSTANT.format(Instant.ofEpochMilli(timestamp));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "convert-to-external", aliases = "conv-ext")
|
||||
class UserConvertToExternalCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@Inject
|
||||
UserConvertToExternalCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
User user = manager.get(username);
|
||||
|
||||
if (user != null) {
|
||||
user.setExternal(true);
|
||||
manager.modify(user);
|
||||
templateRenderer.render(user);
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "convert-to-internal", aliases = "conv-int")
|
||||
class UserConvertToInternalCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@CommandLine.Parameters(index = "1", paramLabel = "<password>", descriptionKey = "scm.user.password")
|
||||
private String password;
|
||||
|
||||
@Inject
|
||||
UserConvertToInternalCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
User user = manager.get(username);
|
||||
|
||||
if (user != null) {
|
||||
user.setExternal(false);
|
||||
user.setPassword(password);
|
||||
manager.modify(user);
|
||||
templateRenderer.render(user);
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.CommandValidator;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.constraints.Email;
|
||||
|
||||
@CommandLine.Command(name = "create")
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
class UserCreateCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
@CommandLine.Mixin
|
||||
private final CommandValidator validator;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@CommandLine.Parameters(index = "1", paramLabel = "<displayname>", descriptionKey = "scm.user.displayName")
|
||||
private String displayName;
|
||||
|
||||
@Email
|
||||
@CommandLine.Option(names = {"--email", "-e"}, descriptionKey = "scm.user.email")
|
||||
private String email;
|
||||
|
||||
@CommandLine.Option(names = {"--external", "-x"}, descriptionKey = "scm.user.create.external")
|
||||
private boolean external;
|
||||
|
||||
@CommandLine.Option(names = {"--password", "-p"}, descriptionKey = "scm.user.password")
|
||||
private String password;
|
||||
|
||||
@CommandLine.Option(names = {"--deactivate", "-d"}, descriptionKey = "scm.user.create.deactivate")
|
||||
private boolean inactive;
|
||||
|
||||
@Inject
|
||||
public UserCreateCommand(UserTemplateRenderer templateRenderer,
|
||||
CommandValidator validator,
|
||||
UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.validator = validator;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
validator.validate();
|
||||
User newUser = new User();
|
||||
newUser.setName(username);
|
||||
newUser.setDisplayName(displayName);
|
||||
newUser.setMail(email);
|
||||
newUser.setExternal(external);
|
||||
if (!external) {
|
||||
if (password == null) {
|
||||
templateRenderer.renderPasswordError();
|
||||
}
|
||||
newUser.setPassword(password);
|
||||
newUser.setActive(!inactive);
|
||||
} else {
|
||||
if (inactive) {
|
||||
templateRenderer.renderExternalDeactivateError();
|
||||
}
|
||||
}
|
||||
User createdUser = manager.create(newUser);
|
||||
templateRenderer.render(createdUser);
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setExternal(boolean external) {
|
||||
this.external = external;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setInactive(boolean inactive) {
|
||||
this.inactive = inactive;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "deactivate")
|
||||
class UserDeactivateCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@Inject
|
||||
UserDeactivateCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
User user = manager.get(username);
|
||||
|
||||
if (user != null) {
|
||||
if (user.isExternal()) {
|
||||
templateRenderer.renderExternalDeactivateError();
|
||||
} else {
|
||||
user.setActive(false);
|
||||
manager.modify(user);
|
||||
templateRenderer.render(user);
|
||||
}
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
|
||||
@CommandLine.Command(name = "delete", aliases = "rm")
|
||||
@ParentCommand(UserCommand.class)
|
||||
class UserDeleteCommand implements Runnable {
|
||||
|
||||
private static final String CONFIRM_TEMPLATE = "{{i18n.scmUserDeleteConfirm}}";
|
||||
private static final String SUCCESS_TEMPLATE = "{{i18n.scmUserDeleteSuccess}}";
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@CommandLine.Option(names = {"--yes", "-y"}, descriptionKey = "scm.user.delete.prompt")
|
||||
private boolean shouldDelete;
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@Inject
|
||||
public UserDeleteCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (!shouldDelete) {
|
||||
templateRenderer.renderToStderr(CONFIRM_TEMPLATE, Collections.emptyMap());
|
||||
return;
|
||||
}
|
||||
User user = manager.get(username);
|
||||
if (user != null) {
|
||||
manager.delete(user);
|
||||
templateRenderer.renderToStdout(SUCCESS_TEMPLATE, Collections.emptyMap());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setShouldDelete(boolean shouldDelete) {
|
||||
this.shouldDelete = shouldDelete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "get")
|
||||
class UserGetCommand implements Runnable {
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
|
||||
@Inject
|
||||
UserGetCommand(UserTemplateRenderer templateRenderer, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
User user = manager.get(username);
|
||||
if (user != null) {
|
||||
templateRenderer.render(user);
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.cli.Table;
|
||||
import sonia.scm.cli.TemplateRenderer;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "list", aliases = "ls")
|
||||
class UserListCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final TemplateRenderer templateRenderer;
|
||||
private final UserManager manager;
|
||||
private final UserCommandBeanMapper mapper;
|
||||
@CommandLine.Spec
|
||||
private CommandLine.Model.CommandSpec spec;
|
||||
|
||||
@CommandLine.Option(names = {"--short", "-s"})
|
||||
private boolean useShortTemplate;
|
||||
|
||||
private static final String TABLE_TEMPLATE = String.join("\n",
|
||||
"{{#rows}}",
|
||||
"{{#cols}}{{#row.first}}{{#upper}}{{value}}{{/upper}}{{/row.first}}{{^row.first}}{{value}}{{/row.first}}{{^last}} {{/last}}{{/cols}}",
|
||||
"{{/rows}}"
|
||||
);
|
||||
|
||||
private static final String SHORT_TEMPLATE = String.join("\n",
|
||||
"{{#users}}",
|
||||
"{{name}}",
|
||||
"{{/users}}"
|
||||
);
|
||||
|
||||
@Inject
|
||||
public UserListCommand(TemplateRenderer templateRenderer, UserManager manager, UserCommandBeanMapper mapper) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.manager = manager;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Collection<UserCommandBean> beans = manager.getAll().stream().map(mapper::map).collect(Collectors.toList());
|
||||
if (useShortTemplate) {
|
||||
templateRenderer.renderToStdout(SHORT_TEMPLATE, ImmutableMap.of("users", beans));
|
||||
} else {
|
||||
Table table = templateRenderer.createTable();
|
||||
String yes = spec.resourceBundle().getString("yes");
|
||||
String no = spec.resourceBundle().getString("no");
|
||||
table.addHeader("scm.user.username", "scm.user.displayName", "scm.user.email", "scm.user.external", "scm.user.active");
|
||||
for (UserCommandBean bean : beans) {
|
||||
table.addRow(bean.getName(), bean.getDisplayName(), bean.getMail(), bean.isExternal() ? yes : no, bean.isActive() ? yes : no);
|
||||
}
|
||||
templateRenderer.renderToStdout(TABLE_TEMPLATE, ImmutableMap.of("rows", table, "users", beans));
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setUseShortTemplate(boolean useShortTemplate) {
|
||||
this.useShortTemplate = useShortTemplate;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setSpec(CommandLine.Model.CommandSpec spec) {
|
||||
this.spec = spec;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.cli.CommandValidator;
|
||||
import sonia.scm.cli.ParentCommand;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.constraints.Email;
|
||||
|
||||
@ParentCommand(value = UserCommand.class)
|
||||
@CommandLine.Command(name = "modify")
|
||||
class UserModifyCommand implements Runnable {
|
||||
|
||||
@CommandLine.Mixin
|
||||
private final UserTemplateRenderer templateRenderer;
|
||||
@CommandLine.Mixin
|
||||
private final CommandValidator validator;
|
||||
private final UserManager manager;
|
||||
|
||||
@CommandLine.Parameters(index = "0", paramLabel = "<username>", descriptionKey = "scm.user.username")
|
||||
private String username;
|
||||
|
||||
@CommandLine.Option(names = {"--displayname", "-d"}, descriptionKey = "scm.user.displayName")
|
||||
private String displayName;
|
||||
|
||||
@Email
|
||||
@CommandLine.Option(names = {"--email", "-e"}, descriptionKey = "scm.user.email")
|
||||
private String email;
|
||||
|
||||
@CommandLine.Option(names = {"--password", "-p"}, descriptionKey = "scm.user.password")
|
||||
private String password;
|
||||
|
||||
@Inject
|
||||
UserModifyCommand(UserTemplateRenderer templateRenderer, CommandValidator validator, UserManager manager) {
|
||||
this.templateRenderer = templateRenderer;
|
||||
this.validator = validator;
|
||||
this.manager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
validator.validate();
|
||||
|
||||
User user = manager.get(username);
|
||||
|
||||
if (user != null) {
|
||||
if (displayName != null) {
|
||||
user.setDisplayName(displayName);
|
||||
}
|
||||
if (email != null) {
|
||||
user.setMail(email);
|
||||
}
|
||||
if (password != null) {
|
||||
user.setPassword(password);
|
||||
}
|
||||
manager.modify(user);
|
||||
templateRenderer.render(user);
|
||||
} else {
|
||||
templateRenderer.renderNotFoundError();
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
@SuppressWarnings("SameParameterValue")
|
||||
@VisibleForTesting
|
||||
void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import sonia.scm.cli.CliContext;
|
||||
import sonia.scm.cli.ExitCode;
|
||||
import sonia.scm.cli.Table;
|
||||
import sonia.scm.cli.TemplateRenderer;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
import sonia.scm.user.User;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.util.Collections;
|
||||
|
||||
class UserTemplateRenderer extends TemplateRenderer {
|
||||
|
||||
private static final String DETAILS_TABLE_TEMPLATE = String.join("\n",
|
||||
"{{#rows}}",
|
||||
"{{#cols}}{{value}}{{/cols}}",
|
||||
"{{/rows}}"
|
||||
);
|
||||
private static final String PASSWORD_ERROR_TEMPLATE = "{{i18n.scmUserErrorPassword}}";
|
||||
private static final String EXTERNAL_ACTIVATE_TEMPLATE = "{{i18n.scmUserErrorExternalActivate}}";
|
||||
private static final String EXTERNAL_DEACTIVATE_TEMPLATE = "{{i18n.scmUserErrorExternalDeactivate}}";
|
||||
private static final String NOT_FOUND_TEMPLATE = "{{i18n.scmUserErrorNotFound}}";
|
||||
|
||||
private final CliContext context;
|
||||
private final UserCommandBeanMapper mapper;
|
||||
|
||||
@Inject
|
||||
UserTemplateRenderer(CliContext context, TemplateEngineFactory templateEngineFactory, UserCommandBeanMapper mapper) {
|
||||
super(context, templateEngineFactory);
|
||||
this.context = context;
|
||||
this.mapper = mapper;
|
||||
}
|
||||
|
||||
public void render(User user) {
|
||||
Table table = createTable();
|
||||
|
||||
String yes = getBundle().getString("yes");
|
||||
String no = getBundle().getString("no");
|
||||
UserCommandBean bean = mapper.map(user);
|
||||
table.addLabelValueRow("scm.user.username", bean.getName());
|
||||
table.addLabelValueRow("scm.user.displayName", bean.getDisplayName());
|
||||
table.addLabelValueRow("scm.user.email", bean.getMail());
|
||||
table.addLabelValueRow("scm.user.external", bean.isExternal() ? yes : no);
|
||||
table.addLabelValueRow("scm.user.active", bean.isActive() ? yes : no);
|
||||
table.addLabelValueRow("creationDate", bean.getCreationDate());
|
||||
table.addLabelValueRow("lastModified", bean.getLastModified());
|
||||
renderToStdout(DETAILS_TABLE_TEMPLATE, ImmutableMap.of("rows", table, "user", bean));
|
||||
}
|
||||
|
||||
public void renderPasswordError() {
|
||||
renderToStderr(PASSWORD_ERROR_TEMPLATE, Collections.emptyMap());
|
||||
context.exit(ExitCode.USAGE);
|
||||
}
|
||||
|
||||
public void renderExternalActivateError() {
|
||||
renderToStderr(EXTERNAL_ACTIVATE_TEMPLATE, Collections.emptyMap());
|
||||
context.exit(ExitCode.USAGE);
|
||||
}
|
||||
|
||||
public void renderExternalDeactivateError() {
|
||||
renderToStderr(EXTERNAL_DEACTIVATE_TEMPLATE, Collections.emptyMap());
|
||||
context.exit(ExitCode.USAGE);
|
||||
}
|
||||
|
||||
public void renderNotFoundError() {
|
||||
renderToStderr(NOT_FOUND_TEMPLATE, Collections.emptyMap());
|
||||
context.exit(ExitCode.NOT_FOUND);
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,11 @@ errorLabel= ERROR
|
||||
errorExecutionFailed = Error
|
||||
transactionId = Transaction ID
|
||||
|
||||
creationDate = Creation Date
|
||||
lastModified = Last Modified
|
||||
yes = yes
|
||||
no = no
|
||||
|
||||
repoNamespace = Namespace
|
||||
repoName = Name
|
||||
repoDescription= Description
|
||||
@@ -54,12 +59,12 @@ scm.logout.usage.description.0 = Removes the api key from server and local cli c
|
||||
scm.ping.usage.description.0 = Returns PONG if the server is available
|
||||
|
||||
## Repo
|
||||
scm.repo.usage.description.0 = Parent command for all repository-related actions
|
||||
scm.repo.usage.description.0 = Resource command for all repository-related actions
|
||||
repoNotFound= Could not find repository
|
||||
repoInvalidInput= Invalid input. Use namespace/name
|
||||
|
||||
### Get repo
|
||||
scm.repo.get.usage.description.0 = Returns repository related information
|
||||
scm.repo.get.usage.description.0 = Returns repository-related information
|
||||
|
||||
### List repo
|
||||
scm.repo.list.usage.description.0 = List all repositories on server
|
||||
@@ -81,3 +86,102 @@ repoDeletePrompt= If you really want to delete this repository please pass --yes
|
||||
### Modify repo
|
||||
scm.repo.modify.usage.description.0 = Modify repository on server
|
||||
scm.repo.modify.repository = Repository namespace/name
|
||||
|
||||
## User
|
||||
scm.user.username = Username
|
||||
scm.user.displayName = Display Name
|
||||
scm.user.email = Email address
|
||||
scm.user.external = External
|
||||
scm.user.password = Password
|
||||
scm.user.active = Active
|
||||
|
||||
### User error
|
||||
scmUserErrorPassword = Password is required for internal users
|
||||
scmUserErrorExternalActivate = External users cannot be activated
|
||||
scmUserErrorExternalDeactivate = External users cannot be deactivated
|
||||
scmUserErrorNotFound = Could not find user
|
||||
|
||||
### User command
|
||||
scm.user.usage.description.0 = Resource command for all user-related actions
|
||||
|
||||
### Get user
|
||||
scm.user.get.usage.description.0 = Returns user-related information
|
||||
|
||||
### List user
|
||||
scm.user.list.usage.description.0 = List all users on server
|
||||
|
||||
### Create user
|
||||
scm.user.create.usage.description.0 = Creates new user on server
|
||||
scm.user.create.deactivate = User is deactivated
|
||||
scm.user.create.external = User is managed by an external system
|
||||
|
||||
### Delete user
|
||||
scm.user.delete.usage.description.0 = Deletes user on server
|
||||
scm.user.delete.prompt = Set this flag to agree to delete the user
|
||||
scmUserDeleteConfirm = If you really want to delete this user please pass --yes
|
||||
scmUserDeleteSuccess = Successfully deleted user
|
||||
|
||||
### Modify user
|
||||
scm.user.modify.usage.description.0 = Modify user on server
|
||||
|
||||
### Activate user
|
||||
scm.user.activate.usage.description.0 = Activate user on server
|
||||
|
||||
### Deactivate user
|
||||
scm.user.deactivate.usage.description.0 = Deactivate user on server
|
||||
|
||||
### Convert to external user
|
||||
scm.user.convert-to-external.usage.description.0 = Convert user to external user on server
|
||||
|
||||
### Convert to internal user
|
||||
scm.user.convert-to-internal.usage.description.0 = Convert user to internal user on server
|
||||
|
||||
### Group
|
||||
scm.group.name = Name
|
||||
scm.group.description = Description
|
||||
scm.group.members = Members
|
||||
scm.group.membersList = Members
|
||||
scm.group.external = External
|
||||
|
||||
### Group command
|
||||
scm.group.usage.description.0 = Resource command for all group-related actions
|
||||
|
||||
### Get group
|
||||
scm.group.get.usage.description.0 = Returns group-related information
|
||||
scm.group.get.name = Name of the group
|
||||
|
||||
### List group
|
||||
scm.group.list.usage.description.0 = List all groups on server
|
||||
scm.group.list.short = List only names of groups
|
||||
|
||||
### Create group
|
||||
scm.group.create.usage.description.0 = Creates new group on server
|
||||
scm.group.create.name = Name of the group
|
||||
scm.group.create.description = Description of the new group
|
||||
scm.group.create.member = Members of the new group
|
||||
scm.group.create.external = Group is managed by an external system
|
||||
|
||||
### Delete group
|
||||
scm.group.delete.usage.description.0 = Delete group on server
|
||||
scm.group.delete.group = Name of the group
|
||||
scm.group.delete.prompt = Set this flag to agree to delete the group
|
||||
groupDeletePrompt = If you really want to delete this group please pass --yes
|
||||
|
||||
### Modify group
|
||||
scm.group.modify.usage.description.0 = Modify group on server
|
||||
scm.group.modify.name = Name of the group
|
||||
scm.group.modify.desc = New description of the group
|
||||
scm.group.modify.member = New members of the group
|
||||
scm.group.modify.external = Whether the group is an external group or not
|
||||
|
||||
### Add members to group
|
||||
scm.group.add-member.usage.description.0 = Add members to an existing group
|
||||
scm.group.add-member.name = Name of the group
|
||||
scm.group.add-member.members = Members to add to the group
|
||||
|
||||
### Remove members form group
|
||||
scm.group.remove-member.usage.description.0 = Remove members from an existing group
|
||||
scm.group.remove-member.name = Name of the group
|
||||
scm.group.remove-member.members = Members to remove from the group
|
||||
|
||||
groupNotFound = Could not find group
|
||||
|
||||
@@ -28,6 +28,11 @@ errorLabel= FEHLER
|
||||
errorExecutionFailed = Fehler
|
||||
transactionId = Transaktions-ID
|
||||
|
||||
creationDate = Erstellt
|
||||
lastModified = Zuletzt bearbeitet
|
||||
yes = ja
|
||||
no = nein
|
||||
|
||||
repoNamespace = Namespace
|
||||
repoName = Name
|
||||
repoDescription= Beschreibung
|
||||
@@ -54,7 +59,7 @@ scm.logout.usage.description.0 = Entfernt den API Key vom Server und die lokale
|
||||
scm.ping.usage.description.0 = Antwortet PONG, wenn der Server erreichbar ist
|
||||
|
||||
## Repo
|
||||
scm.repo.usage.description.0 = Gruppen Befehl f<>r alle Repository Befehle
|
||||
scm.repo.usage.description.0 = Ressourcenkommando f<>r alle Repositoryaktionen
|
||||
repoNotFound= Repository konnte nicht gefunden werden
|
||||
repoInvalidInput= Ung<EFBFBD>ltige Eingabe. Nutzen Sie namespace/name
|
||||
|
||||
@@ -81,3 +86,102 @@ repoDeletePrompt= Wenn dieses Repository endg
|
||||
### Modify repo
|
||||
scm.repo.modify.usage.description.0 = Aktualisiert ein Repository auf dem Server
|
||||
scm.repo.modify.repository = Repository Namespace/Name
|
||||
|
||||
## User
|
||||
scm.user.username = Benutzername
|
||||
scm.user.displayName = Anzeigename
|
||||
scm.user.email = E-Mail-Adresse
|
||||
scm.user.external = Extern
|
||||
scm.user.password = Passwort
|
||||
scm.user.active = Aktiv
|
||||
|
||||
### User error
|
||||
scmUserErrorPassword = F<EFBFBD>r interne Benutzer muss ein Passwort gesetzt werden
|
||||
scmUserErrorExternalActivate = Externe Benutzer k<>nnen nicht aktiviert werden
|
||||
scmUserErrorExternalDeactivate = Externe Benutzer k<>nnen nicht deaktiviert werden
|
||||
scmUserErrorNotFound= Benutzer konnte nicht gefunden werden
|
||||
|
||||
### User command
|
||||
scm.user.usage.description.0 = Ressourcenkommando f<>r alle Benutzeraktionen
|
||||
|
||||
### Get user
|
||||
scm.user.get.usage.description.0 = Liefert Informationen zum Benutzer
|
||||
|
||||
### List user
|
||||
scm.user.list.usage.description.0 = Listet alle Benutzer auf dem Server
|
||||
|
||||
### Create user
|
||||
scm.user.create.usage.description.0 = Erzeugt einen neuen Benutzer auf dem Server
|
||||
scm.user.create.deactivate = Benutzer ist deaktiviert
|
||||
scm.user.create.external = Der Benutzer wird von einem Fremdsystem verwaltet
|
||||
|
||||
### Delete user
|
||||
scm.user.delete.usage.description.0 = L<EFBFBD>scht einen Benutzer auf dem Server
|
||||
scm.user.delete.prompt = Setzen Sie diese Option, um einen Benutzer endg<64>ltig zu l<>schen
|
||||
scmUserDeleteConfirm = Wenn dieser Benutzer endg<64>ltig gel<65>scht werden soll, setzen Sie bitte --yes
|
||||
scmUserDeleteSuccess = Benutzer erfolgreich gel<65>scht
|
||||
|
||||
### Modify user
|
||||
scm.user.modify.usage.description.0 = Aktualisiert einen Benutzer auf dem Server
|
||||
|
||||
### Activate user
|
||||
scm.user.activate.usage.description.0 = Aktiviert einen Benutzer auf dem Server
|
||||
|
||||
### Deactivate user
|
||||
scm.user.deactivate.usage.description.0 = Deaktiviert einen Benutzer auf dem Server
|
||||
|
||||
### Convert to external user
|
||||
scm.user.convert-to-external.usage.description.0 = Konvertiert einen Benutzer zu einem externen Benutzer
|
||||
|
||||
### Convert to internal user
|
||||
scm.user.convert-to-internal.usage.description.0 = Konvertiert einen Benutzer zu einem internen Benutzer
|
||||
|
||||
### Group
|
||||
scm.group.name = Name
|
||||
scm.group.description = Beschreibung
|
||||
scm.group.members = Mitglieder
|
||||
scm.group.membersList = Mitglieder
|
||||
scm.group.external = Extern
|
||||
|
||||
### Group command
|
||||
scm.group.usage.description.0 = Ressourcenkommando f<>r alle Gruppenaktionen
|
||||
|
||||
### Get group
|
||||
scm.group.get.usage.description.0 = Liefert Informationen zur Gruppe
|
||||
scm.group.get.name = Name der Gruppe
|
||||
|
||||
### List group
|
||||
scm.group.list.usage.description.0 = Listet alle Gruppen auf dem Server
|
||||
scm.group.list.short = Listet nur die Namen der Gruppen
|
||||
|
||||
### Create group
|
||||
scm.group.create.usage.description.0 = Erzeugt eine neue Gruppe auf dem Server
|
||||
scm.group.create.name = Name der Gruppe
|
||||
scm.group.create.description = Beschreibung der Gruppe
|
||||
scm.group.create.member = Mitglieder der Gruppe
|
||||
scm.group.create.external = Die Gruppe wird von einem externen System verwaltet
|
||||
|
||||
### Delete group
|
||||
scm.group.delete.usage.description.0 = L<EFBFBD>scht eine Gruppe auf dem Server
|
||||
scm.group.delete.group = Name der Gruppe
|
||||
scm.group.delete.prompt = Setzen Sie diese Option, um eine Gruppe endg<64>ltig zu l<>schen
|
||||
groupDeletePrompt = Wenn diese Gruppe endg<64>ltig gel<65>scht werden soll, setzen Sie bitte --yes
|
||||
|
||||
### Modify group
|
||||
scm.group.modify.usage.description.0 = <EFBFBD>ndert eine Gruppe auf dem Server
|
||||
scm.group.modify.name = Name der Gruppe
|
||||
scm.group.modify.desc = Neue Beschreibung der Gruppe
|
||||
scm.group.modify.member = Neue Mitglieder der Gruppe
|
||||
scm.group.modify.external = Flag, ob diese Gruppe von einem Fremdsystem verwaltet wird
|
||||
|
||||
### Add members to group
|
||||
scm.group.add-member.usage.description.0 = F<EFBFBD>gt neue Mitglieder zu einer Gruppe hinzu
|
||||
scm.group.add-member.name = Name der Gruppe
|
||||
scm.group.add-member.members = Hinzuzuf<EFBFBD>gende Mitglieder
|
||||
|
||||
### Remove members form group
|
||||
scm.group.remove-member.usage.description.0 = Entfernt Mitglieder von einer Gruppe
|
||||
scm.group.remove-member.name = Name der Gruppe
|
||||
scm.group.remove-member.members = Zu l<>schende Mitglieder
|
||||
|
||||
groupNotFound = Gruppe konnte nicht gefunden werden
|
||||
|
||||
117
scm-webapp/src/test/java/sonia/scm/cli/TemplateTestRenderer.java
Normal file
117
scm-webapp/src/test/java/sonia/scm/cli/TemplateTestRenderer.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.cli;
|
||||
|
||||
import com.google.common.io.Resources;
|
||||
import picocli.CommandLine;
|
||||
import sonia.scm.template.MustacheTemplateTestEngine;
|
||||
import sonia.scm.template.TemplateEngine;
|
||||
import sonia.scm.template.TemplateEngineFactory;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import static java.util.Collections.singleton;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* This is a helper to create a {@link TemplateRenderer} that can be used for
|
||||
* command tests
|
||||
*/
|
||||
public class TemplateTestRenderer {
|
||||
|
||||
private final ByteArrayOutputStream stdOut = new ByteArrayOutputStream();
|
||||
private final ByteArrayOutputStream stdErr = new ByteArrayOutputStream();
|
||||
private final CliContext context = mock(CliContext.class);
|
||||
private final TemplateEngineFactory templateEngineFactory;
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
public TemplateTestRenderer() {
|
||||
lenient().when(context.getStdout()).thenReturn(new PrintWriter(stdOut));
|
||||
lenient().when(context.getStderr()).thenReturn(new PrintWriter(stdErr));
|
||||
lenient().doThrow(CliExitException.class).when(context).exit(anyInt());
|
||||
|
||||
ServletContext servletContext = mock(ServletContext.class);
|
||||
lenient().when(servletContext.getResourceAsStream(any()))
|
||||
.thenAnswer(invocation -> Resources.getResource(invocation.getArgument(0, String.class)).openStream());
|
||||
TemplateEngine engine = new MustacheTemplateTestEngine().createEngine(servletContext);
|
||||
|
||||
when(context.getLocale()).thenReturn(new Locale("en"));
|
||||
|
||||
templateEngineFactory = new TemplateEngineFactory(singleton(engine), engine);
|
||||
}
|
||||
|
||||
public TemplateRenderer createTemplateRenderer() {
|
||||
return new TemplateRenderer(context, templateEngineFactory) {
|
||||
@Override
|
||||
protected ResourceBundle getBundle() {
|
||||
return TemplateTestRenderer.this.getResourceBundle();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public ResourceBundle getResourceBundle() {
|
||||
return ResourceBundle.getBundle("sonia.scm.cli.i18n", context.getLocale(), new ResourceBundle.Control() {
|
||||
@Override
|
||||
public Locale getFallbackLocale(String baseName, Locale locale) {
|
||||
return Locale.ROOT;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
lenient().when(context.getLocale()).thenReturn(new Locale(locale));
|
||||
}
|
||||
|
||||
public String getStdOut() {
|
||||
return stdOut.toString();
|
||||
}
|
||||
|
||||
public String getStdErr() {
|
||||
return stdErr.toString();
|
||||
}
|
||||
|
||||
public CliContext getContextMock() {
|
||||
return context;
|
||||
}
|
||||
|
||||
public TemplateEngineFactory getTemplateEngineFactory() {
|
||||
return templateEngineFactory;
|
||||
}
|
||||
|
||||
public CommandLine.Model.CommandSpec getMockedSpeck() {
|
||||
ResourceBundle resourceBundle = getResourceBundle();
|
||||
CommandLine.Model.CommandSpec mock = mock(CommandLine.Model.CommandSpec.class);
|
||||
lenient().when(mock.resourceBundle()).thenReturn(resourceBundle);
|
||||
return mock;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupAddMemberCommandTest {
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private GroupAddMemberCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupAddMemberCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulModificationTest {
|
||||
|
||||
private Group group;
|
||||
|
||||
@BeforeEach
|
||||
void mockModification() {
|
||||
group = new Group("test", "hog", "zaphod");
|
||||
|
||||
when(manager.get("hog")).thenAnswer(invocation -> group);
|
||||
doAnswer(invocation -> {
|
||||
Group modifiedGroup = invocation.getArgument(0, Group.class);
|
||||
modifiedGroup.setLastModified(1649662000000L);
|
||||
group = modifiedGroup;
|
||||
return null;
|
||||
}).when(manager).modify(any());
|
||||
|
||||
command.setName("hog");
|
||||
command.setMembers(new String[]{"trillian", "arthur", "ford"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldModifyGroup() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("hog");
|
||||
assertThat(argument.getMembers()).contains("zaphod", "trillian", "arthur", "ford");
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintGroupAfterModification() {
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Name: hog",
|
||||
"Members: zaphod, trillian, arthur, ford",
|
||||
"Last Modified: 2022-04-11T07:26:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailIfGroupDoesNotExists() {
|
||||
when(manager.get("hog")).thenReturn(null);
|
||||
command.setName("hog");
|
||||
|
||||
Assertions.assertThrows(
|
||||
CliExitException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEqualTo("Could not find group");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupCreateCommandTest {
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private GroupCreateCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupCreateCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulCreationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockCreation() {
|
||||
when(manager.create(any()))
|
||||
.thenAnswer(invocation -> {
|
||||
Group createdGroup = invocation.getArgument(0, Group.class);
|
||||
createdGroup.setCreationDate(1649262000000L);
|
||||
return createdGroup;
|
||||
});
|
||||
|
||||
command.setName("hog");
|
||||
command.setDescription("Crew of the Heart of Gold");
|
||||
command.setMembers(new String[]{"zaphod", "trillian"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateGroup() {
|
||||
command.run();
|
||||
|
||||
verify(manager).create(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("hog");
|
||||
assertThat(argument.getDescription()).isEqualTo("Crew of the Heart of Gold");
|
||||
assertThat(argument.getMembers()).contains("zaphod", "trillian");
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintGroupAfterCreation() {
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Name: hog",
|
||||
"Description: Crew of the Heart of Gold",
|
||||
"Members: zaphod, trillian",
|
||||
"External: no",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: "
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupDeleteCommandTest {
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
private GroupDeleteCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupDeleteCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderPromptWithoutYesFlag() {
|
||||
command.setName("hog");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEqualTo("If you really want to delete this group please pass --yes");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteGroup() {
|
||||
Group groupToDelete = new Group("test", "vogons");
|
||||
when(manager.get("vogons")).thenReturn(groupToDelete);
|
||||
command.setShouldDelete(true);
|
||||
command.setName("vogons");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).delete(groupToDelete);
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotFailForNotExistingGroup() {
|
||||
when(manager.get("vogons")).thenReturn(null);
|
||||
command.setShouldDelete(true);
|
||||
command.setName("vogons");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager, never()).delete(any());
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupGetCommandTest {
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private GroupGetCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupGetCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetGroup() {
|
||||
Group group = new Group("test", "hog", "zaphod", "trillian");
|
||||
group.setCreationDate(1649262000000L);
|
||||
group.setLastModified(1649462000000L);
|
||||
group.setDescription("Crew of the Heart of Gold");
|
||||
|
||||
when(manager.get("hog")).thenReturn(group);
|
||||
|
||||
command.setName("hog");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Name: hog",
|
||||
"Description: Crew of the Heart of Gold",
|
||||
"Members: zaphod, trillian",
|
||||
"External: no",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-08T23:53:20Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailForNotExistingGroup() {
|
||||
command.setName("hog");
|
||||
|
||||
Assertions.assertThrows(
|
||||
CliExitException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.contains("Could not find group");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.TemplateTestRenderer;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupListCommandTest {
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private final GroupCommandBeanMapper beanMapper = new GroupCommandBeanMapperImpl();
|
||||
private final TemplateTestRenderer testRenderer = new TemplateTestRenderer();
|
||||
|
||||
private GroupListCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupListCommand(testRenderer.createTemplateRenderer(), manager, beanMapper);
|
||||
command.setSpec(testRenderer.getMockedSpeck());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void mockGroups() {
|
||||
Group internalGroup = new Group("test", "hog");
|
||||
Group externalGroup = new Group("test", "vogons");
|
||||
externalGroup.setExternal(true);
|
||||
when(manager.getAll())
|
||||
.thenReturn(
|
||||
asList(
|
||||
internalGroup,
|
||||
externalGroup));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderShortTable() {
|
||||
command.setUseShortTemplate(true);
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEqualTo("hog\nvogons\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderLongTable() {
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEqualTo("NAME EXTERNAL\nhog no \nvogons yes \n");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupModifyCommandTest {
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private GroupModifyCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupModifyCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulModificationTest {
|
||||
|
||||
private Group group;
|
||||
|
||||
@BeforeEach
|
||||
void mockModification() {
|
||||
group = new Group("test", "hog", "zaphod", "trillian");
|
||||
group.setCreationDate(1649262000000L);
|
||||
group.setLastModified(1649462000000L);
|
||||
group.setDescription("Crew of the Heart of Gold");
|
||||
|
||||
when(manager.get("hog")).thenAnswer(invocation -> group);
|
||||
doAnswer(invocation -> {
|
||||
Group modifiedGroup = invocation.getArgument(0, Group.class);
|
||||
modifiedGroup.setLastModified(1649662000000L);
|
||||
group = modifiedGroup;
|
||||
return null;
|
||||
}).when(manager).modify(any());
|
||||
|
||||
command.setName("hog");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldModifyGroup() {
|
||||
command.setDescription("Earthlings on the Heart of Gold");
|
||||
command.setMembers(new String[]{"arthur", "trillian"});
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("hog");
|
||||
assertThat(argument.getDescription()).isEqualTo("Earthlings on the Heart of Gold");
|
||||
assertThat(argument.getMembers()).contains("arthur", "trillian");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyDescriptionIfNotSet() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getDescription()).isEqualTo("Crew of the Heart of Gold");
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyExternalIfNotSet() {
|
||||
group.setExternal(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.isExternal()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyMembersIfNotSet() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getMembers()).contains("zaphod", "trillian");
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldSetGroupExternal() {
|
||||
command.setExternal(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getMembers()).isEmpty();
|
||||
assertThat(argument.isExternal()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintGroupAfterModification() {
|
||||
command.setDescription("Earthlings on the Heart of Gold");
|
||||
command.setMembers(new String[]{"arthur", "trillian"});
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Name: hog",
|
||||
"Description: Earthlings on the Heart of Gold",
|
||||
"Members: arthur, trillian",
|
||||
"External: no",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-11T07:26:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailIfGroupDoesNotExists() {
|
||||
when(manager.get("hog")).thenReturn(null);
|
||||
command.setName("hog");
|
||||
|
||||
Assertions.assertThrows(
|
||||
CliExitException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEqualTo("Could not find group");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.group.Group;
|
||||
import sonia.scm.group.GroupManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class GroupRemoveMemberCommandTest {
|
||||
|
||||
private final GroupTemplateTestRenderer testRenderer = new GroupTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private GroupManager manager;
|
||||
|
||||
private GroupRemoveMemberCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new GroupRemoveMemberCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulModificationTest {
|
||||
|
||||
private Group group;
|
||||
|
||||
@BeforeEach
|
||||
void mockModification() {
|
||||
group = new Group("test", "hog", "zaphod", "marvin", "trillian");
|
||||
|
||||
when(manager.get("hog")).thenAnswer(invocation -> group);
|
||||
doAnswer(invocation -> {
|
||||
Group modifiedGroup = invocation.getArgument(0, Group.class);
|
||||
modifiedGroup.setLastModified(1649662000000L);
|
||||
group = modifiedGroup;
|
||||
return null;
|
||||
}).when(manager).modify(any());
|
||||
|
||||
command.setName("hog");
|
||||
command.setMembers(new String[]{"zaphod", "marvin"});
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldModifyGroup() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("hog");
|
||||
assertThat(argument.getMembers()).contains("trillian");
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintGroupAfterModification() {
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Name: hog",
|
||||
"Members: trillian",
|
||||
"Last Modified: 2022-04-11T07:26:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailIfGroupDoesNotExists() {
|
||||
when(manager.get("hog")).thenReturn(null);
|
||||
command.setName("hog");
|
||||
|
||||
Assertions.assertThrows(
|
||||
CliExitException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEmpty();
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEqualTo("Could not find group");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.group.cli;
|
||||
|
||||
import sonia.scm.cli.TemplateTestRenderer;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
class GroupTemplateTestRenderer {
|
||||
private final TemplateTestRenderer testRenderer = new TemplateTestRenderer();
|
||||
private final GroupCommandBeanMapper beanMapper = new GroupCommandBeanMapperImpl();
|
||||
private final GroupTemplateRenderer templateRenderer = new GroupTemplateRenderer(testRenderer.getContextMock(), testRenderer.getTemplateEngineFactory(), beanMapper) {
|
||||
@Override
|
||||
protected ResourceBundle getBundle() {
|
||||
return testRenderer.getResourceBundle();
|
||||
}
|
||||
};
|
||||
|
||||
GroupTemplateRenderer getTemplateRenderer() {
|
||||
return templateRenderer;
|
||||
}
|
||||
|
||||
String getStdOut() {
|
||||
return testRenderer.getStdOut();
|
||||
}
|
||||
|
||||
String getStdErr() {
|
||||
return testRenderer.getStdErr();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.template;
|
||||
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import sonia.scm.plugin.PluginLoader;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
/**
|
||||
* This class can be used to create a mustache renderer in unit test
|
||||
*/
|
||||
public class MustacheTemplateTestEngine {
|
||||
|
||||
public TemplateEngine createEngine(ServletContext context) {
|
||||
PluginLoader loader = mock(PluginLoader.class);
|
||||
|
||||
when(loader.getUberClassLoader()).thenReturn(
|
||||
Thread.currentThread().getContextClassLoader());
|
||||
|
||||
MustacheTemplateEngine.PluginLoaderHolder pluginLoaderHolder = new MustacheTemplateEngine.PluginLoaderHolder();
|
||||
pluginLoaderHolder.pluginLoader = loader;
|
||||
|
||||
MustacheTemplateEngine.MeterRegistryHolder meterRegistryHolder = new MustacheTemplateEngine.MeterRegistryHolder();
|
||||
meterRegistryHolder.registry = new SimpleMeterRegistry();
|
||||
|
||||
return new MustacheTemplateEngine(context, pluginLoaderHolder, meterRegistryHolder);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserActivateCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserActivateCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserActivateCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulActivationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(false);
|
||||
user.setActive(false);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldActivateInternalUser() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterActivationInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: no",
|
||||
"Active: yes",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterActivationInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: nein",
|
||||
"Aktiv: ja",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulActivationTest {
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForExternalUserTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockExternalUser() {
|
||||
User user = new User();
|
||||
user.setExternal(true);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserIsExternal() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("External users cannot be activated");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserIsExternal() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Externe Benutzer können nicht aktiviert werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserConvertToExternalCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserConvertToExternalCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserConvertToExternalCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulConversionTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(false);
|
||||
user.setActive(true);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldConvertToExternalUser() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isTrue();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterConversionInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: yes",
|
||||
"Active: yes",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterConversionInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: ja",
|
||||
"Aktiv: ja",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulConversionTest {
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserConvertToInternalCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserConvertToInternalCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserConvertToInternalCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulActivationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(true);
|
||||
user.setActive(true);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldActivateInternalUser() {
|
||||
command.setPassword("havelock123");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("havelock123");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterActivationInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: no",
|
||||
"Active: yes",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterActivationInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: nein",
|
||||
"Aktiv: ja",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulConversionTest {
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.cli.CommandValidator;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserCreateCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private CommandValidator validator;
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserCreateCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserCreateCommand(testRenderer.getTemplateRenderer(), validator, manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulCreationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockCreation() {
|
||||
when(manager.create(any()))
|
||||
.thenAnswer(invocation -> {
|
||||
User createdUser = invocation.getArgument(0, User.class);
|
||||
createdUser.setCreationDate(1649262000000L);
|
||||
return createdUser;
|
||||
});
|
||||
|
||||
command.setUsername("havelock");
|
||||
command.setDisplayName("Havelock Vetinari");
|
||||
command.setEmail("havelock.vetinari@discworld");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateInternalUser() {
|
||||
command.setPassword("patrician");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).create(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateExternalUser() {
|
||||
command.setExternal(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).create(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isTrue();
|
||||
assertThat(argument.getPassword()).isNull();
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCreateInactiveUser() {
|
||||
command.setPassword("patrician");
|
||||
command.setInactive(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).create(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isFalse();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterCreationInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setPassword("patrician");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: no",
|
||||
"Active: yes",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified:"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterCreationInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setPassword("patrician");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: nein",
|
||||
"Aktiv: ja",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet:"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulCreationTest {
|
||||
|
||||
@Test
|
||||
void shouldFailIfValidatorFails() {
|
||||
doThrow(picocli.CommandLine.ParameterException.class).when(validator).validate();
|
||||
|
||||
assertThrows(
|
||||
picocli.CommandLine.ParameterException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfInternalUserWithoutPassword() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Password is required for internal users");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfInternalUserWithoutPassword() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Für interne Benutzer muss ein Passwort gesetzt werden");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfExternalUserAndInactive() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setExternal(true);
|
||||
command.setInactive(true);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("External users cannot be deactivated");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfExternalUserWithInactive() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setExternal(true);
|
||||
command.setInactive(true);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Externe Benutzer können nicht deaktiviert werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserDeactivateCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserDeactivateCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserDeactivateCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulDeactivationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(false);
|
||||
user.setActive(true);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeactivateInternalUser() {
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isFalse();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterDeactivationInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: no",
|
||||
"Active: no",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterDeactivationInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: nein",
|
||||
"Aktiv: nein",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulActivationTest {
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForExternalUserTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockExternalUser() {
|
||||
User user = new User();
|
||||
user.setExternal(true);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserIsExternal() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("External users cannot be deactivated");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserIsExternal() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Externe Benutzer können nicht deaktiviert werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.lenient;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.verifyNoInteractions;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserDeleteCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserDeleteCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserDeleteCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulDeletionTest {
|
||||
|
||||
private User user;
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
user = new User();
|
||||
lenient().when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderPromptInEnglishWithoutYesFlag() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("If you really want to delete this user please pass --yes");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderPromptInGermanWithoutYesFlag() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
verifyNoInteractions(manager);
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Wenn dieser Benutzer endgültig gelöscht werden soll, setzen Sie bitte --yes");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteUserWithEnglishMsg() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setShouldDelete(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).delete(user);
|
||||
assertThat(testRenderer.getStdOut()).contains("Successfully deleted user");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldDeleteUserWithGermanMsg() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setShouldDelete(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).delete(user);
|
||||
assertThat(testRenderer.getStdOut()).contains("Benutzer erfolgreich gelöscht");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulDeletionTest {
|
||||
|
||||
@Test
|
||||
void shouldFailSilentlyIfUserNotFound() {
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
command.setShouldDelete(true);
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager, never()).delete(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserGetCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserGetCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserGetCommand(testRenderer.getTemplateRenderer(), manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulGetTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(true);
|
||||
user.setActive(false);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Havelock Vetinari",
|
||||
"Email address: havelock.vetinari@discworld",
|
||||
"External: yes",
|
||||
"Active: no",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Havelock Vetinari ",
|
||||
"E-Mail-Adresse: havelock.vetinari@discworld",
|
||||
"Extern: ja",
|
||||
"Aktiv: nein",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr())
|
||||
.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulGetTest {
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.TemplateTestRenderer;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserListCommandTest {
|
||||
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private final UserCommandBeanMapper beanMapper = new UserCommandBeanMapperImpl();
|
||||
private final TemplateTestRenderer testRenderer = new TemplateTestRenderer();
|
||||
|
||||
private UserListCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserListCommand(testRenderer.createTemplateRenderer(), manager, beanMapper);
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void mockGroups() {
|
||||
User internalUser = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
User externalUser = new User("mustrum", "Mustrum Ridcully", "mustrum.ridcully@discworld");
|
||||
externalUser.setExternal(true);
|
||||
externalUser.setActive(false);
|
||||
when(manager.getAll())
|
||||
.thenReturn(
|
||||
asList(
|
||||
internalUser,
|
||||
externalUser));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderShortTableInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setSpec(testRenderer.getMockedSpeck());
|
||||
command.setUseShortTemplate(true);
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEqualTo("havelock\nmustrum\n");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderShortTableInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setSpec(testRenderer.getMockedSpeck());
|
||||
command.setUseShortTemplate(true);
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEqualTo("havelock\nmustrum\n");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderLongTableInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setSpec(testRenderer.getMockedSpeck());
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEqualTo("USERNAME DISPLAY NAME EMAIL ADDRESS EXTERNAL ACTIVE\n" +
|
||||
"havelock Havelock Vetinari havelock.vetinari@discworld no yes \n" +
|
||||
"mustrum Mustrum Ridcully mustrum.ridcully@discworld yes no \n");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldRenderLongTableInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setSpec(testRenderer.getMockedSpeck());
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.isEqualTo("BENUTZERNAME ANZEIGENAME E-MAIL-ADRESSE EXTERN AKTIV\n" +
|
||||
"havelock Havelock Vetinari havelock.vetinari@discworld nein ja \n" +
|
||||
"mustrum Mustrum Ridcully mustrum.ridcully@discworld ja nein \n");
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import sonia.scm.cli.CliExitException;
|
||||
import sonia.scm.cli.CommandValidator;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserManager;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.argThat;
|
||||
import static org.mockito.Mockito.doThrow;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class UserModifyCommandTest {
|
||||
|
||||
private final UserTemplateTestRenderer testRenderer = new UserTemplateTestRenderer();
|
||||
|
||||
@Mock
|
||||
private CommandValidator validator;
|
||||
@Mock
|
||||
private UserManager manager;
|
||||
|
||||
private UserModifyCommand command;
|
||||
|
||||
@BeforeEach
|
||||
void initCommand() {
|
||||
command = new UserModifyCommand(testRenderer.getTemplateRenderer(), validator, manager);
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForSuccessfulModificationTest {
|
||||
|
||||
@BeforeEach
|
||||
void mockGet() {
|
||||
User user = new User("havelock", "Havelock Vetinari", "havelock.vetinari@discworld");
|
||||
user.setPassword("patrician");
|
||||
user.setExternal(false);
|
||||
user.setActive(true);
|
||||
user.setCreationDate(1649262000000L);
|
||||
user.setLastModified(1649272000000L);
|
||||
when(manager.get(any())).thenReturn(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldModifyUser() {
|
||||
command.setDisplayName("Lord Vetinari");
|
||||
command.setEmail("patrician@discworld");
|
||||
command.setPassword("havelock");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Lord Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("havelock");
|
||||
assertThat(argument.getMail()).isEqualTo("patrician@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyDisplayNameIfNotSet() {
|
||||
command.setEmail("patrician@discworld");
|
||||
command.setPassword("havelock");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Havelock Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("havelock");
|
||||
assertThat(argument.getMail()).isEqualTo("patrician@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyEmailIfNotSet() {
|
||||
command.setDisplayName("Lord Vetinari");
|
||||
command.setPassword("havelock");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Lord Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("havelock");
|
||||
assertThat(argument.getMail()).isEqualTo("havelock.vetinari@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldNotModifyPasswordIfNotSet() {
|
||||
command.setEmail("patrician@discworld");
|
||||
command.setDisplayName("Lord Vetinari");
|
||||
|
||||
command.run();
|
||||
|
||||
verify(manager).modify(argThat(argument -> {
|
||||
assertThat(argument.getName()).isEqualTo("havelock");
|
||||
assertThat(argument.getDisplayName()).isEqualTo("Lord Vetinari");
|
||||
assertThat(argument.isExternal()).isFalse();
|
||||
assertThat(argument.getPassword()).isEqualTo("patrician");
|
||||
assertThat(argument.getMail()).isEqualTo("patrician@discworld");
|
||||
assertThat(argument.isActive()).isTrue();
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterModificationInEnglish() {
|
||||
testRenderer.setLocale("en");
|
||||
command.setDisplayName("Lord Vetinari");
|
||||
command.setEmail("patrician@discworld");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Username: havelock",
|
||||
"Display Name: Lord Vetinari",
|
||||
"Email address: patrician@discworld",
|
||||
"External: no",
|
||||
"Active: yes",
|
||||
"Creation Date: 2022-04-06T16:20:00Z",
|
||||
"Last Modified: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintUserAfterModificationInGerman() {
|
||||
testRenderer.setLocale("de");
|
||||
command.setDisplayName("Lord Vetinari");
|
||||
command.setEmail("patrician@discworld");
|
||||
|
||||
command.run();
|
||||
|
||||
assertThat(testRenderer.getStdOut())
|
||||
.contains(
|
||||
"Benutzername: havelock",
|
||||
"Anzeigename: Lord Vetinari ",
|
||||
"E-Mail-Adresse: patrician@discworld",
|
||||
"Extern: nein",
|
||||
"Aktiv: ja",
|
||||
"Erstellt: 2022-04-06T16:20:00Z",
|
||||
"Zuletzt bearbeitet: 2022-04-06T19:06:40Z"
|
||||
);
|
||||
assertThat(testRenderer.getStdErr()).isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
class ForUnsuccessfulModificationTest {
|
||||
|
||||
@Test
|
||||
void shouldFailIfValidatorFails() {
|
||||
doThrow(picocli.CommandLine.ParameterException.class).when(validator).validate();
|
||||
|
||||
assertThrows(
|
||||
picocli.CommandLine.ParameterException.class,
|
||||
() -> command.run()
|
||||
);
|
||||
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithEnglishMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("en");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Could not find user");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldFailWithGermanMsgIfUserNotFound() {
|
||||
testRenderer.setLocale("de");
|
||||
when(manager.get(any())).thenReturn(null);
|
||||
|
||||
assertThrows(CliExitException.class, () -> command.run());
|
||||
|
||||
verify(manager, never()).modify(any());
|
||||
assertThat(testRenderer.getStdOut()).isEmpty();
|
||||
assertThat(testRenderer.getStdErr()).contains("Benutzer konnte nicht gefunden werden");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 sonia.scm.user.cli;
|
||||
|
||||
import sonia.scm.cli.TemplateTestRenderer;
|
||||
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
class UserTemplateTestRenderer {
|
||||
private final TemplateTestRenderer testRenderer = new TemplateTestRenderer();
|
||||
private final UserCommandBeanMapper beanMapper = new UserCommandBeanMapperImpl();
|
||||
private final UserTemplateRenderer templateRenderer = new UserTemplateRenderer(testRenderer.getContextMock(), testRenderer.getTemplateEngineFactory(), beanMapper) {
|
||||
@Override
|
||||
protected ResourceBundle getBundle() {
|
||||
return testRenderer.getResourceBundle();
|
||||
}
|
||||
};
|
||||
|
||||
UserTemplateRenderer getTemplateRenderer() {
|
||||
return templateRenderer;
|
||||
}
|
||||
|
||||
String getStdOut() {
|
||||
return testRenderer.getStdOut();
|
||||
}
|
||||
|
||||
String getStdErr() {
|
||||
return testRenderer.getStdErr();
|
||||
}
|
||||
|
||||
public void setLocale(String locale) {
|
||||
testRenderer.setLocale(locale);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user