Commit 2392615cebbd2a0429d07b2f66811b00a72f3145

Authored by Thomas Ziemer
1 parent 0bbe393d

feature: Profile ist feature-complete

@@ -63,11 +63,11 @@ @@ -63,11 +63,11 @@
63 <artifactId>mysql-connector-java</artifactId> 63 <artifactId>mysql-connector-java</artifactId>
64 <version>${mysql-version}</version> 64 <version>${mysql-version}</version>
65 </dependency> 65 </dependency>
66 - <dependency> 66 + <!-- dependency>
67 <groupId>com.fasterxml.jackson.core</groupId> 67 <groupId>com.fasterxml.jackson.core</groupId>
68 <artifactId>jackson-databind</artifactId> 68 <artifactId>jackson-databind</artifactId>
69 <version>${jackson-version}</version> 69 <version>${jackson-version}</version>
70 - </dependency> 70 + </dependency -->
71 </dependencies> 71 </dependencies>
72 <build> 72 <build>
73 <finalName>swXercise</finalName> 73 <finalName>swXercise</finalName>
src/main/java/net/ziemers/swxercise/db/dao/GenericDao.java
@@ -16,7 +16,7 @@ import net.ziemers.swxercise.db.BaseEntity; @@ -16,7 +16,7 @@ import net.ziemers.swxercise.db.BaseEntity;
16 public class GenericDao { 16 public class GenericDao {
17 17
18 @PersistenceContext 18 @PersistenceContext
19 - private EntityManager entityManager; 19 + protected EntityManager entityManager;
20 20
21 /** 21 /**
22 * Speichert die gegebene Entität. 22 * Speichert die gegebene Entität.
src/main/java/net/ziemers/swxercise/db/dao/user/UserDao.java 0 → 100644
  1 +package net.ziemers.swxercise.db.dao.user;
  2 +
  3 +import net.ziemers.swxercise.db.dao.GenericDao;
  4 +import net.ziemers.swxercise.lg.model.user.User;
  5 +
  6 +import javax.ejb.Stateless;
  7 +
  8 +@Stateless
  9 +public class UserDao extends GenericDao {
  10 +
  11 + public User findById(final Long id) {
  12 + User user = null;
  13 +
  14 + try {
  15 + // ermittelt den ersten Datensatz mit der gesuchten Id, auch wenn er sich nicht im Persistence Context befindet
  16 + user = (User) entityManager.createNamedQuery("User.findById").setParameter("id", id).getSingleResult();
  17 + } catch(Exception e) {
  18 + /* nix */
  19 + }
  20 + return user;
  21 + }
  22 +
  23 +}
src/main/java/net/ziemers/swxercise/lg/user/Address.java renamed to src/main/java/net/ziemers/swxercise/lg/model/user/Address.java
1 -package net.ziemers.swxercise.lg.user; 1 +package net.ziemers.swxercise.lg.model.user;
2 2
3 import javax.persistence.Entity; 3 import javax.persistence.Entity;
4 4
src/main/java/net/ziemers/swxercise/lg/model/user/Profile.java 0 → 100644
  1 +package net.ziemers.swxercise.lg.model.user;
  2 +
  3 +import javax.persistence.Entity;
  4 +import javax.persistence.EnumType;
  5 +import javax.persistence.Enumerated;
  6 +import javax.validation.constraints.NotNull;
  7 +import javax.xml.bind.DatatypeConverter;
  8 +
  9 +import net.ziemers.swxercise.db.BaseEntity;
  10 +import net.ziemers.swxercise.lg.user.enums.PasswordHashAlgorithm;
  11 +
  12 +import java.security.MessageDigest;
  13 +import java.security.SecureRandom;
  14 +import java.util.Random;
  15 +
  16 +@Entity
  17 +public class Profile extends BaseEntity {
  18 +
  19 + @NotNull
  20 + private String username;
  21 +
  22 + @NotNull
  23 + private String passwordHash;
  24 +
  25 + @NotNull
  26 + private PasswordHashAlgorithm hashAlgorithm = PasswordHashAlgorithm.SHA512;
  27 +
  28 + @NotNull
  29 + private String salt;
  30 +
  31 + private String mailaddress;
  32 +
  33 + /*
  34 + * *****************************************************************************************************************************
  35 + * Konstruktoren
  36 + * *****************************************************************************************************************************
  37 + */
  38 +
  39 + public Profile() {
  40 + super();
  41 +
  42 + setSalt(this.generateSalt());
  43 + }
  44 +
  45 + public Profile(final String username, final String password) {
  46 + this();
  47 +
  48 + setUsername(username);
  49 + setPasswordHash(password);
  50 + }
  51 +
  52 + /*
  53 + * *****************************************************************************************************************************
  54 + * Methoden
  55 + * *****************************************************************************************************************************
  56 + */
  57 +
  58 + private byte[] base64ToByte(final String str) {
  59 + byte[] bytes;
  60 + // Java 6 ships the javax.xml.bind.DatatypeConverter this class provides two static methods that support the same decoding &
  61 + // encoding: parseBase64Binary() and printBase64Binary(). Use this and you will not need an extra library, like Apache
  62 + // Commons Codec.
  63 + // BASE64Decoder decoder = new BASE64Decoder();
  64 +
  65 + // try {
  66 + // bytes = decoder.decodeBuffer(str);
  67 + bytes = DatatypeConverter.parseBase64Binary(str);
  68 + // } catch(IOException e) {
  69 + // e.printStackTrace();
  70 + // }
  71 + return bytes;
  72 + }
  73 + private String byteToBase64(final byte[] bytes) {
  74 + // Java 6 ships the javax.xml.bind.DatatypeConverter this class provides two static methods that support the same decoding &
  75 + // encoding: parseBase64Binary() and printBase64Binary(). Use this and you will not need an extra library, like Apache
  76 + // Commons Codec.
  77 + // BASE64Encoder encoder = new BASE64Encoder();
  78 +
  79 + // String str = encoder.encode(bytes);
  80 + String str = DatatypeConverter.printBase64Binary(bytes);
  81 + return str;
  82 + }
  83 +
  84 + private String cryptString(String string) {
  85 + final int HASH_ITERATION_COUNT = 5;
  86 +
  87 + String hashedString = "";
  88 +
  89 + // vor dem Verschlüsseln den benutzerspezifischen Salt an das Kennwort anhängen
  90 + string += this.getSalt();
  91 +
  92 + // Quelle: http://codeschnipsel.wordpress.com/2008/11/13/passwort-hash-in-java/
  93 + MessageDigest md;
  94 + try {
  95 + md = MessageDigest.getInstance(getHashAlgorithm().getAlgorithm());
  96 + md.reset();
  97 + md.update(base64ToByte(this.getSalt()));
  98 +
  99 + byte[] bytes = md.digest(string.getBytes("UTF-8"));
  100 + for(int i = 0; i < HASH_ITERATION_COUNT; i++) {
  101 + md.reset();
  102 + bytes = md.digest(bytes);
  103 + }
  104 + hashedString = byteToBase64(bytes);
  105 + } catch(Exception e) {
  106 + e.printStackTrace();
  107 + }
  108 + return hashedString;
  109 + }
  110 +
  111 + private String generateSalt() {
  112 + final int HASH_LENGTH = 20; // Ferguson & Schneier overcautiously recommend 32
  113 +
  114 + // Quelle: http://www.javamex.com/tutorials/cryptography/pbe_salt.shtml
  115 + Random random = new SecureRandom();
  116 + byte[] salt = new byte[HASH_LENGTH];
  117 +
  118 + random.nextBytes(salt);
  119 + return byteToBase64(salt);
  120 + }
  121 +
  122 + /*
  123 + * *****************************************************************************************************************************
  124 + * Getters und Setters
  125 + * *****************************************************************************************************************************
  126 + */
  127 +
  128 + public String getUsername() {
  129 + return username;
  130 + }
  131 +
  132 + public void setUsername(String username) {
  133 + this.username = username;
  134 + }
  135 +
  136 + // da die Methode "private" ist, wird der Kennwort-Hashwert niemals per REST in einem JSON-Objekt übermittelt
  137 + private String getPasswordHash() {
  138 + return passwordHash;
  139 + }
  140 +
  141 + private void setPasswordHash(String password) {
  142 + // das Klartextkennwort wird niemals gespeichert!
  143 + this.passwordHash = cryptString(password);
  144 + }
  145 +
  146 + public boolean isValidPassword(final String password) {
  147 + return getPasswordHash().equals(cryptString(password));
  148 + }
  149 +
  150 + @Enumerated(EnumType.STRING)
  151 + private PasswordHashAlgorithm getHashAlgorithm() {
  152 + return hashAlgorithm;
  153 + }
  154 +
  155 + private void setHashAlgorithm(PasswordHashAlgorithm hashAlgorithm) {
  156 + this.hashAlgorithm = hashAlgorithm;
  157 + }
  158 +
  159 + // da die Methode "private" ist, wird der Kennwort-Saltwert niemals per REST in einem JSON-Objekt übermittelt
  160 + private String getSalt() {
  161 + return salt;
  162 + }
  163 +
  164 + private void setSalt(String salt) {
  165 + this.salt = salt;
  166 + }
  167 +
  168 + public String getMailaddress() {
  169 + return mailaddress;
  170 + }
  171 +
  172 + public void setMailaddress(String mailaddress) {
  173 + this.mailaddress = mailaddress;
  174 + }
  175 +
  176 +}
src/main/java/net/ziemers/swxercise/lg/user/User.java renamed to src/main/java/net/ziemers/swxercise/lg/model/user/User.java
1 -package net.ziemers.swxercise.lg.user; 1 +package net.ziemers.swxercise.lg.model.user;
2 2
3 -import javax.persistence.CascadeType;  
4 -import javax.persistence.Entity;  
5 -import javax.persistence.OneToOne; 3 +import javax.persistence.*;
6 import javax.validation.constraints.NotNull; 4 import javax.validation.constraints.NotNull;
7 5
8 import net.ziemers.swxercise.db.BaseEntity; 6 import net.ziemers.swxercise.db.BaseEntity;
9 7
10 @Entity 8 @Entity
  9 +@NamedQueries({
  10 + @NamedQuery(name = "User.findById", query = "SELECT u FROM User u WHERE u.id = :id"),
  11 + @NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")})
11 public class User extends BaseEntity { 12 public class User extends BaseEntity {
12 13
13 private String firstname; 14 private String firstname;
@@ -17,6 +18,8 @@ public class User extends BaseEntity { @@ -17,6 +18,8 @@ public class User extends BaseEntity {
17 @NotNull 18 @NotNull
18 private Profile profile; 19 private Profile profile;
19 20
  21 + private Address address;
  22 +
20 public User() { 23 public User() {
21 super(); 24 super();
22 } 25 }
@@ -56,4 +59,13 @@ public class User extends BaseEntity { @@ -56,4 +59,13 @@ public class User extends BaseEntity {
56 return this; 59 return this;
57 } 60 }
58 61
  62 + @OneToOne(cascade = {CascadeType.ALL})
  63 + public Address getAddress() {
  64 + return address;
  65 + }
  66 +
  67 + public void setAddress(Address address) {
  68 + this.address = address;
  69 + }
  70 +
59 } 71 }
src/main/java/net/ziemers/swxercise/lg/user/Profile.java deleted 100644 → 0
1 -package net.ziemers.swxercise.lg.user;  
2 -  
3 -import javax.persistence.Entity;  
4 -import javax.validation.constraints.NotNull;  
5 -  
6 -import net.ziemers.swxercise.db.BaseEntity;  
7 -import net.ziemers.swxercise.lg.user.enums.PasswordHashType;  
8 -  
9 -@Entity  
10 -public class Profile extends BaseEntity {  
11 -  
12 - @NotNull  
13 - private String username;  
14 -  
15 - @NotNull  
16 - private String passwordHash;  
17 -  
18 - @NotNull  
19 - private PasswordHashType passwordHashType = PasswordHashType.Unknown;  
20 -  
21 - private String mailaddress;  
22 -  
23 - public Profile() {  
24 - super();  
25 - }  
26 -  
27 - public Profile(final String username, final String password) {  
28 - this.username = username;  
29 - // TODO Kennwort verhashen  
30 - this.passwordHash = password;  
31 - }  
32 -  
33 - public String getUsername() {  
34 - return username;  
35 - }  
36 -  
37 - public void setUsername(String username) {  
38 - this.username = username;  
39 - }  
40 -  
41 - private String getPasswordHash() {  
42 - return passwordHash;  
43 - }  
44 -  
45 - private void setPasswordHash(String passwordHash) {  
46 - this.passwordHash = passwordHash;  
47 - }  
48 -  
49 - private PasswordHashType getPasswordHashType() {  
50 - return passwordHashType;  
51 - }  
52 -  
53 - private void setPasswordHashType(PasswordHashType passwordHashType) {  
54 - this.passwordHashType = passwordHashType;  
55 - }  
56 -  
57 - public String getMailaddress() {  
58 - return mailaddress;  
59 - }  
60 -  
61 - public void setMailaddress(String mailaddress) {  
62 - this.mailaddress = mailaddress;  
63 - }  
64 -  
65 -}  
src/main/java/net/ziemers/swxercise/lg/user/enums/PasswordHashAlgorithm.java 0 → 100644
  1 +package net.ziemers.swxercise.lg.user.enums;
  2 +
  3 +public enum PasswordHashAlgorithm {
  4 +
  5 + SHA512("SHA-512"),
  6 + ;
  7 +
  8 + private String algorithm;
  9 +
  10 + PasswordHashAlgorithm(final String algorithm) {
  11 + setAlgorithm(algorithm);
  12 + }
  13 +
  14 + public String getAlgorithm() {
  15 + return algorithm;
  16 + }
  17 +
  18 + private void setAlgorithm(String algorithm) {
  19 + this.algorithm = algorithm;
  20 + }
  21 +
  22 +}
src/main/java/net/ziemers/swxercise/lg/user/enums/PasswordHashType.java deleted 100644 → 0
1 -package net.ziemers.swxercise.lg.user.enums;  
2 -  
3 -public enum PasswordHashType {  
4 -  
5 - Unknown,  
6 - ;  
7 -}  
src/main/java/net/ziemers/swxercise/lg/user/service/UserService.java
@@ -6,20 +6,23 @@ import javax.ejb.Stateless; @@ -6,20 +6,23 @@ import javax.ejb.Stateless;
6 import javax.inject.Inject; 6 import javax.inject.Inject;
7 7
8 import net.ziemers.swxercise.db.dao.GenericDao; 8 import net.ziemers.swxercise.db.dao.GenericDao;
9 -import net.ziemers.swxercise.lg.user.Profile;  
10 -import net.ziemers.swxercise.lg.user.User; 9 +import net.ziemers.swxercise.db.dao.user.UserDao;
  10 +import net.ziemers.swxercise.lg.model.user.Profile;
  11 +import net.ziemers.swxercise.lg.model.user.User;
11 import net.ziemers.swxercise.lg.user.dto.UserDto; 12 import net.ziemers.swxercise.lg.user.dto.UserDto;
12 13
13 @Stateless 14 @Stateless
14 public class UserService { 15 public class UserService {
15 16
16 @Inject 17 @Inject
17 - private GenericDao genericDao; 18 + private UserDao dao;
18 19
19 - public User findUser(final Long id) { return genericDao.findById(User.class, id); } 20 + public User findUser(final Long id) {
  21 + return dao.findById(id);
  22 + }
20 23
21 public Collection<User> findAllUsers() { 24 public Collection<User> findAllUsers() {
22 - return genericDao.findAll(User.class); 25 + return dao.findAll(User.class);
23 } 26 }
24 27
25 public Long saveUser(final UserDto userDto) { 28 public Long saveUser(final UserDto userDto) {
@@ -29,7 +32,7 @@ public class UserService { @@ -29,7 +32,7 @@ public class UserService {
29 final User user = new User(userDto.getFirstname(), userDto.getLastname()) 32 final User user = new User(userDto.getFirstname(), userDto.getLastname())
30 .withProfile(profile); 33 .withProfile(profile);
31 34
32 - return genericDao.save(user); 35 + return dao.save(user);
33 } 36 }
34 37
35 } 38 }
src/main/java/net/ziemers/swxercise/ui/UserViewController.java
@@ -7,8 +7,7 @@ import javax.inject.Inject; @@ -7,8 +7,7 @@ import javax.inject.Inject;
7 import javax.ws.rs.*; 7 import javax.ws.rs.*;
8 import javax.ws.rs.core.MediaType; 8 import javax.ws.rs.core.MediaType;
9 9
10 -import net.ziemers.swxercise.lg.user.Profile;  
11 -import net.ziemers.swxercise.lg.user.User; 10 +import net.ziemers.swxercise.lg.model.user.User;
12 import net.ziemers.swxercise.lg.user.dto.UserDto; 11 import net.ziemers.swxercise.lg.user.dto.UserDto;
13 import net.ziemers.swxercise.lg.user.service.UserService; 12 import net.ziemers.swxercise.lg.user.service.UserService;
14 13
@@ -54,7 +53,6 @@ public class UserViewController { @@ -54,7 +53,6 @@ public class UserViewController {
54 @Produces({MediaType.TEXT_PLAIN}) 53 @Produces({MediaType.TEXT_PLAIN})
55 public String postUser(UserDto userDto) throws Exception { 54 public String postUser(UserDto userDto) throws Exception {
56 userService.saveUser(userDto); 55 userService.saveUser(userDto);
57 -  
58 return "Ok"; 56 return "Ok";
59 } 57 }
60 58