mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-12 16:35:45 +01:00
Merge with 2.0.0-m3
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package sonia.scm.api.v2;
|
||||
|
||||
public final class ValidationConstraints {
|
||||
|
||||
private ValidationConstraints() {}
|
||||
|
||||
/**
|
||||
* A user or group name should not start with <code>@</code> or a whitespace
|
||||
* and it not contains whitespaces
|
||||
* and the characters: . - _ @ are allowed
|
||||
*/
|
||||
public static final String USER_GROUP_PATTERN = "^[A-Za-z0-9\\.\\-_][A-Za-z0-9\\.\\-_@]*$";
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
import sonia.scm.group.GroupManager;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Response;
|
||||
import java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
@Path(AutoCompleteResource.PATH)
|
||||
public class AutoCompleteResource {
|
||||
public static final String PATH = "v2/autocomplete/";
|
||||
public static final int MIN_SEARCHED_CHARS = 2;
|
||||
|
||||
public static final String PARAMETER_IS_REQUIRED = "The parameter is required.";
|
||||
public static final String INVALID_PARAMETER_LENGTH = "Invalid parameter length.";
|
||||
|
||||
|
||||
private ReducedObjectModelToDtoMapper mapper;
|
||||
|
||||
private UserManager userManager;
|
||||
private GroupManager groupManager;
|
||||
|
||||
@Inject
|
||||
public AutoCompleteResource(ReducedObjectModelToDtoMapper mapper, UserManager userManager, GroupManager groupManager) {
|
||||
this.mapper = mapper;
|
||||
this.userManager = userManager;
|
||||
this.groupManager = groupManager;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("user")
|
||||
@Produces(VndMediaType.AUTOCOMPLETE)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "if the searched string contains less than 2 characters"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"user:autocomplete\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response searchUser(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter) {
|
||||
return map(userManager.autocomplete(filter));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("group")
|
||||
@Produces(VndMediaType.AUTOCOMPLETE)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 400, condition = "if the searched string contains less than 2 characters"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 403, condition = "not authorized, the current user does not have the \"group:autocomplete\" privilege"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response searchGroup(@NotEmpty(message = PARAMETER_IS_REQUIRED) @Size(min = MIN_SEARCHED_CHARS, message = INVALID_PARAMETER_LENGTH) @QueryParam("filter") String filter) {
|
||||
return map(groupManager.autocomplete(filter));
|
||||
}
|
||||
|
||||
private <T extends ReducedModelObject> Response map(Collection<T> autocomplete) {
|
||||
return Response.ok(autocomplete
|
||||
.stream()
|
||||
.map(mapper::map)
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -12,12 +12,12 @@ public class BranchChangesetCollectionToDtoMapper extends ChangesetCollectionToD
|
||||
|
||||
@Inject
|
||||
public BranchChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
super(changesetToChangesetDtoMapper);
|
||||
super(changesetToChangesetDtoMapper, resourceLinks);
|
||||
this.resourceLinks = resourceLinks;
|
||||
}
|
||||
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, String branch) {
|
||||
return this.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository, branch));
|
||||
return this.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository, branch), branch);
|
||||
}
|
||||
|
||||
private String createSelfLink(Repository repository, String branch) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@NoArgsConstructor @AllArgsConstructor @Getter @Setter
|
||||
public class BranchReferenceDto extends HalRepresentation {
|
||||
private String name;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
|
||||
protected HalRepresentation add(Links links) {
|
||||
return super.add(links);
|
||||
}
|
||||
}
|
||||
@@ -12,10 +12,13 @@ public class ChangesetCollectionToDtoMapper extends ChangesetCollectionToDtoMapp
|
||||
|
||||
@Inject
|
||||
public ChangesetCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
super(changesetToChangesetDtoMapper);
|
||||
super(changesetToChangesetDtoMapper, resourceLinks);
|
||||
this.resourceLinks = resourceLinks;
|
||||
}
|
||||
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, String branchName) {
|
||||
return super.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository), branchName);
|
||||
}
|
||||
public CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository) {
|
||||
return super.map(pageNumber, pageSize, pageResult, repository, () -> createSelfLink(repository));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.Links;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.repository.Changeset;
|
||||
import sonia.scm.repository.Repository;
|
||||
@@ -10,14 +11,28 @@ import java.util.function.Supplier;
|
||||
class ChangesetCollectionToDtoMapperBase extends PagedCollectionToDtoMapper<Changeset, ChangesetDto> {
|
||||
|
||||
private final ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper;
|
||||
private final ResourceLinks resourceLinks;
|
||||
|
||||
ChangesetCollectionToDtoMapperBase(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper) {
|
||||
ChangesetCollectionToDtoMapperBase(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
super("changesets");
|
||||
this.changesetToChangesetDtoMapper = changesetToChangesetDtoMapper;
|
||||
this.resourceLinks = resourceLinks;
|
||||
}
|
||||
|
||||
CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, Supplier<String> selfLinkSupplier) {
|
||||
return super.map(pageNumber, pageSize, pageResult, selfLinkSupplier.get(), Optional.empty(), changeset -> changesetToChangesetDtoMapper.map(changeset, repository));
|
||||
}
|
||||
}
|
||||
|
||||
CollectionDto map(int pageNumber, int pageSize, PageResult<Changeset> pageResult, Repository repository, Supplier<String> selfLinkSupplier, String branchName) {
|
||||
CollectionDto collectionDto = this.map(pageNumber, pageSize, pageResult, repository, selfLinkSupplier);
|
||||
collectionDto.withEmbedded("branch", createBranchReferenceDto(repository, branchName));
|
||||
return collectionDto;
|
||||
}
|
||||
|
||||
private BranchReferenceDto createBranchReferenceDto(Repository repository, String branchName) {
|
||||
BranchReferenceDto branchReferenceDto = new BranchReferenceDto();
|
||||
branchReferenceDto.setName(branchName);
|
||||
branchReferenceDto.add(Links.linkingTo().self(resourceLinks.branch().self(repository.getNamespaceAndName(), branchName)).build());
|
||||
return branchReferenceDto;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,11 @@ public class ChangesetRootResource {
|
||||
.getChangesets();
|
||||
if (changesets != null && changesets.getChangesets() != null) {
|
||||
PageResult<Changeset> pageResult = new PageResult<>(changesets.getChangesets(), changesets.getTotal());
|
||||
return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository)).build();
|
||||
if (changesets.getBranchName() != null) {
|
||||
return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository, changesets.getBranchName())).build();
|
||||
} else {
|
||||
return Response.ok(changesetCollectionToDtoMapper.map(page, pageSize, pageResult, repository)).build();
|
||||
}
|
||||
} else {
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
@@ -15,4 +15,9 @@ class CollectionDto extends HalRepresentation {
|
||||
CollectionDto(Links links, Embedded embedded) {
|
||||
super(links, embedded);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HalRepresentation withEmbedded(String rel, HalRepresentation embeddedItem) {
|
||||
return super.withEmbedded(rel, embeddedItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ public class FileHistoryCollectionToDtoMapper extends ChangesetCollectionToDtoMa
|
||||
|
||||
@Inject
|
||||
public FileHistoryCollectionToDtoMapper(ChangesetToChangesetDtoMapper changesetToChangesetDtoMapper, ResourceLinks resourceLinks) {
|
||||
super(changesetToChangesetDtoMapper);
|
||||
super(changesetToChangesetDtoMapper, resourceLinks);
|
||||
this.resourceLinks = resourceLinks;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static sonia.scm.api.v2.ValidationConstraints.USER_GROUP_PATTERN;
|
||||
|
||||
@Getter @Setter @NoArgsConstructor
|
||||
public class GroupDto extends HalRepresentation {
|
||||
|
||||
@@ -20,9 +22,8 @@ public class GroupDto extends HalRepresentation {
|
||||
private String description;
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private Instant lastModified;
|
||||
@Pattern(regexp = "^[A-z0-9\\.\\-_@]|[^ ]([A-z0-9\\.\\-_@ ]*[A-z0-9\\.\\-_@]|[^ ])?$")
|
||||
@Pattern(regexp = USER_GROUP_PATTERN)
|
||||
private String name;
|
||||
@NotEmpty
|
||||
private String type;
|
||||
private Map<String, String> properties;
|
||||
private List<String> members;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class IndexDto extends HalRepresentation {
|
||||
|
||||
private final String version;
|
||||
|
||||
IndexDto(String version, Links links) {
|
||||
super(links);
|
||||
this.version = version;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.Links;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import sonia.scm.SCMContextProvider;
|
||||
import sonia.scm.config.ConfigurationPermissions;
|
||||
import sonia.scm.group.GroupPermissions;
|
||||
import sonia.scm.user.UserPermissions;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static de.otto.edison.hal.Link.link;
|
||||
|
||||
public class IndexDtoGenerator {
|
||||
|
||||
private final ResourceLinks resourceLinks;
|
||||
private final SCMContextProvider scmContextProvider;
|
||||
|
||||
@Inject
|
||||
public IndexDtoGenerator(ResourceLinks resourceLinks, SCMContextProvider scmContextProvider) {
|
||||
this.resourceLinks = resourceLinks;
|
||||
this.scmContextProvider = scmContextProvider;
|
||||
}
|
||||
|
||||
public IndexDto generate() {
|
||||
Links.Builder builder = Links.linkingTo();
|
||||
builder.self(resourceLinks.index().self());
|
||||
builder.single(link("uiPlugins", resourceLinks.uiPluginCollection().self()));
|
||||
if (SecurityUtils.getSubject().isAuthenticated()) {
|
||||
builder.single(
|
||||
link("me", resourceLinks.me().self()),
|
||||
link("logout", resourceLinks.authentication().logout())
|
||||
);
|
||||
if (UserPermissions.list().isPermitted()) {
|
||||
builder.single(link("users", resourceLinks.userCollection().self()));
|
||||
}
|
||||
if (GroupPermissions.list().isPermitted()) {
|
||||
builder.single(link("groups", resourceLinks.groupCollection().self()));
|
||||
}
|
||||
if (ConfigurationPermissions.list().isPermitted()) {
|
||||
builder.single(link("config", resourceLinks.config().self()));
|
||||
}
|
||||
builder.single(link("repositories", resourceLinks.repositoryCollection().self()));
|
||||
} else {
|
||||
builder.single(link("login", resourceLinks.authentication().jsonLogin()));
|
||||
}
|
||||
|
||||
return new IndexDto(scmContextProvider.getVersion(), builder.build());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
||||
@Path(IndexResource.INDEX_PATH_V2)
|
||||
public class IndexResource {
|
||||
public static final String INDEX_PATH_V2 = "v2/";
|
||||
|
||||
private final IndexDtoGenerator indexDtoGenerator;
|
||||
|
||||
@Inject
|
||||
public IndexResource(IndexDtoGenerator indexDtoGenerator) {
|
||||
this.indexDtoGenerator = indexDtoGenerator;
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("")
|
||||
@Produces(VndMediaType.INDEX)
|
||||
@TypeHint(IndexDto.class)
|
||||
public IndexDto getIndex() {
|
||||
return indexDtoGenerator.generate();
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ public class MapperModule extends AbstractModule {
|
||||
bind(FileObjectToFileObjectDtoMapper.class).to(Mappers.getMapper(FileObjectToFileObjectDtoMapper.class).getClass());
|
||||
bind(ModificationsToDtoMapper.class).to(Mappers.getMapper(ModificationsToDtoMapper.class).getClass());
|
||||
|
||||
bind(ReducedObjectModelToDtoMapper.class).to(Mappers.getMapper(ReducedObjectModelToDtoMapper.class).getClass());
|
||||
|
||||
// no mapstruct required
|
||||
bind(UIPluginDtoMapper.class);
|
||||
bind(UIPluginDtoCollectionMapper.class);
|
||||
|
||||
@@ -4,15 +4,20 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import de.otto.edison.hal.Links;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter @Setter @ToString
|
||||
import javax.validation.constraints.Pattern;
|
||||
|
||||
import static sonia.scm.api.v2.ValidationConstraints.USER_GROUP_PATTERN;
|
||||
|
||||
@Getter @Setter @ToString @NoArgsConstructor
|
||||
public class PermissionDto extends HalRepresentation {
|
||||
|
||||
public static final String GROUP_PREFIX = "@";
|
||||
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@Pattern(regexp = USER_GROUP_PATTERN)
|
||||
private String name;
|
||||
|
||||
/**
|
||||
@@ -28,9 +33,6 @@ public class PermissionDto extends HalRepresentation {
|
||||
|
||||
private boolean groupPermission = false;
|
||||
|
||||
public PermissionDto() {
|
||||
}
|
||||
|
||||
public PermissionDto(String permissionName, boolean groupPermission) {
|
||||
name = permissionName;
|
||||
this.groupPermission = groupPermission;
|
||||
|
||||
@@ -16,6 +16,7 @@ import sonia.scm.repository.RepositoryPermissions;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.validation.Valid;
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
@@ -70,14 +71,15 @@ public class PermissionRootResource {
|
||||
@TypeHint(TypeHint.NO_CONTENT.class)
|
||||
@Consumes(VndMediaType.PERMISSION)
|
||||
@Path("")
|
||||
public Response create(@PathParam("namespace") String namespace, @PathParam("name") String name, PermissionDto permission) throws Exception {
|
||||
public Response create(@PathParam("namespace") String namespace, @PathParam("name") String name,@Valid PermissionDto permission) throws AlreadyExistsException, NotFoundException {
|
||||
log.info("try to add new permission: {}", permission);
|
||||
Repository repository = load(namespace, name);
|
||||
RepositoryPermissions.permissionWrite(repository).check();
|
||||
checkPermissionAlreadyExists(permission, repository);
|
||||
repository.getPermissions().add(dtoToModelMapper.map(permission));
|
||||
manager.modify(repository);
|
||||
return Response.created(URI.create(resourceLinks.permission().self(namespace, name, permission.getName()))).build();
|
||||
String urlPermissionName = modelToDtoMapper.getUrlPermissionName(permission);
|
||||
return Response.created(URI.create(resourceLinks.permission().self(namespace, name, urlPermissionName))).build();
|
||||
}
|
||||
|
||||
|
||||
@@ -156,7 +158,7 @@ public class PermissionRootResource {
|
||||
public Response update(@PathParam("namespace") String namespace,
|
||||
@PathParam("name") String name,
|
||||
@PathParam("permission-name") String permissionName,
|
||||
PermissionDto permission) throws NotFoundException, AlreadyExistsException {
|
||||
@Valid PermissionDto permission) throws NotFoundException, AlreadyExistsException {
|
||||
log.info("try to update the permission with name: {}. the modified permission is: {}", permissionName, permission);
|
||||
Repository repository = load(namespace, name);
|
||||
RepositoryPermissions.permissionWrite(repository).check();
|
||||
|
||||
@@ -41,9 +41,7 @@ public abstract class PermissionToPermissionDtoMapper {
|
||||
*/
|
||||
@AfterMapping
|
||||
void appendLinks(@MappingTarget PermissionDto target, @Context Repository repository) {
|
||||
String permissionName = Optional.of(target.getName())
|
||||
.filter(p -> !target.isGroupPermission())
|
||||
.orElse(GROUP_PREFIX + target.getName());
|
||||
String permissionName = getUrlPermissionName(target);
|
||||
Links.Builder linksBuilder = linkingTo()
|
||||
.self(resourceLinks.permission().self(repository.getNamespace(), repository.getName(), permissionName));
|
||||
if (RepositoryPermissions.permissionWrite(repository).isPermitted()) {
|
||||
@@ -52,4 +50,10 @@ public abstract class PermissionToPermissionDtoMapper {
|
||||
}
|
||||
target.add(linksBuilder.build());
|
||||
}
|
||||
|
||||
public String getUrlPermissionName(PermissionDto permissionDto) {
|
||||
return Optional.of(permissionDto.getName())
|
||||
.filter(p -> !permissionDto.isGroupPermission())
|
||||
.orElse(GROUP_PREFIX + permissionDto.getName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import de.otto.edison.hal.HalRepresentation;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class ReducedObjectModelDto extends HalRepresentation {
|
||||
|
||||
private String id;
|
||||
|
||||
private String displayName;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.Mapping;
|
||||
import sonia.scm.ReducedModelObject;
|
||||
|
||||
@Mapper
|
||||
public abstract class ReducedObjectModelToDtoMapper {
|
||||
|
||||
@Mapping(target = "attributes", ignore = true) // We do not map HAL attributes
|
||||
public abstract ReducedObjectModelDto map(ReducedModelObject modelObject);
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@ package sonia.scm.api.v2.resources;
|
||||
import sonia.scm.repository.NamespaceAndName;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.net.URI;
|
||||
|
||||
class ResourceLinks {
|
||||
@@ -441,7 +440,6 @@ class ResourceLinks {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public UIPluginLinks uiPlugin() {
|
||||
return new UIPluginLinks(scmPathInfoStore.get());
|
||||
}
|
||||
@@ -473,4 +471,45 @@ class ResourceLinks {
|
||||
return uiPluginCollectionLinkBuilder.method("plugins").parameters().method("getInstalledPlugins").parameters().href();
|
||||
}
|
||||
}
|
||||
|
||||
public AuthenticationLinks authentication() {
|
||||
return new AuthenticationLinks(scmPathInfoStore.get());
|
||||
}
|
||||
|
||||
static class AuthenticationLinks {
|
||||
private final LinkBuilder loginLinkBuilder;
|
||||
|
||||
AuthenticationLinks(ScmPathInfo pathInfo) {
|
||||
this.loginLinkBuilder = new LinkBuilder(pathInfo, AuthenticationResource.class);
|
||||
}
|
||||
|
||||
String formLogin() {
|
||||
return loginLinkBuilder.method("authenticateViaForm").parameters().href();
|
||||
}
|
||||
|
||||
String jsonLogin() {
|
||||
return loginLinkBuilder.method("authenticateViaJSONBody").parameters().href();
|
||||
}
|
||||
|
||||
String logout() {
|
||||
return loginLinkBuilder.method("logout").parameters().href();
|
||||
}
|
||||
}
|
||||
|
||||
public IndexLinks index() {
|
||||
return new IndexLinks(scmPathInfoStore.get());
|
||||
}
|
||||
|
||||
static class IndexLinks {
|
||||
private final LinkBuilder indexLinkBuilder;
|
||||
|
||||
IndexLinks(ScmPathInfo pathInfo) {
|
||||
indexLinkBuilder = new LinkBuilder(pathInfo, IndexResource.class);
|
||||
}
|
||||
|
||||
String self() {
|
||||
return indexLinkBuilder.method("getIndex").parameters().href();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import javax.validation.constraints.Pattern;
|
||||
import java.time.Instant;
|
||||
import java.util.Map;
|
||||
|
||||
import static sonia.scm.api.v2.ValidationConstraints.USER_GROUP_PATTERN;
|
||||
|
||||
@NoArgsConstructor @Getter @Setter
|
||||
public class UserDto extends HalRepresentation {
|
||||
private boolean active;
|
||||
@@ -24,7 +26,7 @@ public class UserDto extends HalRepresentation {
|
||||
private Instant lastModified;
|
||||
@NotEmpty @Email
|
||||
private String mail;
|
||||
@Pattern(regexp = "^[A-z0-9\\.\\-_@]|[^ ]([A-z0-9\\.\\-_@ ]*[A-z0-9\\.\\-_@]|[^ ])?$")
|
||||
@Pattern(regexp = USER_GROUP_PATTERN)
|
||||
private String name;
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
private String password;
|
||||
|
||||
Reference in New Issue
Block a user