Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.yaml.snakeyaml.Yaml;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.ConstraintViolation;
import javax.validation.Validator;
Expand Down
23 changes: 18 additions & 5 deletions backend/src/main/java/com/park/utmstack/service/UserService.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ private boolean removeNonActivatedUser(User existingUser) {
}

public User createUser(UserDTO userDTO) {
return createUser(userDTO, null);
}

/**
* Create a user. When a local password is provided the user is activated
* immediately, no email/activation step is needed.
*/
public User createUser(UserDTO userDTO, String localPassword) {
String ctx = CLASS_NAME + ".createUser";
try {
User user = new User();
Expand All @@ -142,11 +150,16 @@ public User createUser(UserDTO userDTO) {
} else {
user.setLangKey(userDTO.getLangKey());
}
String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
user.setPassword(encryptedPassword);
user.setResetKey(RandomUtil.generateResetKey());
user.setResetDate(Instant.now());
user.setActivated(false);
if (StringUtils.hasText(localPassword)) {
user.setPassword(passwordEncoder.encode(localPassword));
user.setActivated(true);
} else {
String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
user.setPassword(encryptedPassword);
user.setResetKey(RandomUtil.generateResetKey());
user.setResetDate(Instant.now());
user.setActivated(false);
}
if (userDTO.getAuthorities() != null) {
Set<Authority> authorities = userDTO.getAuthorities().stream().map(authorityRepository::findById).filter(
Optional::isPresent).map(Optional::get).collect(Collectors.toSet());
Expand Down
33 changes: 33 additions & 0 deletions backend/src/main/java/com/park/utmstack/web/rest/UserResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.park.utmstack.web.rest.errors.LoginAlreadyUsedException;
import com.park.utmstack.web.rest.util.HeaderUtil;
import com.park.utmstack.web.rest.util.PaginationUtil;
import com.park.utmstack.web.rest.vm.ManagedUserVM;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Page;
Expand All @@ -25,6 +26,7 @@
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;
import tech.jhipster.web.util.ResponseUtil;

Expand Down Expand Up @@ -130,6 +132,37 @@ public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO userDTO) {
}
}

@PostMapping("/users/local")
@PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
@AuditEvent(
attemptType = ApplicationEventType.USER_CREATION_ATTEMPT,
attemptMessage = "Attempting to create user {login} locally",
successType = ApplicationEventType.USER_CREATION_SUCCESS,
successMessage = "User {login} created locally (no email activation)"
)
public ResponseEntity<User> createUserLocal(@Valid @RequestBody ManagedUserVM userDTO) {
if (userDTO.getId() != null) {
throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists");
}
if (userRepository.findOneByLogin(userDTO.getLogin()
.toLowerCase())
.isPresent()) {
throw new LoginAlreadyUsedException();
}
if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail())
.isPresent()) {
throw new EmailAlreadyUsedException();
}
if (!StringUtils.hasText(userDTO.getPassword()) || userDTO.getPassword().length() <= 4) {
throw new BadRequestAlertException("Password is invalid: it must be longer than 4 characters", "userManagement", "invalidpassword");
}
User newUser = userService.createUser(userDTO, userDTO.getPassword());
return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin()))
.headers(HeaderUtil.createAlert("A user is created with identifier " + newUser.getLogin(),
newUser.getLogin()))
.body(newUser);
}

/**
* PUT /users : Updates an existing User.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,106 +1,212 @@
<app-utm-modal-header [name]="user.id?'Edit user':'Create user'"></app-utm-modal-header>
<app-utm-modal-header
[name]="user.id ? 'Edit user' : 'Create user'"
></app-utm-modal-header>
<div class="container-fluid p-3">
<form #editForm="ngForm" (ngSubmit)="save()" class="form-user" name="editForm" novalidate role="form">
<form
#editForm="ngForm"
(ngSubmit)="save()"
class="form-user"
name="editForm"
novalidate
role="form"
>
<div class="form-group">
<label class="form-control-label">Login</label>
<input #loginInput="ngModel" [(ngModel)]="user.login" class="form-control" maxlength="50"
minlength="1" name="login" pattern="^[_.@A-Za-z0-9-]*$" required
type="text">
<input
#loginInput="ngModel"
[(ngModel)]="user.login"
class="form-control"
maxlength="50"
minlength="1"
name="login"
pattern="^[_.@A-Za-z0-9-]*$"
required
type="text"
/>

<div *ngIf="loginInput.dirty && loginInput.invalid">
<small *ngIf="loginInput.errors.required"
class="form-text text-danger">
<small *ngIf="loginInput.errors.required" class="form-text text-danger">
This field is required.
</small>

<small *ngIf="loginInput.errors.maxlength"
class="form-text text-danger">
<small
*ngIf="loginInput.errors.maxlength"
class="form-text text-danger"
>
This field cannot be longer than 50 characters.
</small>

<small *ngIf="loginInput.errors.pattern"
class="form-text text-danger">
<small *ngIf="loginInput.errors.pattern" class="form-text text-danger">
This field can only contain letters, digits and e-mail addresses.
</small>
</div>
</div>
<div class="form-group">
<label class="form-control-label">First Name</label>
<input #firstNameInput="ngModel" [(ngModel)]="user.firstName" class="form-control" maxlength="50"
name="firstName" type="text">
<input
#firstNameInput="ngModel"
[(ngModel)]="user.firstName"
class="form-control"
maxlength="50"
name="firstName"
type="text"
/>

<div *ngIf="firstNameInput.dirty && firstNameInput.invalid">
<small *ngIf="firstNameInput.errors.maxlength"
class="form-text text-danger">
<small
*ngIf="firstNameInput.errors.maxlength"
class="form-text text-danger"
>
This field cannot be longer than 50 characters.
</small>
</div>
</div>
<div class="form-group">
<label>Last Name</label>
<input #lastNameInput="ngModel" [(ngModel)]="user.lastName" class="form-control" maxlength="50"
name="lastName" type="text">
<input
#lastNameInput="ngModel"
[(ngModel)]="user.lastName"
class="form-control"
maxlength="50"
name="lastName"
type="text"
/>

<div *ngIf="lastNameInput.dirty && lastNameInput.invalid">
<small *ngIf="lastNameInput.errors.maxlength"
class="form-text text-danger">
<small
*ngIf="lastNameInput.errors.maxlength"
class="form-text text-danger"
>
This field cannot be longer than 50 characters.
</small>
</div>
</div>
<div class="form-group">
<label class="form-control-label">Email</label>
<input #emailInput="ngModel" [(ngModel)]="user.email" class="form-control" email
maxlength="254" minlength="5" name="email" required type="email">
<input
#emailInput="ngModel"
[(ngModel)]="user.email"
class="form-control"
email
maxlength="254"
minlength="5"
name="email"
required
type="email"
/>

<div *ngIf="emailInput.dirty && emailInput.invalid">
<small *ngIf="emailInput.errors.required"
class="form-text text-danger">
<small *ngIf="emailInput.errors.required" class="form-text text-danger">
This field is required.
</small>

<small *ngIf="emailInput.errors.maxlength"
class="form-text text-danger">
<small
*ngIf="emailInput.errors.maxlength"
class="form-text text-danger"
>
This field cannot be longer than 100 characters.
</small>

<small *ngIf="emailInput.errors.minlength"
class="form-text text-danger">
<small
*ngIf="emailInput.errors.minlength"
class="form-text text-danger"
>
This field is required to be at least 5 characters.
</small>

<small *ngIf="emailInput.errors.email"
class="form-text text-danger">
<small *ngIf="emailInput.errors.email" class="form-text text-danger">
Your email is invalid.
</small>
</div>
</div>
<div class="form-group ml-12" *ngIf="!user.id">
<label
for="localCreation"
class="form-control-label d-flex justify-content-between align-items-center"
>
<span>Local creation (no email activation)</span>
<input
id="localCreation"
class="form-check-input"
name="localCreation"
type="checkbox"
[(ngModel)]="localCreation"
/>
</label>
</div>
<div class="form-group" *ngIf="localCreation && !user.id">
<label class="form-control-label">Password</label>
<input
#passwordInput="ngModel"
[(ngModel)]="user.password"
class="form-control"
maxlength="100"
minlength="4"
name="password"
required
type="password"
/>

<div *ngIf="passwordInput.dirty && passwordInput.invalid">
<small
*ngIf="passwordInput.errors.required"
class="form-text text-danger"
>
This field is required.
</small>

<small
*ngIf="passwordInput.errors.minlength"
class="form-text text-danger"
>
This field is required to be at least 4 characters.
</small>

<small
*ngIf="passwordInput.errors.maxlength"
class="form-text text-danger"
>
This field cannot be longer than 100 characters.
</small>
</div>
</div>
<div class="form-group">
<label for="profile">Rol</label>
<select [(ngModel)]="user.authorities" required class="form-control" id="profile" multiple name="authority">
<option *ngFor="let authority of authorities" [value]="authority">{{authority}}</option>
<select
[(ngModel)]="user.authorities"
required
class="form-control"
id="profile"
multiple
name="authority"
>
<option *ngFor="let authority of authorities" [value]="authority">
{{ authority }}
</option>
</select>
<small *ngIf="user.authorities && user.authorities.length === 0"
class="form-text text-danger">
<small
*ngIf="user.authorities && user.authorities.length === 0"
class="form-text text-danger"
>
This field is required. You must select a role.
</small>
</div>

</form>
<div class="button-container d-flex justify-content-end mt-4">
<button (click)="activeModal.close()" class="btn utm-button utm-button-grey mr-3">
<i class="icon-cancel-circle2"></i>&nbsp;
Cancel
<button
(click)="activeModal.close()"
class="btn utm-button utm-button-grey mr-3"
>
<i class="icon-cancel-circle2"></i>&nbsp; Cancel
</button>
<button (click)="save()"
[disabled]="!editForm.valid"
class="btn utm-button utm-button-primary
d-flex justify-content-center
align-items-center">
<i [ngClass]="isSaving?'icon-spinner2 spinner':'icon-user-plus'">
</i>&nbsp;
{{user.id ? 'Edit user' : 'Create user'}}
<button
(click)="save()"
[disabled]="!editForm.valid"
class="btn utm-button utm-button-primary d-flex justify-content-center align-items-center"
>
<i [ngClass]="isSaving ? 'icon-spinner2 spinner' : 'icon-user-plus'"> </i
>&nbsp;
{{ user.id ? "Edit user" : "Create user" }}
</button>
</div>
</div>

Loading
Loading