Gerüst mit Form-Auth

This commit is contained in:
mbremer
2021-07-02 21:39:28 +02:00
commit 825363e491
30 changed files with 1528 additions and 0 deletions

View File

@@ -0,0 +1,26 @@
package de.mbremer.kalender;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
@Path("/kalender")
@RolesAllowed({"USER", "ADMIN"})
public class KalenderResource {
@Inject
Template kalender;
@Path("")
@GET
@Produces(MediaType.TEXT_HTML)
public TemplateInstance kalender() {
return kalender.instance();
}
}

View File

@@ -0,0 +1,20 @@
package de.mbremer.kalender;
import de.mbremer.secutity.User;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import java.time.LocalDate;
@Getter
@Setter
public class KalenderTag extends PanacheEntity {
private LocalDate date;
@OneToMany
private User inOffice;
}

View File

@@ -0,0 +1,5 @@
package de.mbremer.secutity;
public enum Role {
ADMIN, USER
}

View File

@@ -0,0 +1,57 @@
package de.mbremer.secutity;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.hibernate.orm.panache.PanacheEntity;
import io.quarkus.security.jpa.Password;
import io.quarkus.security.jpa.Roles;
import io.quarkus.security.jpa.UserDefinition;
import io.quarkus.security.jpa.Username;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import javax.persistence.*;
import javax.validation.constraints.NotBlank;
@UserDefinition
@NoArgsConstructor
@Entity
@Table(name = "users")
public class User extends PanacheEntity {
@Username
@NotBlank
@Getter
@Column(nullable = false)
private String username;
@Password
@NotBlank
@Getter
@Column(nullable = false)
private String password;
/**
* ADMIN or USER.
*/
@Roles
@Getter
@Setter
@Column(nullable = false)
private String role = "USER";
public User setPassword(String password) {
this.password = BcryptUtil.bcryptHash(password);
return this;
}
public User setUsername(String username) {
this.username = username == null ? null : username.trim();
return this;
}
public User setRole(String role) {
this.role = role == null ? role : role.toUpperCase();
return this;
}
}

View File

@@ -0,0 +1,18 @@
package de.mbremer.secutity;
import javax.ws.rs.FormParam;
public class UserForm {
public @FormParam("username") String username;
public @FormParam("password") String password;
public @FormParam("passwordVerify") String passwordVerify;
public @FormParam("role") String role;
public User getUser() {
return new User().setUsername(username).setPassword(password).setRole(role);
}
public boolean verifyPassword() {
return password != null && password.length() > 4 && password.equals(passwordVerify);
}
}

View File

@@ -0,0 +1,104 @@
package de.mbremer.secutity;
import io.quarkus.qute.Location;
import io.quarkus.qute.Template;
import io.quarkus.qute.TemplateInstance;
import io.quarkus.security.identity.SecurityIdentity;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.providers.multipart.MultipartForm;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.inject.Inject;
import javax.transaction.Transactional;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import java.net.URI;
import static de.mbremer.secutity.Role.ADMIN;
@Path("/user")
@RolesAllowed("ADMIN")
public class UserResource {
@Inject
Logger log;
@Inject
SecurityIdentity identity;
@Inject
Template userinit;
@Inject
@Location("user.html")
Template userTemplate;
@GET
@Produces(MediaType.TEXT_HTML)
@RolesAllowed({"USER", "ADMIN"})
public TemplateInstance getUser() {
return userTemplate
.data("user_count", User.count())
.data("current_username", identity.getPrincipal().getName())
.data("is_admin", identity.hasRole("ADMIN"));
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Transactional
@Path("init")
@PermitAll
public Response initialAdd(@MultipartForm UserForm userForm) {
if(User.count("role", ADMIN.name()) > 0) {
throw new BadRequestException("Only allowed on initial set up");
}
if(!ADMIN.name().equals(userForm.role)) {
throw new BadRequestException("Only role ADMIN");
}
User user = userForm.getUser();
user.persist();
return Response.status(Response.Status.SEE_OTHER)
.location(URI.create("/login.html"))
.build();
}
@GET
@Produces(MediaType.TEXT_HTML)
@Path("init")
@PermitAll
public TemplateInstance initial() {
if(User.count("role", ADMIN.name()) > 0) {
throw new BadRequestException("Only allowed on initial set up");
}
return userinit.instance();
}
@GET
@Produces(MediaType.TEXT_HTML)
@Path("logout")
@RolesAllowed({"USER", "ADMIN"})
public Response logout() {
return Response
.temporaryRedirect(URI.create("/"))
.cookie(new NewCookie("quarkus-credential", null, "/", null, null, 0, false,true))
.build();
}
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.TEXT_HTML)
@Transactional
@Path("/new")
public TemplateInstance add(@MultipartForm UserForm userForm) {
if (!userForm.verifyPassword()) {
return getUser().data("error", "Das Passwort ist zu kurz oder stimmt nicht mit der Wiederholung überein.");
}
User user = userForm.getUser();
user.persist();
return getUser().data("info", "User angelegt.");
}
}