Signup, Edit personal and Modify password forms in Spring MVC - spring

Spring MVC, Signup, Edit personal and Password forms
My Spring MVC application is a website where members can subscribe to indoor and outdoor activities, organized by a member. THe application therefore needs a well-known funcionality to sign up, login and edit/modify personal details.
I used Spring MVC in combination with Thymeleaf views. THis works fine but I am struggling with the different forms and try to avoid redundant fields.
The following use cases are required:
Sign up:
User chooses a username, password en password confirmation and personal details like birth date, gender, city, personal interests.
After submitting the form, form validation checks whether username is not in use and passwords fields are equal.
Edit personal data:
When logged in, the user can choose to edit his/her personal data. Username cannot be changed (and is therefore invisible or at least immutable in this form) and password fields are not shown.
Edit password;
To change the password, the logged in user enters his existing password for extra security, and the new password and the confirmation of the new password. After committing, the existing password is verified and changed afterwards if and only of the new password and confirmation are matching.
I think this is pretty common functionality. But my issue is that we have only one Member class that can act as the form-backing object (The Spring MVC documentation advises against the use of separate form backing objects).
Besides, the password is not stored as the plain entered text, but as the (SHA-256) hash.
For the signup use case, I choose the following approach:
THe Member entity object contains one mapped field for the hashed password (which is persisted in the database) and two transient fields for entering the password which are bound to the form and validated for being equal and match other criteria (minimum length, special characters etc):
#Entity
#Table(name="member")
public class Member {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
#Size(min=3, max=25)
#Column(name = "loginname", nullable = false, updatable = false)
#NotEmpty
private String loginName;
#Transient
private String registerPassword;
#Transient
private String retypeRegisterPassword;
#Column(name = "password_sha256", nullable = false, updatable = false)
#NotEmpty
private String passwordHash;
... more fields, getters and setters
In the intitial signup form, the new user enters his username, password (Twice) and all other required fields. This works as expected.
But what if the user wants to edit his personal data?
We do not want to edit the username and password fields in this scenario. The other fields need to be validated according to the same rules as the signup form. So we should need:
1) A separate form backing object, mimicking the Member object but without username and password fields. This sounds unacceptable to me due to redundancy.
2) Or use the same form backing object but somehow bypassing the username and password fields in the validation. Of course, those fields must be preserved when saving the member object back to the database using Hibernate, but we can make a customized update method in the service layer to handle that.
And the last use case is modifying the password. For this I want a separate form with 3 fields, the original password for extra verification and two fields for the new password and its confirmation.
I think I should use a separate form backing object for this containing only those 3 fields, but do not want to duplicate the field and validation definitions.
Is there a clean way to do this without redundant definitions?
Hope for some thoughts... :)

Related

Passing a set of IDs or a set of objects as data in a DTO in Spring Boot?

I am trying to create a project management app and for my back-end I have a Project Entity which has a many-to-many relationship with the User Entity. I have the following DTO:
public class ProjectDto implements Serializable {
private final Long id;
private final String name;
private final String description;
private final Date createdAt;
private final Date updatedAt;
private final Set<UserDto> users;
}
And in my ProjectService I want to have a method which creates a project having any sent users assigned to it. However, my question is should my front-end send to my back-end a set of user objects or is better to send a set of IDs of the users I want to assign to this project ? Is it not better to actually have this DTO returned when a project is created and have another DTO with a set of user ids for when I want to create a project ?
We cannot trust data from front-end and should apply validations for the request body including Set<UserDto> users. And to validate the Set<UserDto> users we have to use trusted data - from DB, or other BE sources.
And using Set<?> userIds also needs to fetch from DB, but we don't have to add more code to do validate the DTO and validating the IDs is more simple and easy to maintain.
Using userIds is also to make sure the users that set to project are entities that fetched from DB. It also keeps the FE code simpler (I hope) as not having to build the (DTO) object

How to submit a form that has data for 2 models on Spring and let it validate them?

Suppose I have 2 tables: users and preferences.
users table has columns username, password and email.
preferences table has columns contact_me_by_email, contact_me_by_phone_call, contact_me_by_sms.
Each table has it's own model (User and Preferences).
I want to present just one page for users so that when they fill in data in the form that data will be validated and will populate both tables.
I'm able to get all parameters from one form by accessing the Request object and manually performing all validations and proceed according to the results I get.
Also, I can successfully use #Validate annotation to validate models when I present 2 pages for user (each page having just one model - first page contains only data for User model and the second one contains only data for preferences).
I'm struggling to discover a way to present one page only with a form that contains all fields from both models above that could be validated by Spring using the #Validate annotation.
Is that possible? Is there any other annotation I'm not aware of that could do it?
Any help is very much appreciated.
Regards.
So, here is your user mode class :
#Entity
#Table(name = "user")
public class User(){
// Fields of your user annotated with #Column
and fields of your preferences annotated #Transient as below :
#Transient
private String favoriteTvShow;
//getters and setters for both
}
This way you need to submit only one form. Enjoy.

.NET MVC 3 Validation

I use Entity framework for creating model.
I have table hierarchy where User is my base table and I have tables Lecturer and Student which have some specific data in them. Entity framework made model that it isn't suitable so I made my middle layer called modelview where I have student table which wraps all data from both user and student tables. I have made CRUD functionality for students but I only want that admin can create student with some initial password, than admin should not have option to change student password at Edit action.
The problem is that password is required field at student Create action so I set [Required] attribute to it, but at Edit I must not have password field and my ModelState.IsValid is then always false since password field in this case isn't present and therefore is null.
I thought on adding hidden password field, but that would be very bad since someone could look at page source and see password value.
Can I somehow once this field required and another time not required?
If you have any other idea that might help please share with me.
When a user is being edited, you can put in a placeholder hidden field, with the value * (or something like that). This will satisfy the Required attribute - you just have to make sure you don't update the password when the user is edited :)
Maybe you could randomly generate a password and not have it be required at all.
Or you could remove the requred attribute and manually check if it's present at the serverside.
if (string.IsNullOrEmpty(user.Password))
ModelState.AddModelError("Password","A password is required");
To validate clientside, if you're using jquery validation: JQuery Docs
If you have separate views for Student addition and editing, an alternative solution would be:
Create a StudentViewModel class which contains all the properties required for both Student addition and editing, and
Create a StudentAdditionViewModel class (optionally derived from StudentViewModel) which includes a Password property.
You can then use StudentAdditionViewModel as the Add view's model, and StudentViewModel as the edit view's model :)

self referencing object in JPA

I am trying to save a SystemUser entity in JPA. I also want to save certain things like who created the SystemUser and who last modified the system User as well.
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoCreated;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeCreated;
#ManyToOne(targetEntity = SystemUser.class)
#JoinColumn
private SystemUser userWhoLastModified;
#Temporal(TemporalType.TIMESTAMP)
#DateTimeFormat(iso=ISO.DATE_TIME)
private Date timeLastModified;
I also want to ensure that these values are not null when persisted. So If I use the NotNull JPA annotation, that is easily solved (along with reference to another entity)
The problem description is simple, I cannot save rootuser without having rootuser in the system if I am to use a DataLoader class to persist JPA entity. Every other later user can be easily persisted with userWhoModified as the "systemuser" , but systemuser it's self cannot be added in this scheme.
Is there a way so persist this first system user (I am thinking with SQL). This is a typical bootstrap (chicken or the egg) problem i suppose.
Have you tried rootUser.setUserWhoLastModified(rootUser) ?

Order by nullable property simultaneously with ordering by not nullable property in HQL

I have a table called Users in my database. Let's assume that User has only 3 properties
int ID;
string? Name;
string Login;
If user doesn't specify his name then Login is displayed. Otherwise Name is displayed. I wan't to get list of all users sorted by what is displayed. So if user specified Name, it is taken into consideration while sorting, otherwise his position on the list should be determined by Login. Eventually whole list should be ordered alphabetically. I hope I made myself clear...
Is that possible to do in HQL?
Just if someone have similar problem in future:
"order by coalesce(u.Name, u.Login) asc"

Resources