Jpa update get result - jpa

Is it possible to know if the update was done correctly, at least one data was updated?
public void userForgetPassword(String email) {
String resetPasswordKey = ...;
userRepository.userForgetPassword(email, resetPasswordKey);
mailService.sendHtmlMail(email);
}
#Modifying
#Query("update User u set u.resetKey=:resetKey, u.enabled=false where u.username=:email")
void userForgetPassword(#Param("email") String email, #Param("resetPasswordKey") String resetPasswordKey);
Because i would like to send email only if update has worked.
I can verify email before update... but i would like to avoid.

You can return an int instead of void. The number returned specifies the number of modified rows.
#Modifying
#Query("update User u set u.resetKey=:resetKey, u.enabled=false where u.username=:email")
int userForgetPassword(#Param("email") String email, #Param("resetPasswordKey") String resetPasswordKey);
See example at Update Queries With #Modifying

Related

How to return an object from Mono SpringWebFlux

I am using Spring Webflux, and I need to return the ID of user upon successful save.
Repository is returning the Mono
Mono<User> savedUserMono = repository.save(user);
But from controller, I need to return the user ID which is in object returned from save() call.
I have tried using doOn*, and subscribe(), but when I use return from subscribe, there is an error 'Unexpected return value'
Any time you feel the need to transform or map what's in your Mono to something else, then you use the map() method, passing a lambda that will do the transformation like so:
Mono<Integer> userId = savedUserMono.map(user -> user.getId());
(assuming, of course, that your user has a getId() method, and the id is an integer.)
In this simple case, you could also use optionally use the double colon syntax for a more concise syntax:
Mono<Integer> userId = savedUserMono.map(User::getId);
The resulting Mono, when subscribed, will then emit the user's ID.
what you do is
Mono<String> id = user.map(user -> {
return user.getId();
});
and then you return the Mono<String> to the client, if your id is a string

False positives for SQL injection from find-sec-bugs

We're using find-sec-bugs with findbugs to find potential problems in our code. We using Spring JDBCTemplate for our DB access, and find-sec-bugs seems to think we have SQL injection vulnerabilities all over the place. The simplest example is as follows:
public class MyDataRepo {
private final String getDataSql;
public PilotRepositoryImpl(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
getDataSql = "SELECT ID, FIRST_NAME, LAST_NAME, USERNAME, EMAIL FROM USERS WHERE COMPANY_ID = ? AND ID = ?";
//...
}
public MyData getMyData(String companyId, UUID userId)
{
return jdbcTemplate.queryForObject(getDataSql, new Object[]{companyId, userId}, myDataRowMapper);
}
}
This results it thinking it is vulnerable to SQL injection, which it clearly isn't (Please correct me if I'm wrong).
If I copy and paste the string directly into the method like this:
return jdbcTemplate.queryForObject("SELECT ID, FIRST_NAME, LAST_NAME, USERNAME, EMAIL FROM USERS WHERE COMPANY_ID = ? AND ID = ?", new Object[]{companyId, userId}, myDataRowMapper);
then it thinks it's fine. I like having the SQL defined at the top of my class and not buried in each method. I don't really want to have to add #SuppressFBWarnings everywhere, as that pretty much defeats the purpose.
Is there a better way to get around this? Is there something actually wrong with what we're doing?
I like having the SQL defined at the top of my class and not buried in each method.
Try using a static method instead of a field.
public class MyDataRepo {
private static String getDataSql() {
return "SELECT ID, FIRST_NAME, LAST_NAME, USERNAME, EMAIL FROM USERS WHERE COMPANY_ID = ? AND ID = ?"
}
public PilotRepositoryImpl(DataSource dataSource) {
jdbcTemplate = new JdbcTemplate(dataSource);
//...
}
public MyData getMyData(String companyId, UUID userId) {
return jdbcTemplate.queryForObject(getDataSql(), new Object[]{companyId, userId}, myDataRowMapper);
}
}
This results it thinking it is vulnerable to SQL injection, which it clearly isn't (Please correct me if I'm wrong).
I don't disagree but the wider scope might invite more attack vectors.
The code is safe. FSB does not recognize at the moment that the field read is a final field and its source was safe.
This false positive will eventually be ignored when this issue gets fix: https://github.com/find-sec-bugs/find-sec-bugs/issues/385.

Entity Framework field query slow

I'm having some trouble working with a particular ef query. I've simplified everything down as much as I can. I'm only querying for two columns. Here is my model.
[Table("TAXROLL", Schema = "CLAND")]
public class TaxRoll
{
[Key]
[Column("TAXROLL_ID")]
public string Id { get; set; }
[Column("APN")]
public string APN { get; set; }
}
When I execute my query in my controller, if I do firstordefault, the results take as long as 15-18 seconds to return. If I do a where query, the results are almost instantaneous (less than 1 second), (see my commented timing statements below. When I say 15-18 seconds and almost instantaneous, that's where my numbers are coming from).
[ResponseType(typeof(TaxRoll))]
public async Task<IHttpActionResult> Get(string id)
{
//var start = DateTime.Now;
//Debug.WriteLine("Starting Query");
var apnRecord = await ctx.TaxRoll.FirstOrDefaultAsync(x => x.APN == id);
//Debug.WriteLine("Returning APN after " + DateTime.Now.Subtract(start).TotalSeconds);
return Ok(apnRecord);
}
When I query for the primary key (Id), results return consistently fast every single time regardless of how I run the query. This is only a problem when I'm querying for APN. Yes, APN is indexed. It's also unique. I could use it as PK, and in fact I tried that. No dice. I know that executing a query that searches based on APN consistently returns fast when I do it directly against the database.
Any help or direction is greatly appreciated -- I am thoroughly confused.
Your APN Column is NULLABLE that makes EF add OR operator, 99% it makes SQL to "seek" the column (which does not use index). make APN column NOT NULL.
Additionally to the user skalinkin answer, you can set DbContextConfiguration.UseDatabaseNullSemantics property to true.
public class YourDbContext : DbContext
{
public YourDbContext()
{
Configuration.UseDatabaseNullSemantics = true;
// ...
}
}
The query that takes 15-18s
var apnRecord = await ctx.TaxRoll.FirstOrDefaultAsync(x => x.APN == id);
Is same as
var apnRecord = await ctx.TaxRoll.Where(x => x.APN == id).FirstOrDefaultAsync();
If you are using just Where(), nothing will be materialized from the database.
Also consider using Stopwatch instead of calculating timestamps.
var sw = new Stopwatch();
sw.Start();
// do something
Debug.WriteLine(sw.Elapsed);

Validate Unique Value in MVC5 and EF6

In my MVC application I have a requirement where I want user to insert Unique value in a column.
i.e.: Username should be unique in Users table.
I used [Indes(IsUnique = true)] data annotation in my model.
But when I insert duplicate value in the field it throws an exception, but I want to display an Error Message on my View saying Please try with a different Username
Please help me what should I do here?
You can use one of those:
Write your CustomValidator (ny recommendation)
[CustomRemoteValidator(ErrorMessage = #"Username already in use")]
public string Username{ get; set; }`
And override IsValid method
public override bool IsValid(object value)
{
return !(this.DbContext.Set<User>().Any(a =>
a.Username.Equals((string)value));
}
Check it in your business layer.
Check it before save entity in database by overriding SaveChanges() method.

How to authenticate and redirect a user to his 'own' page in Jersey REST service

How to authenticate and redirect a user to his own page i.e to www.mysite.com/"user's email".
I am using the following algo which is not working...
userDB in User class:
Map<String,String> userdata=new HashMap<String,String>();
First my login process form :
#Path("/login")
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void login(
#FormParam("email") String emailc,
#FormParam("password") String pass,
#Context HttpServletResponse servletResponse
) throws IOException,RuntimeException {
User u1=new User();
pass=u1.getPassword();
emailc=u1.getEmailaddrs();
boolean checked=false;
boolean exists;
exists=u1.userdata.containsKey(emailc);
if(exists){
String mypass =u1.userdata.get(emailc);
if(mypass==pass){
checked=true;
}else{
checked=false;
}
}else{
checked=false;
}
if(!checked){
//User Doesn't exists
servletResponse.sendRedirect("http://localhost:8080/MySite/pages/Create_Profile.html");
}else{
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
}
}
createprofile
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public void newUser(
#FormParam("email") String email,
#FormParam("password") String password,
#Context HttpServletResponse servletResponse
) throws IOException {
User u = new User(email,password);
User.userdata.put(email,password);
}
Your usage of userdata [Map] looks wrong to me. Is it a part of user class, is it non static or static ?
If it is non static then every time you will do new User() .. that map will be initialized and it will have no data in it. Hence u1.userdata.containsKey(emailc); will be always false.
If you are using a hashmap as a temporary database for dev purposes then, make it static rather keep it in a different class like UserStore or some DB access layer. Exmaple below:
public class UserDAO(){
private static Map<String,User> userdata = new HashMap<String,User>();
public boolean hasUser(String email){
return userdata.contains(email);
}
public User saveUser(String email, String password ...){
//make user object save it in map and return the same
}
// more methods for delete and edit etc.
}
And use this in your REST layer classes like this
exists = userDao.hasUser(email);
Advantages :
Your problem will be solved.
Later on when you move to actual db implementation you will just have to change your UserDao code and rest application code will be just fine. -- Loose coupling :)
Also regarding forward using email
servletResponse.sendRedirect("http://localhost:8080/MySite/{email}"); <<<< How to redirect using #FormParam("email")
add the email parameter there in the url only, if thats what you want:
servletResponse.sendRedirect("http://localhost:8080/MySite/"+emailc);
UPDATE :
See the fundamental thing is that you get request parameters [email , password]. You check it whether it is present in map or not. Now what you are doing wrong here is you create a new user like this User u = new User(); and then get email and password from it emailc = u.getEmail();. This emailc will always be null and your userdata map will always return false for that. You have two choices :
Either set email and password in user object and then get the data from user object.
Use the email and password obtained from request parameters for your logic. Do not alter them
One good practice to follow while programming is that at all times think of your method parameters as final parameters.
UPDATE 2 :
if(mypass==pass){
checked=true;
}else{
checked=false;
}
Change == to equals method. String matching should be done by equals or equalsIgnoreCase method not ==.
You always create a new User without any parameters: User u1=new User();. All these User instances will have the same property values and probably exists is always false.