Implemented authorisation
This commit is contained in:
parent
11ca677f65
commit
b48b375e4e
@ -0,0 +1,39 @@
|
|||||||
|
package ru.dragonestia.picker.api.exception;
|
||||||
|
|
||||||
|
import ru.dragonestia.picker.api.repository.response.ErrorResponse;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class AccountDoesNotExistsException extends ApiException {
|
||||||
|
|
||||||
|
public static final String ERROR_ID = "err.account.does_not_exists";
|
||||||
|
|
||||||
|
private final String accountId;
|
||||||
|
|
||||||
|
public AccountDoesNotExistsException(String accountId) {
|
||||||
|
this.accountId = accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccountDoesNotExistsException(ErrorResponse errorResponse) {
|
||||||
|
this(errorResponse.details().get("accountId"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getErrorId() {
|
||||||
|
return ERROR_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMessage() {
|
||||||
|
return "Account with id '" + accountId + "' does not exists";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendDetailsToErrorResponse(Map<String, String> details) {
|
||||||
|
details.put("accountId", accountId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -25,6 +25,7 @@ public class ExceptionFactory {
|
|||||||
factory.put(RoomAreFullException.ERROR_ID, RoomAreFullException::new);
|
factory.put(RoomAreFullException.ERROR_ID, RoomAreFullException::new);
|
||||||
factory.put(RoomNotFoundException.ERROR_ID, RoomNotFoundException::new);
|
factory.put(RoomNotFoundException.ERROR_ID, RoomNotFoundException::new);
|
||||||
factory.put(NotPersistedNodeException.ERROR_ID, NotPersistedNodeException::new);
|
factory.put(NotPersistedNodeException.ERROR_ID, NotPersistedNodeException::new);
|
||||||
|
factory.put(AccountDoesNotExistsException.ERROR_ID, AccountDoesNotExistsException::new);
|
||||||
|
|
||||||
return factory;
|
return factory;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,8 +2,10 @@ package ru.dragonestia.picker.api.impl.repository;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.ApiStatus.Internal;
|
import org.jetbrains.annotations.ApiStatus.Internal;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import ru.dragonestia.picker.api.exception.AccountDoesNotExistsException;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
import ru.dragonestia.picker.api.impl.util.RestTemplate;
|
import ru.dragonestia.picker.api.impl.util.RestTemplate;
|
||||||
|
import ru.dragonestia.picker.api.impl.util.type.HttpMethod;
|
||||||
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
||||||
import ru.dragonestia.picker.api.repository.AccountRepository;
|
import ru.dragonestia.picker.api.repository.AccountRepository;
|
||||||
|
|
||||||
@ -20,6 +22,11 @@ public class AccountRepositoryImpl implements AccountRepository {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Optional<ResponseAccount> findAccountByUsername(@NotNull String username) {
|
public Optional<ResponseAccount> findAccountByUsername(@NotNull String username) {
|
||||||
throw new UnsupportedOperationException("Not implemented");
|
try {
|
||||||
|
var response = rest.query("/accounts/" + username, HttpMethod.GET, ResponseAccount.class);
|
||||||
|
return Optional.of(response);
|
||||||
|
} catch (AccountDoesNotExistsException ex) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,4 +8,4 @@ scrape_configs:
|
|||||||
scrape_interval: 5s
|
scrape_interval: 5s
|
||||||
metrics_path: '/actuator/prometheus'
|
metrics_path: '/actuator/prometheus'
|
||||||
static_configs:
|
static_configs:
|
||||||
- targets: [ 'host.docker.internal:8080' ]
|
- targets: [ 'server:8080' ]
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import org.springframework.context.annotation.Configuration;
|
|||||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
|
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||||
import ru.dragonestia.picker.cp.page.LoginPage;
|
import ru.dragonestia.picker.cp.page.LoginPage;
|
||||||
import ru.dragonestia.picker.cp.service.AccountService;
|
import ru.dragonestia.picker.cp.service.AccountService;
|
||||||
|
|
||||||
@ -39,16 +40,17 @@ public class SecurityConfig extends VaadinWebSecurity {
|
|||||||
@Override
|
@Override
|
||||||
protected void configure(HttpSecurity http) throws Exception {
|
protected void configure(HttpSecurity http) throws Exception {
|
||||||
http.authorizeHttpRequests(auth -> {
|
http.authorizeHttpRequests(auth -> {
|
||||||
|
auth.requestMatchers(AntPathRequestMatcher.antMatcher("/static/**")).permitAll();
|
||||||
});
|
|
||||||
|
|
||||||
http.formLogin(login -> {
|
|
||||||
login.successForwardUrl("/nodes");
|
|
||||||
});
|
});
|
||||||
|
|
||||||
http.userDetailsService(accountService);
|
http.userDetailsService(accountService);
|
||||||
|
|
||||||
super.configure(http);
|
super.configure(http);
|
||||||
|
|
||||||
|
http.formLogin(login -> {
|
||||||
|
login.successForwardUrl("/nodes");
|
||||||
|
login.defaultSuccessUrl("/nodes");
|
||||||
|
});
|
||||||
setLoginView(http, LoginPage.class);
|
setLoginView(http, LoginPage.class);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import com.vaadin.flow.server.ErrorEvent;
|
|||||||
import com.vaadin.flow.server.ErrorHandler;
|
import com.vaadin.flow.server.ErrorHandler;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import ru.dragonestia.picker.api.exception.ApiException;
|
import ru.dragonestia.picker.api.exception.ApiException;
|
||||||
|
import ru.dragonestia.picker.api.impl.exception.NotEnoughPermissions;
|
||||||
import ru.dragonestia.picker.cp.component.Notifications;
|
import ru.dragonestia.picker.cp.component.Notifications;
|
||||||
|
|
||||||
import java.security.InvalidParameterException;
|
import java.security.InvalidParameterException;
|
||||||
@ -34,6 +35,13 @@ public class ApplicationErrorHandler implements ErrorHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errorEvent.getThrowable() instanceof NotEnoughPermissions) {
|
||||||
|
execute(() -> {
|
||||||
|
Notifications.error("Not enough permissions to this action");
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
execute(() -> {
|
execute(() -> {
|
||||||
Notifications.error("Internal server error");
|
Notifications.error("Internal server error");
|
||||||
});
|
});
|
||||||
|
|||||||
@ -19,7 +19,7 @@ public class Account implements IAccount, UserDetails {
|
|||||||
public Account(ResponseAccount original, RoomPickerClient client) {
|
public Account(ResponseAccount original, RoomPickerClient client) {
|
||||||
this.original = original;
|
this.original = original;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
permissions = original.getPermissions().stream().map(Permission::new).collect(Collectors.toSet());
|
permissions = original.getPermissions().stream().map(permission -> new Permission("ROLE_" + permission)).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull RoomPickerClient getClient() {
|
public @NotNull RoomPickerClient getClient() {
|
||||||
|
|||||||
@ -1,29 +0,0 @@
|
|||||||
package ru.dragonestia.picker.cp.page;
|
|
||||||
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
|
||||||
import com.vaadin.flow.component.html.H1;
|
|
||||||
import com.vaadin.flow.component.html.Paragraph;
|
|
||||||
import com.vaadin.flow.component.notification.Notification;
|
|
||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|
||||||
import com.vaadin.flow.component.textfield.TextField;
|
|
||||||
import com.vaadin.flow.router.*;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
|
|
||||||
@Route(value = "/", layout = MainLayout.class)
|
|
||||||
public class HomePage extends VerticalLayout {
|
|
||||||
|
|
||||||
public HomePage() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
var field = new TextField("Some field");
|
|
||||||
field.setRequired(true);
|
|
||||||
add(field);
|
|
||||||
|
|
||||||
var button = new Button("Click me", e -> {
|
|
||||||
Notification.show(field.isInvalid() + "");
|
|
||||||
});
|
|
||||||
|
|
||||||
add(button);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -7,9 +7,11 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|||||||
import com.vaadin.flow.router.BeforeEnterEvent;
|
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import com.vaadin.flow.server.auth.AnonymousAllowed;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
|
||||||
@Log4j2
|
@Log4j2
|
||||||
|
@AnonymousAllowed
|
||||||
@Route("/login")
|
@Route("/login")
|
||||||
public class LoginPage extends VerticalLayout implements BeforeEnterObserver {
|
public class LoginPage extends VerticalLayout implements BeforeEnterObserver {
|
||||||
|
|
||||||
|
|||||||
@ -16,13 +16,11 @@ import ru.dragonestia.picker.cp.annotation.ServerURL;
|
|||||||
|
|
||||||
public class MainLayout extends AppLayout {
|
public class MainLayout extends AppLayout {
|
||||||
|
|
||||||
private final RoomPickerClient client;
|
|
||||||
private final RoomPickerInfoResponse serverInfo;
|
private final RoomPickerInfoResponse serverInfo;
|
||||||
private final String serverUrl;
|
private final String serverUrl;
|
||||||
|
|
||||||
public MainLayout(RoomPickerClient client, @ServerURL String serverUrl) {
|
public MainLayout(RoomPickerClient adminClient, @ServerURL String serverUrl) {
|
||||||
this.client = client;
|
this.serverInfo = adminClient.getServerInfo();
|
||||||
this.serverInfo = client.getServerInfo();
|
|
||||||
this.serverUrl = serverUrl;
|
this.serverUrl = serverUrl;
|
||||||
|
|
||||||
var toggle = new DrawerToggle();
|
var toggle = new DrawerToggle();
|
||||||
@ -47,7 +45,6 @@ public class MainLayout extends AppLayout {
|
|||||||
nav.addItem(new SideNavItem("Search users", UserSearchPage.class, VaadinIcon.SEARCH.create()));
|
nav.addItem(new SideNavItem("Search users", UserSearchPage.class, VaadinIcon.SEARCH.create()));
|
||||||
nav.addItem(new SideNavItem("Documentation", "https://github.com/ScarletRedMan/RoomPicker", VaadinIcon.BOOK.create()));
|
nav.addItem(new SideNavItem("Documentation", "https://github.com/ScarletRedMan/RoomPicker", VaadinIcon.BOOK.create()));
|
||||||
nav.addItem(new SideNavItem("Swagger UI", serverUrl + "/api-docs-ui", VaadinIcon.CURLY_BRACKETS.create()));
|
nav.addItem(new SideNavItem("Swagger UI", serverUrl + "/api-docs-ui", VaadinIcon.CURLY_BRACKETS.create()));
|
||||||
nav.addItem(new SideNavItem("Sign-out", HomePage.class, VaadinIcon.SIGN_OUT.create()));
|
|
||||||
return nav;
|
return nav;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import com.vaadin.flow.router.BeforeEnterEvent;
|
|||||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
@ -19,6 +20,7 @@ import ru.dragonestia.picker.cp.util.RouteParamsExtractor;
|
|||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@PermitAll
|
||||||
@PageTitle("Rooms")
|
@PageTitle("Rooms")
|
||||||
@Route(value = "/nodes/:nodeId", layout = MainLayout.class)
|
@Route(value = "/nodes/:nodeId", layout = MainLayout.class)
|
||||||
public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
public class NodeDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
||||||
|
|||||||
@ -4,8 +4,8 @@ import com.vaadin.flow.component.html.Hr;
|
|||||||
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
import lombok.Getter;
|
import com.vaadin.flow.router.RouteAlias;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import ru.dragonestia.picker.api.exception.ApiException;
|
import ru.dragonestia.picker.api.exception.ApiException;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
@ -14,14 +14,13 @@ import ru.dragonestia.picker.cp.component.NavPath;
|
|||||||
import ru.dragonestia.picker.cp.component.NodeList;
|
import ru.dragonestia.picker.cp.component.NodeList;
|
||||||
import ru.dragonestia.picker.cp.component.RegisterNode;
|
import ru.dragonestia.picker.cp.component.RegisterNode;
|
||||||
|
|
||||||
@Log4j2
|
@PermitAll
|
||||||
@Getter
|
|
||||||
@PageTitle("Nodes")
|
@PageTitle("Nodes")
|
||||||
|
@RouteAlias(value = "/", layout = MainLayout.class)
|
||||||
@Route(value = "/nodes", layout = MainLayout.class)
|
@Route(value = "/nodes", layout = MainLayout.class)
|
||||||
public class NodesPage extends VerticalLayout {
|
public class NodesPage extends VerticalLayout {
|
||||||
|
|
||||||
private final NodeRepository nodeRepository;
|
private final NodeRepository nodeRepository;
|
||||||
private final RegisterNode registerNode;
|
|
||||||
private final NodeList nodeList;
|
private final NodeList nodeList;
|
||||||
|
|
||||||
public NodesPage(@Autowired RoomPickerClient client) {
|
public NodesPage(@Autowired RoomPickerClient client) {
|
||||||
@ -29,7 +28,7 @@ public class NodesPage extends VerticalLayout {
|
|||||||
this.nodeRepository = client.getNodeRepository();
|
this.nodeRepository = client.getNodeRepository();
|
||||||
|
|
||||||
add(NavPath.rootNodes());
|
add(NavPath.rootNodes());
|
||||||
add(registerNode = createRegisterNodeElement());
|
add(createRegisterNodeElement());
|
||||||
add(new Hr());
|
add(new Hr());
|
||||||
add(nodeList = createNodeListElement());
|
add(nodeList = createNodeListElement());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.vaadin.flow.router.BeforeEnterEvent;
|
|||||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
import ru.dragonestia.picker.api.model.node.INode;
|
import ru.dragonestia.picker.api.model.node.INode;
|
||||||
@ -31,6 +32,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@PermitAll
|
||||||
@PageTitle("Room details")
|
@PageTitle("Room details")
|
||||||
@Route(value = "/nodes/:nodeId/rooms/:roomId", layout = MainLayout.class)
|
@Route(value = "/nodes/:nodeId/rooms/:roomId", layout = MainLayout.class)
|
||||||
public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserver {
|
||||||
@ -40,7 +42,6 @@ public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserv
|
|||||||
|
|
||||||
private INode node;
|
private INode node;
|
||||||
private ResponseRoom room;
|
private ResponseRoom room;
|
||||||
private AddUsers addUsers;
|
|
||||||
private UserList userList;
|
private UserList userList;
|
||||||
private Button lockRoomButton;
|
private Button lockRoomButton;
|
||||||
private VerticalLayout roomInfo;
|
private VerticalLayout roomInfo;
|
||||||
@ -58,7 +59,7 @@ public class RoomDetailsPage extends VerticalLayout implements BeforeEnterObserv
|
|||||||
add(new H2("Room details"));
|
add(new H2("Room details"));
|
||||||
printRoomDetails();
|
printRoomDetails();
|
||||||
add(new Hr());
|
add(new Hr());
|
||||||
add(addUsers = new AddUsers(room, (users, ignoreLimitation) -> appendUsers(room, users, ignoreLimitation)));
|
add(new AddUsers(room, (users, ignoreLimitation) -> appendUsers(room, users, ignoreLimitation)));
|
||||||
add(new Hr());
|
add(new Hr());
|
||||||
add(new H2("Users"));
|
add(new H2("Users"));
|
||||||
add(userList = new UserList(room, client.getUserRepository()));
|
add(userList = new UserList(room, client.getUserRepository()));
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
package ru.dragonestia.picker.cp.page;
|
package ru.dragonestia.picker.cp.page;
|
||||||
|
|
||||||
import com.vaadin.flow.component.Html;
|
|
||||||
import com.vaadin.flow.component.button.Button;
|
import com.vaadin.flow.component.button.Button;
|
||||||
import com.vaadin.flow.component.button.ButtonVariant;
|
import com.vaadin.flow.component.button.ButtonVariant;
|
||||||
import com.vaadin.flow.component.grid.ColumnTextAlign;
|
import com.vaadin.flow.component.grid.ColumnTextAlign;
|
||||||
@ -12,6 +11,7 @@ import com.vaadin.flow.router.BeforeEnterEvent;
|
|||||||
import com.vaadin.flow.router.BeforeEnterObserver;
|
import com.vaadin.flow.router.BeforeEnterObserver;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
import ru.dragonestia.picker.api.model.room.RoomDetails;
|
import ru.dragonestia.picker.api.model.room.RoomDetails;
|
||||||
@ -21,11 +21,11 @@ import ru.dragonestia.picker.api.repository.query.user.FindRoomsLinkedWithUser;
|
|||||||
import ru.dragonestia.picker.cp.component.RefreshableTable;
|
import ru.dragonestia.picker.cp.component.RefreshableTable;
|
||||||
import ru.dragonestia.picker.cp.util.RouteParamsExtractor;
|
import ru.dragonestia.picker.cp.util.RouteParamsExtractor;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
|
@PermitAll
|
||||||
@PageTitle("User details")
|
@PageTitle("User details")
|
||||||
@Route(value = "/users/:userId", layout = MainLayout.class)
|
@Route(value = "/users/:userId", layout = MainLayout.class)
|
||||||
public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserver, RefreshableTable {
|
public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserver, RefreshableTable {
|
||||||
@ -34,7 +34,6 @@ public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserv
|
|||||||
private final RouteParamsExtractor paramsExtractor;
|
private final RouteParamsExtractor paramsExtractor;
|
||||||
private IUser user;
|
private IUser user;
|
||||||
private Grid<ShortResponseRoom> gridRooms;
|
private Grid<ShortResponseRoom> gridRooms;
|
||||||
private List<ShortResponseRoom> cachedRooms = new LinkedList<>();
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void beforeEnter(BeforeEnterEvent event) {
|
public void beforeEnter(BeforeEnterEvent event) {
|
||||||
@ -79,13 +78,9 @@ public class UserDetailsPage extends VerticalLayout implements BeforeEnterObserv
|
|||||||
return grid;
|
return grid;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Html createComponent(String defaultValue) {
|
|
||||||
return new Html("<span>" + defaultValue + "</span>");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refresh() {
|
public void refresh() {
|
||||||
cachedRooms = client.getUserRepository()
|
List<ShortResponseRoom> cachedRooms = client.getUserRepository()
|
||||||
.findRoomsLinkedWithUser(FindRoomsLinkedWithUser.withAllDetails(user.getIdentifierObject()));
|
.findRoomsLinkedWithUser(FindRoomsLinkedWithUser.withAllDetails(user.getIdentifierObject()));
|
||||||
gridRooms.setItems(cachedRooms);
|
gridRooms.setItems(cachedRooms);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,7 @@ import com.vaadin.flow.component.orderedlayout.VerticalLayout;
|
|||||||
import com.vaadin.flow.component.textfield.TextField;
|
import com.vaadin.flow.component.textfield.TextField;
|
||||||
import com.vaadin.flow.router.PageTitle;
|
import com.vaadin.flow.router.PageTitle;
|
||||||
import com.vaadin.flow.router.Route;
|
import com.vaadin.flow.router.Route;
|
||||||
|
import jakarta.annotation.security.PermitAll;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
import ru.dragonestia.picker.api.impl.RoomPickerClient;
|
||||||
import ru.dragonestia.picker.api.model.user.IUser;
|
import ru.dragonestia.picker.api.model.user.IUser;
|
||||||
@ -26,6 +27,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@PermitAll
|
||||||
@PageTitle("Search users")
|
@PageTitle("Search users")
|
||||||
@Route(value = "/users", layout = MainLayout.class)
|
@Route(value = "/users", layout = MainLayout.class)
|
||||||
public class UserSearchPage extends VerticalLayout implements RefreshableTable {
|
public class UserSearchPage extends VerticalLayout implements RefreshableTable {
|
||||||
|
|||||||
@ -0,0 +1,24 @@
|
|||||||
|
package ru.dragonestia.picker.cp.page.plug;
|
||||||
|
|
||||||
|
import com.vaadin.flow.component.html.H1;
|
||||||
|
import com.vaadin.flow.component.html.Paragraph;
|
||||||
|
import com.vaadin.flow.router.BeforeEnterEvent;
|
||||||
|
import com.vaadin.flow.router.ErrorParameter;
|
||||||
|
import com.vaadin.flow.router.HasErrorParameter;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import org.springframework.security.core.userdetails.User;
|
||||||
|
import ru.dragonestia.picker.api.impl.exception.NotEnoughPermissions;
|
||||||
|
|
||||||
|
public class NotEnoughPermissionsPlug extends ErrorPlug implements HasErrorParameter<NotEnoughPermissions> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int setErrorParameter(BeforeEnterEvent event, ErrorParameter<NotEnoughPermissions> parameter) {
|
||||||
|
return render(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int render(ErrorPlug plug) {
|
||||||
|
plug.add(new H1("Access denied"));
|
||||||
|
plug.add(new Paragraph("You do not have sufficient permissions to access this page"));
|
||||||
|
return HttpServletResponse.SC_FORBIDDEN;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,3 +17,12 @@ services:
|
|||||||
GF_SECURITY_ADMIN_PASSWORD: admin
|
GF_SECURITY_ADMIN_PASSWORD: admin
|
||||||
volumes:
|
volumes:
|
||||||
- "./appdata/grafana:/var/lib/grafana/"
|
- "./appdata/grafana:/var/lib/grafana/"
|
||||||
|
|
||||||
|
server:
|
||||||
|
image: openjdk:17-oracle
|
||||||
|
ports:
|
||||||
|
- "8080:8080"
|
||||||
|
working_dir: "/app"
|
||||||
|
volumes:
|
||||||
|
- "./appdata/server:/app"
|
||||||
|
entrypoint: "java -jar -Dspring.profiles.active='test' server.jar"
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
package ru.dragonestia.picker.controller;
|
package ru.dragonestia.picker.controller;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.security.core.context.SecurityContextHolder;
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.*;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
import ru.dragonestia.picker.api.model.account.ResponseAccount;
|
||||||
import ru.dragonestia.picker.model.Account;
|
import ru.dragonestia.picker.model.Account;
|
||||||
import ru.dragonestia.picker.service.AccountService;
|
import ru.dragonestia.picker.service.AccountService;
|
||||||
@ -21,4 +21,13 @@ public class AccountsController {
|
|||||||
var account = (Account) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
var account = (Account) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||||
return account.toResponseObject();
|
return account.toResponseObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/{accountId}")
|
||||||
|
ResponseEntity<ResponseAccount> findAccount(@PathVariable String accountId) {
|
||||||
|
try {
|
||||||
|
return ResponseEntity.ok(accountService.loadUserByUsername(accountId).toResponseObject());
|
||||||
|
} catch (UsernameNotFoundException ex) {
|
||||||
|
return ResponseEntity.notFound().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -61,6 +61,11 @@ public class ExceptionHandlerController {
|
|||||||
return create(400, ex);
|
return create(400, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(AccountDoesNotExistsException.class)
|
||||||
|
ResponseEntity<?> accountDoesNotExists(AccountDoesNotExistsException ex) {
|
||||||
|
return create(404, ex);
|
||||||
|
}
|
||||||
|
|
||||||
private ResponseEntity<ErrorResponse> create(int code, ApiException ex) {
|
private ResponseEntity<ErrorResponse> create(int code, ApiException ex) {
|
||||||
var details = new HashMap<String, String>();
|
var details = new HashMap<String, String>();
|
||||||
ex.appendDetailsToErrorResponse(details);
|
ex.appendDetailsToErrorResponse(details);
|
||||||
|
|||||||
@ -9,6 +9,6 @@ public enum Permission implements GrantedAuthority {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAuthority() {
|
public String getAuthority() {
|
||||||
return name();
|
return "ROLE_" + name();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package ru.dragonestia.picker.service;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.springframework.security.access.prepost.PreAuthorize;
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||||
import ru.dragonestia.picker.model.Account;
|
import ru.dragonestia.picker.model.Account;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -17,4 +18,7 @@ public interface AccountService extends UserDetailsService {
|
|||||||
|
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
void removeAccount(@NotNull Account account);
|
void removeAccount(@NotNull Account account);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
Account loadUserByUsername(String username) throws UsernameNotFoundException;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,10 +10,11 @@ import ru.dragonestia.picker.model.Account;
|
|||||||
import ru.dragonestia.picker.model.Permission;
|
import ru.dragonestia.picker.model.Permission;
|
||||||
import ru.dragonestia.picker.service.AccountService;
|
import ru.dragonestia.picker.service.AccountService;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
@ -26,7 +27,7 @@ public class AccountServiceImpl implements AccountService {
|
|||||||
@PostConstruct
|
@PostConstruct
|
||||||
void init() {
|
void init() {
|
||||||
var account = createNewAccount("admin", "qwerty123");
|
var account = createNewAccount("admin", "qwerty123");
|
||||||
account.setAuthorities(Set.of(Permission.ADMIN));
|
account.setAuthorities(Arrays.stream(Permission.values()).collect(Collectors.toSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public @NotNull Account createNewAccount(@NotNull String username, @NotNull String password) {
|
public @NotNull Account createNewAccount(@NotNull String username, @NotNull String password) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user