Skip to content

Commit

Permalink
Web ui account create improvements, now only the first user will be a…
Browse files Browse the repository at this point in the history
…ble to login initially
  • Loading branch information
GregJohnStewart committed Sep 1, 2022
1 parent a4492db commit 871fd6c
Show file tree
Hide file tree
Showing 9 changed files with 151 additions and 93 deletions.
2 changes: 1 addition & 1 deletion software/libs/open-qm-core/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ plugins {
//group 'com.ebp.openQuarterMaster.lib'
group 'tech.epic-breakfast-productions.openQuarterMaster.lib'
archivesBaseName = "openQuarterMaster-lib-core"
version '1.0.1-DEV'
version '1.0.3-DEV'

repositories {
mavenLocal()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ public class User extends ImagedMainObject {
private String email;
private String title;

@lombok.Builder.Default
private boolean disabled = true;

/*
* Not used if service.authMode set to EXTERNAL
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class UserGetResponse extends AttKeywordMainObject {
private String lastName;
private String email;
private String title;
private boolean disabled;
private Map<String, String> externIds = new HashMap<>();
private Set<String> roles = new HashSet<>();
private Map<String, String> attributes = new HashMap<>();
Expand All @@ -42,6 +43,7 @@ public static Builder builder(User user) {
.lastName(user.getLastName())
.email(user.getEmail())
.title(user.getTitle())
.disabled(user.isDisabled())
.externIds(user.getExternIds())
.roles(user.getRoles())
.attributes(user.getAttributes());
Expand Down
4 changes: 2 additions & 2 deletions software/open-qm-base-station/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ plugins {
}

group 'com.ebp.openQuarterMaster'
version '1.0.5-DEV'
version '1.0.6-DEV'

repositories {
mavenCentral()
Expand Down Expand Up @@ -47,7 +47,7 @@ dependencies {
// implementation 'org.webjars:js-cookie:2.2.1' //out of date
// implementation 'org.webjars:spin-js:2.1.0'

implementation 'tech.epic-breakfast-productions.openQuarterMaster.lib:open-qm-lib-core:1.0.1-DEV'
implementation 'tech.epic-breakfast-productions.openQuarterMaster.lib:open-qm-lib-core:1.0.3-DEV'
implementation 'tech.epic-breakfast-productions.openQuarterMaster.lib:open-qm-lib-moduleDriver:1.0.1-DEV'

// https://mvnrepository.com/artifact/tech.units/indriya
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,13 +137,16 @@ public Response authenticateUser(
if (user == null) {
return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorMessage("User not found.")).build();
}
if(user.isDisabled()){
return Response.status(Response.Status.UNAUTHORIZED).entity(new ErrorMessage("Account Disabled. Contact an admin for details.")).build();
}

//TODO:: check for # of login attempts?

if (!this.passwordService.passwordMatchesHash(user, loginRequest)) {
return Response.status(Response.Status.BAD_REQUEST).entity(new ErrorMessage("Invalid Password.")).build();
}

//TODO:: additional checks on locked status, etc

log.info("User {} authenticated, generating token and returning.", user.getId());

this.userService.addHistoryFor(user, UserLoginEvent.builder().userId(user.getId()).build());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ public ObjectId create(
@Valid UserCreateRequest ucr
) {
assertSelfAuthMode(this.authMode);

log.info("Creating new user.");
User.Builder builder = User.builder(ucr);

{
Expand All @@ -113,9 +113,14 @@ public ObjectId create(
add(UserRoles.INVENTORY_VIEW);
}};
if (this.getUserService().collectionEmpty()) {
log.info("New user is the first user to enter system. Making them an admin.");
builder.disabled(false);
roles.add(UserRoles.USER_ADMIN);
roles.add(UserRoles.INVENTORY_EDIT);
roles.add(UserRoles.INVENTORY_ADMIN);
} else {
log.info("New user is not the first. Disabling.");
builder.disabled(true);
}
builder.roles(roles);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.eclipse.microprofile.openapi.annotations.tags.Tags;
import org.eclipse.microprofile.opentracing.Traced;
import tech.ebp.oqm.baseStation.service.mongo.UserService;
import tech.ebp.oqm.baseStation.utils.AuthMode;

import javax.annotation.security.PermitAll;
Expand All @@ -25,10 +26,12 @@
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.UUID;

import static tech.ebp.oqm.baseStation.utils.AuthMode.EXTERNAL;
import static tech.ebp.oqm.baseStation.utils.AuthMode.SELF;

@Traced
@Slf4j
Expand All @@ -51,6 +54,9 @@ public class Index extends UiProvider {
@Inject
Tracer tracer;

@Inject
UserService userService;

@ConfigProperty(name = "service.authMode")
AuthMode authMode;

Expand All @@ -70,6 +76,11 @@ public Response index(
) throws MalformedURLException, URISyntaxException {
logRequestContext(jwt, securityContext);

if(this.authMode == SELF && this.userService.collectionEmpty()){
return Response.seeOther(new URI("/accountCreate")).build();
}


String redirectUri = externInteractionCallbackUrl;

if (returnPath != null && !returnPath.isBlank()) {
Expand Down Expand Up @@ -111,6 +122,11 @@ public TemplateInstance accountCreate(
@Context SecurityContext securityContext
) {
logRequestContext(jwt, securityContext);
return this.setupPageTemplate(accountCreate, tracer);

if(this.authMode == EXTERNAL){
//redirect to login, message about
}

return this.setupPageTemplate(accountCreate, tracer).data("firstUser", this.userService.collectionEmpty());
}
}
Original file line number Diff line number Diff line change
@@ -1,95 +1,123 @@
{#include webui/mainWebPageTemplate title='Account Create' showNavbar=false showTitle=true}
{#pageContent}
{#pageContent}
<div class="row">
<div class="col">
<a href="/" title="Back to Login">Back to Login</a>
</div>
</div>

{#if firstUser}
<div class="alert alert-warning" role="alert">
<h4 class="alert-heading">First User!</h4>
<hr>
<p>
You are the first user to create an account. You will be made an admin of both users and data. You
will need to enable users after yourself to interact with data.
</p>
<p class="mb-0">
See the "User Administration" page for more information.
</p>
</div>
{#else}
<div class="alert alert-info" role="alert">
<h4 class="alert-heading">New User!</h4>
<hr>
<p>
You will need to be approved by an admin before being able to login and use the system.
</p>
<!-- TODO:: list admins to contact -->
</div>
{/if}


<hr/>
<div class="row">
<form id="userAccountCreateForm">
<div id="createMessageDiv"></div>
<div class="form-floating mb-1">
<input type="email" class="form-control" id="emailInput" placeholder="[email protected]" required>
<label for="emailInput">Email address</label>
</div>
<div class="form-floating mb-1">
<input type="text" class="form-control" id="usernameInput" placeholder="Username" required>
<label for="usernameInput">Username</label>
</div>
<div class="form-floating mb-1">
<input type="text" class="form-control" id="firstnameInput" placeholder="First Name" required>
<label for="firstnameInput">First name</label>
</div>
<div class="form-floating mb-1">
<input type="text" class="form-control" id="lastnameInput" placeholder="Last Name" required>
<label for="lastnameInput">Last name</label>
</div>
<div class="form-floating mb-1">
<input type="text" class="form-control" id="titleInput" placeholder="Title">
<label for="titleInput">Title</label>
</div>
<div class="form-floating mb-1">
<input type="password" class="form-control" id="passwordInput" placeholder="Password" required>
<label for="passwordInput">Password</label>
</div>
<div class="form-floating mb-1">
<input type="password" class="form-control" id="passwordConfirmInput" placeholder="Password Confirm"
required>
<label for="passwordConfirmInput">Password Confirm</label>
</div>
<button type="submit" class="btn btn-success btn-lg">Create User</button>
</form>
</div>
{/pageContent}
{#pageScript}
<script>
assertNotLoggedIn();

<a href="/" title="Back to Login">Back to Login</a>
<hr/>
<div class="row">
<form id="userAccountCreateForm">
<div id="createMessageDiv"></div>
<div class="form-floating">
<input type="email" class="form-control" id="emailInput" placeholder="[email protected]" required>
<label for="emailInput">Email address</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="usernameInput" placeholder="Username" required>
<label for="usernameInput">Username</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="firstnameInput" placeholder="First Name" required>
<label for="firstnameInput">First name</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="lastnameInput" placeholder="Last Name" required>
<label for="lastnameInput">Last name</label>
</div>
<div class="form-floating">
<input type="text" class="form-control" id="titleInput" placeholder="Title">
<label for="titleInput">Title</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="passwordInput" placeholder="Password" required>
<label for="passwordInput">Password</label>
</div>
<div class="form-floating">
<input type="password" class="form-control" id="passwordConfirmInput" placeholder="Password Confirm"
required>
<label for="passwordConfirmInput">Password Confirm</label>
</div>
<button type="submit" class="btn btn-success btn-lg">Create User</button>
</form>
</div>
{/pageContent}
{#pageScript}
<script>
assertNotLoggedIn();
$("#userAccountCreateForm").submit(function (event) {
event.preventDefault();
console.log("Submitting login form.");

$("#userAccountCreateForm").submit(function(event){
event.preventDefault();
console.log("Submitting login form.");
if ($("#passwordInput").val() != $("#passwordConfirmInput").val()) {
addMessageToDiv($("#createMessageDiv"), "warning", "Password must match confirm!", null, null);
return;
}

if($("#passwordInput").val() != $("#passwordConfirmInput").val()){
addMessageToDiv($("#createMessageDiv"), "warning", "Password must match confirm!", null, null);
return;
}
var createRequestData = {
firstName: $("#firstnameInput").val(),
lastName: $("#lastnameInput").val(),
username: $("#usernameInput").val(),
email: $("#emailInput").val(),
title: $("#titleInput").val(),
password: $("#passwordInput").val()
};

var createRequestData = {
firstName: $("#firstnameInput").val(),
lastName: $("#lastnameInput").val(),
username: $("#usernameInput").val(),
email: $("#emailInput").val(),
title: $("#titleInput").val(),
password: $("#passwordInput").val()
};
doRestCall({
url: "/api/user",
method: "POST",
data: createRequestData,
async: false,
done: function (data) {
console.log("Response from user create request: " + JSON.stringify(data));
window.location.replace("/?message=User Registration Successful!&messageType=success");
},
fail: function (data) {
console.log("FAILED to create user: " + JSON.stringify(data));
var errMessages = "";
if (data.responseJSON.hasOwnProperty('error')) {
errMessages = data.responseJSON.error;
} else if (data.responseJSON.hasOwnProperty('parameterViolations')) {
data.responseJSON.parameterViolations.forEach(function (violation) {
errMessages += violation.message + "<br/>";
});
} else {
errMessages = "Unknown or unspecified error";
}

doRestCall({
url: "/api/user",
method: "POST",
data: createRequestData,
async: false,
done: function(data) {
console.log("Response from user create request: " + JSON.stringify(data));
window.location.replace("/?message=User Registration Successful!&messageType=success");
},
fail: function(data){
console.log("FAILED to create user: " + JSON.stringify(data));
var errMessages = "";
if(data.responseJSON.hasOwnProperty('error')){
errMessages = data.responseJSON.error;
} else if(data.responseJSON.hasOwnProperty('parameterViolations')){
data.responseJSON.parameterViolations.forEach(function(violation){
errMessages += violation.message + "<br/>";
});
} else {
errMessages = "Unknown or unspecified error";
}
addMessageToDiv($("#createMessageDiv"), "warning", errMessages, "Failed to register", null);

addMessageToDiv($("#createMessageDiv"), "warning", errMessages, "Failed to register", null);


}//fail
});
console.log("Done.");
});
</script>
{/pageScript}
}//fail
});
console.log("Done.");
});
</script>
{/pageScript}
{/include}
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ public User getTestUser(boolean admin, boolean persisted) {
builder.lastName(FAKER.name().lastName());
builder.email(FAKER.internet().emailAddress());
builder.title(FAKER.company().profession());
builder.disabled(false);
builder.roles(new HashSet<>() {{
add(UserRoles.USER);
add(UserRoles.INVENTORY_EDIT);
Expand Down

0 comments on commit 871fd6c

Please sign in to comment.