View Javadoc
1   package de.fhdw.wtf.persistence.facade;
2   
3   import java.security.MessageDigest;
4   import java.security.NoSuchAlgorithmException;
5   import java.sql.CallableStatement;
6   import java.sql.ResultSet;
7   import java.sql.SQLException;
8   import java.util.HashSet;
9   import java.util.Set;
10  
11  import oracle.jdbc.OracleTypes;
12  import oracle.jdbc.internal.OracleCallableStatement;
13  import de.fhdw.wtf.persistence.exception.MandantNotLoggedInException;
14  import de.fhdw.wtf.persistence.exception.NameAlreadyExistsException;
15  import de.fhdw.wtf.persistence.exception.ObjectNotFoundException;
16  import de.fhdw.wtf.persistence.exception.OtherSQLException;
17  import de.fhdw.wtf.persistence.exception.PersistenceException;
18  import de.fhdw.wtf.persistence.exception.WrongPasswordException;
19  import de.fhdw.wtf.persistence.meta.Mandant;
20  import de.fhdw.wtf.persistence.meta.Role;
21  import de.fhdw.wtf.persistence.meta.User;
22  import de.fhdw.wtf.persistence.utils.IntegerConstants;
23  
24  /**
25   * Class for the authorization at the Oracle Database.
26   * 
27   */
28  public class OracleAuthorizationFacadeImplementation implements AuthorizationFacade {
29  	
30  	private boolean mandantLoggedIn;
31  	
32  	private Mandant currentMandant;
33  	
34  	private final String salt;
35  	
36  	private final OracleDatabaseManager database;
37  	
38  	/**
39  	 * TODO.
40  	 * 
41  	 * @param salt
42  	 * @param database
43  	 *            is the Database all future Operations will use for the authorization.
44  	 */
45  	public OracleAuthorizationFacadeImplementation(final String salt, final OracleDatabaseManager database) {
46  		super();
47  		this.salt = salt;
48  		this.database = database;
49  		this.currentMandant = null;
50  		this.mandantLoggedIn = false;
51  	}
52  	
53  	@Override
54  	public void logIn(final Mandant mandant) throws PersistenceException {
55  		this.currentMandant = mandant;
56  		if (!this.isPasswordCorrect(this.currentMandant.getId(), "root", this.currentMandant.getRootPassword())) {
57  			throw new WrongPasswordException(mandant.getId(), "root");
58  		}
59  		try (final CallableStatement call =
60  				this.database.getConnection().prepareCall("begin ? := accountfacade.getAllUsersForMandant(?); end;")) {
61  			call.registerOutParameter(1, OracleTypes.CURSOR);
62  			call.setString(2, this.currentMandant.getId());
63  			call.execute();
64  			
65  			try (final ResultSet result = ((OracleCallableStatement) call).getCursor(1)) {
66  				while (result.next()) {
67  					final String name = result.getString(3);
68  					if (!name.equals("root")) {
69  						final User entry = new User(result.getLong(1), name, result.getString(2));
70  						this.currentMandant.addUser(entry);
71  					}
72  				}
73  			}
74  			this.mandantLoggedIn = true;
75  		} catch (final SQLException e) {
76  			throw new OtherSQLException(e);
77  		}
78  	}
79  	
80  	@Override
81  	public boolean isPasswordCorrect(final String mandant, final String username, final String password)
82  			throws PersistenceException {
83  		try {
84  			final MessageDigest message = MessageDigest.getInstance("MD5");
85  			message.update((password + this.salt).getBytes());
86  			final String hashedPW = toHex(message.digest());
87  			
88  			try (final CallableStatement call =
89  					this.database.getConnection().prepareCall("begin ? := accountfacade.authorize(?,?,?); end;")) {
90  				call.registerOutParameter(1, OracleTypes.NUMBER);
91  				call.setString(2, mandant);
92  				call.setString(IntegerConstants.THREE, username);
93  				call.setString(IntegerConstants.FOUR, hashedPW);
94  				call.execute();
95  				return call.getInt(1) == 1;
96  			} catch (final SQLException e) {
97  				throw new OtherSQLException(e);
98  			}
99  		} catch (final NoSuchAlgorithmException e) {
100 			e.printStackTrace();
101 			return false;
102 		}
103 	}
104 	
105 	private void checkMandantLogIn() throws PersistenceException {
106 		if (!this.mandantLoggedIn) {
107 			throw new MandantNotLoggedInException();
108 		}
109 	}
110 	
111 	@Override
112 	public User createUser(final String username, final String password) throws PersistenceException {
113 		this.checkMandantLogIn();
114 		final long id = this.createUser(this.currentMandant.getId(), username, password);
115 		final User result = new User(id, username, this.currentMandant.getId());
116 		this.currentMandant.addUser(result);
117 		return result;
118 	}
119 	
120 	@Override
121 	public void grantRoleToUser(final User user, final Role role) throws PersistenceException {
122 		this.checkMandantLogIn();
123 		try (final CallableStatement call =
124 				this.database.getConnection().prepareCall("begin accountfacade.addRoleToUser(?,?); end;")) {
125 			call.setLong(1, user.getId());
126 			call.setLong(2, role.getId());
127 			call.execute();
128 		} catch (final SQLException e) {
129 			throw new OtherSQLException(e);
130 		}
131 		
132 	}
133 	
134 	@Override
135 	public Role createRole(final String name) throws PersistenceException {
136 		try (final CallableStatement call =
137 				this.database.getConnection().prepareCall("begin ? := accountfacade.createRole(?); end;")) {
138 			call.registerOutParameter(1, OracleTypes.NUMBER);
139 			call.setString(2, name);
140 			call.execute();
141 			return new Role(call.getLong(1), name);
142 		} catch (final SQLException e) {
143 			if (e.getErrorCode() == NameAlreadyExistsException.ERRORCODE) {
144 				throw new NameAlreadyExistsException(e);
145 			}
146 			e.printStackTrace();
147 			throw new OtherSQLException(e);
148 		}
149 	}
150 	
151 	@Override
152 	public Set<Role> getRolesFrom(final User user) throws PersistenceException {
153 		try (final CallableStatement call =
154 				this.database.getConnection().prepareCall("begin ? := accountfacade.getRoles(?,?); end;")) {
155 			call.registerOutParameter(1, OracleTypes.CURSOR);
156 			call.setString(2, user.getMandantId());
157 			call.setString(IntegerConstants.THREE, user.getName());
158 			call.execute();
159 			try (final ResultSet resultSet = ((OracleCallableStatement) call).getCursor(1)) {
160 				final Set<Role> result = new HashSet<>();
161 				while (resultSet.next()) {
162 					final Role entry = new Role(resultSet.getLong(1), resultSet.getString(2));
163 					result.add(entry);
164 				}
165 				return result;
166 			}
167 		} catch (final SQLException e) {
168 			throw new OtherSQLException(e);
169 		}
170 	}
171 	
172 	private long createUser(final String mandant, final String username, final String password)
173 			throws PersistenceException {
174 		try {
175 			final MessageDigest message = MessageDigest.getInstance("MD5");
176 			message.update((password + this.salt).getBytes());
177 			final String hashedPassword = toHex(message.digest());
178 			
179 			try (final CallableStatement call =
180 					this.database.getConnection().prepareCall("begin ? := accountfacade.createUser(?,?,?); end;")) {
181 				call.registerOutParameter(1, OracleTypes.NUMBER);
182 				call.setString(2, mandant);
183 				call.setString(IntegerConstants.THREE, username);
184 				call.setString(IntegerConstants.FOUR, hashedPassword);
185 				call.execute();
186 				return call.getLong(1);
187 			} catch (final SQLException e) {
188 				if (e.getErrorCode() == NameAlreadyExistsException.ERRORCODE) {
189 					throw new NameAlreadyExistsException(e);
190 				}
191 				throw new OtherSQLException(e);
192 			}
193 		} catch (final NoSuchAlgorithmException e) {
194 			e.printStackTrace();
195 			throw new Error(e);
196 		}
197 	}
198 	
199 	@Override
200 	public Mandant createMandant(final String id, final String rootPassword) throws PersistenceException {
201 		this.createUser(id, "root", rootPassword);
202 		return new Mandant(id, rootPassword);
203 	}
204 	
205 	@Override
206 	public Set<User> getUsers() throws PersistenceException {
207 		this.checkMandantLogIn();
208 		return this.currentMandant.getUsers();
209 	}
210 	
211 	@Override
212 	public User getUser(final String mandant, final String name) throws PersistenceException {
213 		try (final CallableStatement call =
214 				this.database.getConnection().prepareCall("begin ? := accountfacade.getUser(?,?); end;")) {
215 			call.registerOutParameter(1, OracleTypes.CURSOR);
216 			call.setString(2, mandant);
217 			call.setString(IntegerConstants.THREE, name);
218 			call.execute();
219 			
220 			try (final ResultSet resultSet = ((OracleCallableStatement) call).getCursor(1)) {
221 				if (resultSet.next()) {
222 					return new User(resultSet.getLong(1), resultSet.getString(IntegerConstants.THREE),
223 							resultSet.getString(2));
224 				} else {
225 					// TODO: create UserNotFoundException
226 					throw new ObjectNotFoundException();
227 				}
228 			}
229 		} catch (final SQLException e) {
230 			e.printStackTrace();
231 			throw new OtherSQLException(e);
232 		}
233 	}
234 	
235 	@Override
236 	public Set<Role> listAllRoles() throws PersistenceException {
237 		final Set<Role> result = new HashSet<>();
238 		try (final CallableStatement call =
239 				this.database.getConnection().prepareCall("begin ?:= accountfacade.getRoles; end;")) {
240 			call.registerOutParameter(1, OracleTypes.CURSOR);
241 			call.execute();
242 			
243 			try (final ResultSet resultSet = ((OracleCallableStatement) call).getCursor(1)) {
244 				while (resultSet.next()) {
245 					result.add(new Role(resultSet.getLong(1), resultSet.getString(2)));
246 				}
247 			}
248 		} catch (final SQLException e) {
249 			throw new OtherSQLException(e);
250 		}
251 		
252 		return result;
253 	}
254 	
255 	private static final char[] hexArray = "0123456789ABCDEF".toCharArray();
256 	
257 	private static String toHex(final byte[] bytes) {
258 		final char[] hexChars = new char[bytes.length * 2];
259 		for (int i = 0; i < bytes.length; i++) {
260 			final int v = bytes[i] & 0xFF;
261 			hexChars[i * 2] = hexArray[v >>> IntegerConstants.FOUR];
262 			hexChars[i * 2 + 1] = hexArray[v & 0x0F];
263 		}
264 		return new String(hexChars);
265 	}
266 	
267 }