Merge with develop branch

This commit is contained in:
Sebastian Sdorra
2020-08-12 14:30:26 +02:00
99 changed files with 2199 additions and 557 deletions

View File

@@ -29,6 +29,7 @@ import de.otto.edison.hal.Links;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import sonia.scm.security.AnonymousMode;
import java.util.Set;
@@ -46,6 +47,7 @@ public class ConfigDto extends HalRepresentation {
private boolean disableGroupingGrid;
private String dateFormat;
private boolean anonymousAccessEnabled;
private AnonymousMode anonymousMode;
private String baseUrl;
private boolean forceBaseUrl;
private int loginAttemptLimit;

View File

@@ -21,11 +21,14 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.AnonymousMode;
// Mapstruct does not support parameterized (i.e. non-default) constructors. Thus, we need to use field injection.
@SuppressWarnings("squid:S3306")
@@ -33,4 +36,15 @@ import sonia.scm.config.ScmConfiguration;
public abstract class ConfigDtoToScmConfigurationMapper {
public abstract ScmConfiguration map(ConfigDto dto);
@AfterMapping // Should map anonymous mode from old flag if not send explicit
void mapAnonymousMode(@MappingTarget ScmConfiguration config, ConfigDto configDto) {
if (configDto.getAnonymousMode() == null) {
if (configDto.isAnonymousAccessEnabled()) {
config.setAnonymousMode(AnonymousMode.PROTOCOL_ONLY);
} else {
config.setAnonymousMode(AnonymousMode.OFF);
}
}
}
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import io.swagger.v3.oas.annotations.Operation;
@@ -31,6 +31,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import sonia.scm.group.Group;
import sonia.scm.group.GroupManager;
import sonia.scm.group.GroupPermissions;
import sonia.scm.search.SearchRequest;
import sonia.scm.search.SearchUtil;
import sonia.scm.web.VndMediaType;
@@ -106,6 +107,7 @@ public class GroupCollectionResource {
@QueryParam("desc") boolean desc,
@DefaultValue("") @QueryParam("q") String search
) {
GroupPermissions.list().check();
return adapter.getAll(page, pageSize, createSearchPredicate(search), sortBy, desc,
pageResult -> groupCollectionToDtoMapper.map(page, pageSize, pageResult));
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import com.google.common.base.Strings;
@@ -35,6 +35,7 @@ import sonia.scm.config.ConfigurationPermissions;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.group.GroupPermissions;
import sonia.scm.plugin.PluginPermissions;
import sonia.scm.security.AnonymousMode;
import sonia.scm.security.Authentications;
import sonia.scm.security.PermissionPermissions;
import sonia.scm.user.UserPermissions;
@@ -70,7 +71,7 @@ public class IndexDtoGenerator extends HalAppenderMapper {
builder.single(link("loginInfo", loginInfoUrl));
}
if (SecurityUtils.getSubject().isAuthenticated()) {
if (shouldAppendSubjectRelatedLinks()) {
builder.single(link("me", resourceLinks.me().self()));
if (Authentications.isAuthenticatedSubjectAnonymous()) {
@@ -120,4 +121,19 @@ public class IndexDtoGenerator extends HalAppenderMapper {
return new IndexDto(builder.build(), embeddedBuilder.build(), scmContextProvider.getVersion());
}
private boolean shouldAppendSubjectRelatedLinks() {
return isAuthenticatedSubjectNotAnonymous()
|| isAuthenticatedSubjectAllowedToBeAnonymous();
}
private boolean isAuthenticatedSubjectAllowedToBeAnonymous() {
return Authentications.isAuthenticatedSubjectAnonymous()
&& configuration.getAnonymousMode() == AnonymousMode.FULL;
}
private boolean isAuthenticatedSubjectNotAnonymous() {
return SecurityUtils.getSubject().isAuthenticated()
&& !Authentications.isAuthenticatedSubjectAnonymous();
}
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Embedded;
@@ -30,7 +30,6 @@ import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import sonia.scm.group.GroupCollector;
import sonia.scm.security.Authentications;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
import sonia.scm.user.UserPermissions;
@@ -92,7 +91,7 @@ public class MeDtoFactory extends HalAppenderMapper {
if (UserPermissions.changePublicKeys(user).isPermitted()) {
linksBuilder.single(link("publicKeys", resourceLinks.user().publicKeys(user.getName())));
}
if (userManager.isTypeDefault(user) && UserPermissions.changePassword(user).isPermitted() && !Authentications.isSubjectAnonymous(user.getName())) {
if (userManager.isTypeDefault(user) && UserPermissions.changePassword(user).isPermitted()) {
linksBuilder.single(link("password", resourceLinks.me().passwordChange()));
}
@@ -101,5 +100,4 @@ public class MeDtoFactory extends HalAppenderMapper {
return new MeDto(linksBuilder.build(), embeddedBuilder.build());
}
}

View File

@@ -27,9 +27,12 @@ package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import org.mapstruct.Named;
import sonia.scm.config.ConfigurationPermissions;
import sonia.scm.config.ScmConfiguration;
import sonia.scm.security.AnonymousMode;
import javax.inject.Inject;
@@ -44,6 +47,15 @@ public abstract class ScmConfigurationToConfigDtoMapper extends BaseMapper<ScmCo
@Inject
private ResourceLinks resourceLinks;
@Mapping(target = "anonymousAccessEnabled", source = "anonymousMode", qualifiedByName = "mapAnonymousAccess")
@Mapping(target = "attributes", ignore = true)
public abstract ConfigDto map(ScmConfiguration scmConfiguration);
@Named("mapAnonymousAccess")
boolean mapAnonymousAccess(AnonymousMode anonymousMode) {
return anonymousMode != AnonymousMode.OFF;
}
@AfterMapping
void appendLinks(ScmConfiguration config, @MappingTarget ConfigDto target) {
Links.Builder linksBuilder = linkingTo().self(resourceLinks.config().self());

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import io.swagger.v3.oas.annotations.Operation;
@@ -34,6 +34,7 @@ import sonia.scm.search.SearchRequest;
import sonia.scm.search.SearchUtil;
import sonia.scm.user.User;
import sonia.scm.user.UserManager;
import sonia.scm.user.UserPermissions;
import sonia.scm.web.VndMediaType;
import javax.inject.Inject;
@@ -108,6 +109,7 @@ public class UserCollectionResource {
@DefaultValue("false") @QueryParam("desc") boolean desc,
@DefaultValue("") @QueryParam("q") String search
) {
UserPermissions.list().check();
return adapter.getAll(page, pageSize, createSearchPredicate(search), sortBy, desc,
pageResult -> userCollectionToDtoMapper.map(page, pageSize, pageResult));
}