mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-11-10 07:25:44 +01:00
merge repository heads
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
//@flow
|
||||
import React from "react";
|
||||
import type { Me } from "../types/me";
|
||||
|
||||
type Props = {
|
||||
me?: Me
|
||||
me?: string
|
||||
};
|
||||
|
||||
class Footer extends React.Component<Props> {
|
||||
@@ -15,7 +14,7 @@ class Footer extends React.Component<Props> {
|
||||
return (
|
||||
<footer className="footer">
|
||||
<div className="container is-centered">
|
||||
<p className="has-text-centered">{me.username}</p>
|
||||
<p className="has-text-centered">{me}</p>
|
||||
</div>
|
||||
</footer>
|
||||
);
|
||||
|
||||
@@ -18,6 +18,7 @@ type Props = {
|
||||
error: Error,
|
||||
loading: boolean,
|
||||
authenticated?: boolean,
|
||||
displayName: string,
|
||||
t: string => string,
|
||||
fetchMe: () => void
|
||||
};
|
||||
@@ -28,7 +29,7 @@ class App extends Component<Props> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { entry, loading, error, t, authenticated } = this.props;
|
||||
const { loading, error, authenticated, displayName, t } = this.props;
|
||||
|
||||
let content;
|
||||
const navigation = authenticated ? <PrimaryNavigation /> : "";
|
||||
@@ -50,7 +51,7 @@ class App extends Component<Props> {
|
||||
<div className="App">
|
||||
<Header>{navigation}</Header>
|
||||
{content}
|
||||
<Footer me={entry} />
|
||||
<Footer me={displayName} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -64,10 +65,17 @@ const mapDispatchToProps = (dispatch: any) => {
|
||||
|
||||
const mapStateToProps = state => {
|
||||
let mapped = state.auth.me || {};
|
||||
let displayName;
|
||||
if (state.auth.login) {
|
||||
mapped.authenticated = state.auth.login.authenticated;
|
||||
}
|
||||
return mapped;
|
||||
if (state.auth.me && state.auth.me.entry) {
|
||||
displayName = state.auth.me.entry.entity.displayName;
|
||||
}
|
||||
return {
|
||||
...mapped,
|
||||
displayName
|
||||
};
|
||||
};
|
||||
|
||||
export default withRouter(
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// @flow
|
||||
export type Me = {
|
||||
username: string
|
||||
};
|
||||
@@ -25,6 +25,7 @@ export const DELETE_USER_SUCCESS = "scm/users/DELETE_SUCCESS";
|
||||
export const DELETE_USER_FAILURE = "scm/users/DELETE_FAILURE";
|
||||
|
||||
const USERS_URL = "users";
|
||||
const USER_URL = "users/";
|
||||
|
||||
const CONTENT_TYPE_USER = "application/vnd.scmm-user+json;v=2";
|
||||
|
||||
|
||||
@@ -1,34 +1,52 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import com.webcohesion.enunciate.metadata.rs.ResponseCode;
|
||||
import com.webcohesion.enunciate.metadata.rs.StatusCodes;
|
||||
import com.webcohesion.enunciate.metadata.rs.TypeHint;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserException;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.Request;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
|
||||
|
||||
@Path(MeResource.ME_PATH_V2)
|
||||
public class MeResource {
|
||||
static final String ME_PATH_V2 = "v2/me/";
|
||||
|
||||
private final UserToUserDtoMapper userToDtoMapper;
|
||||
|
||||
private final IdResourceManagerAdapter<User, UserDto, UserException> adapter;
|
||||
@Inject
|
||||
public MeResource(UserToUserDtoMapper userToDtoMapper, UserManager manager) {
|
||||
this.userToDtoMapper = userToDtoMapper;
|
||||
this.adapter = new IdResourceManagerAdapter<>(manager, User.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently logged in user or a 401 if user is not logged in
|
||||
*/
|
||||
@GET
|
||||
@Produces(VndMediaType.ME)
|
||||
public Response get() {
|
||||
MeDto meDto = new MeDto((String) SecurityUtils.getSubject().getPrincipals().getPrimaryPrincipal());
|
||||
return Response.ok(meDto).build();
|
||||
}
|
||||
@Path("")
|
||||
@Produces(VndMediaType.USER)
|
||||
@TypeHint(UserDto.class)
|
||||
@StatusCodes({
|
||||
@ResponseCode(code = 200, condition = "success"),
|
||||
@ResponseCode(code = 401, condition = "not authenticated / invalid credentials"),
|
||||
@ResponseCode(code = 500, condition = "internal server error")
|
||||
})
|
||||
public Response get(@Context Request request, @Context UriInfo uriInfo) {
|
||||
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
class MeDto {
|
||||
String username;
|
||||
String id = (String) SecurityUtils.getSubject().getPrincipals().getPrimaryPrincipal();
|
||||
return adapter.get(id, userToDtoMapper::map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
package sonia.scm.api.v2.resources;
|
||||
|
||||
import com.github.sdorra.shiro.ShiroRule;
|
||||
import com.github.sdorra.shiro.SubjectAware;
|
||||
import com.google.common.io.Resources;
|
||||
import org.apache.shiro.authc.credential.PasswordService;
|
||||
import org.apache.shiro.subject.PrincipalCollection;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.jboss.resteasy.core.Dispatcher;
|
||||
import org.jboss.resteasy.mock.MockDispatcherFactory;
|
||||
import org.jboss.resteasy.mock.MockHttpRequest;
|
||||
import org.jboss.resteasy.mock.MockHttpResponse;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import sonia.scm.PageResult;
|
||||
import sonia.scm.user.User;
|
||||
import sonia.scm.user.UserException;
|
||||
import sonia.scm.user.UserManager;
|
||||
import sonia.scm.web.VndMediaType;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
|
||||
import static java.util.Collections.singletonList;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Matchers.eq;
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.mockito.MockitoAnnotations.initMocks;
|
||||
|
||||
@SubjectAware(
|
||||
// username = "trillian",
|
||||
// password = "secret",
|
||||
configuration = "classpath:sonia/scm/repository/shiro.ini"
|
||||
)
|
||||
public class MeResourceTest {
|
||||
|
||||
@Rule
|
||||
public ShiroRule shiro = new ShiroRule();
|
||||
|
||||
private Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
|
||||
|
||||
@Mock
|
||||
private UriInfo uriInfo;
|
||||
@Mock
|
||||
private UriInfoStore uriInfoStore;
|
||||
|
||||
@Mock
|
||||
private UserManager userManager;
|
||||
|
||||
@InjectMocks
|
||||
private UserToUserDtoMapperImpl userToDtoMapper;
|
||||
|
||||
private ArgumentCaptor<User> userCaptor = ArgumentCaptor.forClass(User.class);
|
||||
|
||||
@Before
|
||||
public void prepareEnvironment() throws IOException, UserException {
|
||||
initMocks(this);
|
||||
createDummyUser("trillian");
|
||||
doNothing().when(userManager).create(userCaptor.capture());
|
||||
doNothing().when(userManager).modify(userCaptor.capture());
|
||||
doNothing().when(userManager).delete(userCaptor.capture());
|
||||
MeResource meResource = new MeResource(userToDtoMapper, userManager);
|
||||
dispatcher.getRegistry().addSingletonResource(meResource);
|
||||
when(uriInfo.getBaseUri()).thenReturn(URI.create("/"));
|
||||
when(uriInfoStore.get()).thenReturn(uriInfo);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SubjectAware(username = "trillian", password = "secret")
|
||||
public void shouldReturnCurrentlyAuthenticatedUser() throws URISyntaxException {
|
||||
MockHttpRequest request = MockHttpRequest.get("/" + MeResource.ME_PATH_V2);
|
||||
request.accept(VndMediaType.USER);
|
||||
MockHttpResponse response = new MockHttpResponse();
|
||||
|
||||
dispatcher.invoke(request, response);
|
||||
|
||||
assertEquals(HttpServletResponse.SC_OK, response.getStatus());
|
||||
assertTrue(response.getContentAsString().contains("\"name\":\"trillian\""));
|
||||
assertTrue(response.getContentAsString().contains("\"password\":\"__dummypassword__\""));
|
||||
assertTrue(response.getContentAsString().contains("\"self\":{\"href\":\"/v2/users/trillian\"}"));
|
||||
assertTrue(response.getContentAsString().contains("\"delete\":{\"href\":\"/v2/users/trillian\"}"));
|
||||
}
|
||||
|
||||
private User createDummyUser(String name) {
|
||||
User user = new User();
|
||||
user.setName(name);
|
||||
user.setPassword("secret");
|
||||
user.setCreationDate(System.currentTimeMillis());
|
||||
when(userManager.get(name)).thenReturn(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user