Morphia - custom field with custom reader and writer - java

I want to add a custom type of field that will have a default behaviour.
my purpose is to handle all type of secret fields:
for example:
I have password field on user class, and I want password field to be encrypted on some way, so instead of:
#Entity
public static class User {
String name;
String pwd;
String pwdToken
public User() {
}
public User( string name, string password ) {
super();
this.pwd = password;
}
}
and then managing the decrypt and encrypt from outside - service or controller
I would have something like that:
#Entity
public static class User {
String name;
SecretField pwd;
public User() {
}
public User( string name, string password ) {
super();
this.name = name;
// this.pwd.set(password)
}
}
public final class SecretField implements Serializable {
private static final long serialVersionUID = 1L;
private String encryptedContent;
private String token;
public SecretField(String content) {
this.token = generateToken();
this.encryptedContent = decrypt(content, this.token);
}
// when especially called the decrypted pwd will be returned
public decrypt(){
decrypt(encryptedContent, token)
}
//here I should override the default output object - return this.encryptedContent instead of whole object
//???
}
This way, every time I have a secret field I can just use this class and the encrypting will be done automatically, And I won't need to manage the on each controller seperatly.
On update and insert, the password will be sent as decrypted string from client and on get the enrypted string will be returned.
Is it possible with morphia?

You can write a custom codec in 2.0 to do that for you. Prior to that you could write a life cycle event handler to do that. The docs for that can be found at https://morphia.dev

Related

vavr add nested validations with validations combine

I have an input object as
class Person {
private String name;
private String email;
private String phone;
private Address address;
public static class Address {
private String city;
private String pincode;
private String street;
private AddrDetails details;
public static class AddrDetails {
private String state;
private String country;
}
}
}
I am using vavr Validations to validate the input
public static Validation<Seq<ConstraintViolation>, PersonDetailsModel> validatePerson(PersonDetailsRequest request) {
Validation
.combine(
validateName("name", request.getName()),
validateEmail("email", request.getEmail()),
validatePhone("phone", request.getPhone()),
validateAddress(request.getAddress())
).ap((name, email, phone, address) -> new PersonDetailsModel(name, email, phone, address);
}
public static Validation<Seq<ConstraintViolation>, Person.Address> validateAddress(
Person.Address request) {
return Validation
.combine(..
).ap((..) -> new Person.Address(..);
}
In the second function, it returns Seq of ConstraintViolation while validatePerson expects only ConstraintViolation which is why it is failing although I have to add one more level of nesting of validations for AddrDetails. How to handle nested objects validations with this approach.
I am not sure about how shall I go ahead?
In our project we call .mapError(Util::flattenErrors) after .ap. I have the feeling that there is a better way, but this at least solves the nesting.
The method in the Util class looks like this :
public static Seq<ConstraintViolation> flattenErrors(final Seq<Seq<ConstraintViolation>> nested) {
return nested
.flatMap(Function.identity())
.distinct(); // duplicate removal
}

Mask certain string attributes in Java during logging?

Is there a way I can mask certain string variables of a class like password, etc which will prevent during logging? Like overriding toString() method in such way it does not print in logs.
For instance, we have a class Employee with following fields:
public class Employee {
private String username;
**private String password; //mask this field**
private String city;
}
During logging like
LOGGER.INFO("printing object:"+employee);
Here in logging, I'm trying to print the whole object, Employee here and my requirement is it does not print out masked field, password at all and whereas logging of rest of the fields are fine.
First obvious option is to override toString(), example:
public class Employee {
private String username;
private String password;
private String city;
#Override
public String toString() {
return "username=" + username + " city=" + city;
}
public static void main(String[] args) {
System.out.println(new Employee().toString());
}
}
You can also replace password string from logging, for example
String maskedPassword = s.replaceAll("password=[^&]*", "password=***");
In you use jersey you can add logging filter with such replacement.
Create a class called MaskedString that is basically just a replacement for String but has a toString method that doesn't output the actual password:
public class MaskedString(){
private String maskedString;
MaskedString(){
maskedString = "";
}
MaskedString(String string){
maskedString = string;
}
public String getActualString(){
return maskedString;
}
public String setString(String string){
maskedString = string;
}
public String toString(){
return "Not the actual string!";
}
}
If you are using lombok, try the exclude option for ToString.
#Data
#ToString(exclude = {"password"})
public class Employee {
private String username;
private String password;
private String city;
}

How to reference variables in a new class?

I'm writing a program which consists of multiple classes. One class is called "User" and the other one is called "userGroup". I'm trying to import a variable which is contained within a constructor from the User class and use it in the userGroup class.
I've tried the following code:
User userRetrieve = new User();
userRetrieve.User();
This code doesn't seem to work, although I have seen in various tutorials that this is how you would retrieve data from another class. The second line has ".User()" because the constructor is also called User but I am not sure if this is correct and even if it was the initial problem of the program not recognizing the first line would still remain.
I'll show the code form both classes for extra information which may show where I have gone wrong:
User class:
public class User {
String username;
String userType;
String name;
public User() {
username = "x";
userType = "y";
name = "z";
}
public String getUsername() {
return username;
}
public String getUserType() {
return userType;
}
public String getName() {
return name;
}
public String setUserType(String admin) {
return userType = admin;
}
}
userGroup class:
import java.util.ArrayList;
public class userGroup {
String User;
ArrayList<User> userArray = new ArrayList<>();
Integer user0;
public void addSampleData() {
userArray.add(new User());
}
public void getUser(User user0) {
user0 = userArray.get(0);
}
public void printusername() {
System.out.println(user0.getUserName()); // x
}
}
I'm trying to use the username and userType variables in the constructor from the User class.
P.S Apologies for any formatting/indentation errors.
You have misunderstrood some concepts. Firstly the User() method is the constructor so when you do User user = new User() that method is called. I suggest this change to your user class
public class User {
private String username;
private String userType;
private String name;
// Use constructor to pass data to your class
public User(String username, String userType, String name) {
this.username = username;
this.userType = userType;
this.name = name;
}
public String getUsername() {
return username;
}
public String getUserType() {
return userType;
}
public String getName() {
return name;
}
public String setUserType(String admin) {
return userType = admin;
}
}
Now you can create your array and add a user, then retrieve its information
List<User> users = new ArrayList<User>();
users.add(new User("x", "y", "z"));
users.get(0).getUsername(); // returns "x"
Make a list of users
List<User> users = new ArrayList<User>()
Add a user
users.add(new User());
Get a user (lists and arrays are zero-indexed)
User user0 = users.get(0);
Print some properties
System.out.println(user0.getUserName()); // x
You could use the get methods you created in the constructor class?
So if you want to get the username and the userType just create a new variable using the get method
User userRetrieve = new User();
String username = userRetrieve.getUsername();
String userType = userRetrieve.getUserType();
Or alternatively you could just directly access the variables:
User userRetrieve = new User();
String username = userRetrieve.username;
String userType = userRetrieve.userType;
User userRetrieve = new User();
On this line you are instantiating a new object of type Person,
you do this by calling the constructor associated with this particular class.
After you have done this it is possible to acces parameters by calling the various methods you have defined in the Person class. So in your case you should use userRetrieve.getUsername() and so on.. you will however need to declare a variable in the calling class to store these values in.

Form binding using Map<String,String> doesn't work

http://www.playframework.com/documentation/2.1.x/JavaForms
The page states that, with the given example data model,
public class User {
public String email;
public String password;
}
you can bind a Map to the form, and populate the data model, like this:
#Test
public void bindTest() {
Form<User> form = Form.form(User.class);
Map<String,String> anyData = new HashMap<String,String>();
anyData.put("email","bob#gmail.com");
anyData.put("password", "password");
User user = form.bind(anyData).get();
assertEquals("bob#gmail.com", user.email);
assertEquals("password", user.password);
}
This doesn't work. It fails on assertEquals. However, when I add setters and getters to the Users's public fields, it works. Like this:
public class User {
public String email;
public String getEmail() { return email; }
public void setEmail(String value) { email = value; }
public String password;
public String getPassword() { return password; }
public void setPassword(String value) { password = value; }
}
I'd like to be able to do this without adding getters and setters.
After all, the page tells me that "Note: The underlying binding is done using Spring data binder." Okay, so it probably has to do with the way Spring data binding works, but I'm pretty sure the public fields would do the job, without getters and setters.
Any suggestions?

Is there any way to avoid duplicating attributes in this code?

Hi i want to know if exist a way to avoid duplicate code in this code. Now i have an action class named CustomerAction this class handle the behaviour of the request (it's like a controller) and i have a CustomerPOJO with attributes like id, name, last_name etc. Now i have to add attributes to CustomerAction to handle the data submited from the form. Is there any way to bypass the action with my CustomerPOJO ?
public class CustomerAction {
private String nombre;
private String apellido;
private String dni;
private String fechaNac;
private String obraSocial;
private String nroAsociado;
private String plan;
private String password;
private String email;
private String telParticular;
private String telCelular;
private static final Log log = LogFactory
.getLog(CustomerAction.class);
public String execute() throws Exception {
if ("cancelar".equals(this.getAccion())) {
log.debug("Executing 'cancelar' action");
return "login";
}
if ("registro".equals(accion)) {
log.debug("Executing 'registro' action");
IReferenceDataBusinessDelegate ud = new ReferenceDataBusinessDelegate();
ud.signCustomer(this.getNombre(), this.getApellido(),
this.getDni(), this.getCorreo(), this.getContrasena());
return "login";
}
}
public class Customers implements java.io.Serializable {
private long id;
private String dni;
private String name;
private String lastName;
private String email;
private String password;
private String phone;
private String cellphone;
private Date birthDate;
private Date creationDate;
private Date lastAccessDate;
private byte active;
private Set<Profesionales> profesionaleses = new HashSet<Profesionales>(0);
private Set<Pacientes> pacienteses = new HashSet<Pacientes>(0);
public Customers() {
}
}
Yes, use ModelDriven, and use a Customers as the model.
http://struts.apache.org/2.x/docs/model-driven.html
You'll need to make sure the "modelDriven" interceptor is in your stack.
How/where to initialize the model depends on your particular usage scenario; you can do it in a getter as shown in the docs, in a prepare() method if you need to reload it from the DB, etc.
I'm not sure what you mean by "bypass the action."
Please note that the ad-hoc dispatch mechanism implemented here with the accion parameter duplicates functionality provided by Struts 2 using the method attribute of the action configuration. I don't recommend using ad-hoc dispatch mechanisms as it makes understand program flow more difficult than necessary.

Categories