This document contains source code files and configuration files for a Java Spring Boot project called BluePrints. It includes files for authenticating users against an Active Directory, handling data for buildings, floors, comments and coordinates in a database, and providing adapter classes to work with that data. The files define services, repositories and entities for working with users, buildings, floors, comments and other data in the application.
8. Version: 06-14-2012
Type: Source Code
Web Site: https://stackoverflow.com/questions/2860943/how-
can-i-hash-a-password-in-
java?utm_medium=organic&utm_source=google_rich_qa&utm_
campaign=google_rich_qa
BluePrints/src/main/java/edu/kings/cs480/BluePrints/ActiveDire
ctory/AuthenticatedUser.javaBluePrints/src/main/java/edu/kings
/cs480/BluePrints/ActiveDirectory/AuthenticatedUser.java/**
*
*/
package edu.kings.cs480.BluePrints.ActiveDirectory;
import javax.naming.NamingException;
import javax.naming.directory.Attributes;
/**
* This class represents a user from the Active Directory.
*/
publicclassAuthenticatedUser{
/** Keeps track of the user's king's id. */
privateString kingsid;
/** Keeps track of the user's first name. */
privateString firstName;
/** Keeps track of the user's last name. */
privateString lastName;
/** Keeps track of the user's email address. */
privateString email;
/**
* Creates a user with the provided information.
9. *
* @param attr
* -
the set of attributes which contains information about this
* user.
*
*/
protectedAuthenticatedUser(Attributes attr)throwsNamingExcep
tion{
firstName =(String) attr.get("givenName").get(0);
lastName =(String) attr.get("sn").get(0);
kingsid =(String) attr.get("KingsID").get(0);
email =(String) attr.get("mail").get(0);
}
/**
* Returns the user's first name.
*
* @return the user's first name.
*/
publicString getFirstName(){
return firstName;
}
/**
* Returns the user's last name.
*
* @return the user's last name.
*/
publicString getLastName(){
return lastName;
}
11. import javax.naming.ldap.LdapContext;
/**
* AuthenticationService
*
* Provides an interface to authenticate against the King's Activ
e Directory server.
*
*/
publicclassAuthenticationService{
// the domain name to authenticate against.
privatestaticString domain ="kings.edu";
/**
* AuthenticationService()
*/
privateAuthenticationService(){
}
/**
* authenticate
*
* Try to authenticate against active directory via ldap and re
turn the status of the authentication.
*
* @param email The email to authenticate against.
* @param password The password associated with the email
* @return true if authentication was successful, otherwise fa
lse.
* @throws NamingException When communication or authe
ntication fails against the domain controller.
*/
publicstaticLdapContext authenticate(String email,String passw
ord)throwsNamingException{
12. // Define our properties of LDAP.
Hashtable<String,String> adProps =newHashtable<String,String
>();
adProps.put(Context.SECURITY_PRINCIPAL, email);
adProps.put(Context.SECURITY_CREDENTIALS, passwo
rd);
adProps.put(Context.INITIAL_CONTEXT_FACTORY,"co
m.sun.jndi.ldap.LdapCtxFactory");
adProps.put(Context.PROVIDER_URL,"ldap://"+ domain);
// Try created a connection based on the above properties that w
e defined.
try{
returnnewInitialLdapContext(adProps,null);
}
catch(javax.naming.CommunicationException e){
e.printStackTrace();
thrownewNamingException("Failed to connect to "+ domain);
}
catch(NamingException e){
thrownewNamingException("Failed to authenticate against "+ d
omain);
}
}
/**
* getUser
*
* Returns the user object based on the user from AD, otherw
ise return null.
*
* @param email The email to retrieve.
* @param context The context connection to the AD director
y.
* @return A user if the user exists, otherwise return null.
*/
13. publicstaticAuthenticatedUser getUser(String email,LdapContex
t context){
try{
String[] requestedAttrs =newString[]{"sn","givenName","Kings
ID","mail","userPrincipalName"};
// Setup a search control.
SearchControls controls =newSearchControls();
// Limit our search, otherwise we will time out traversing the w
hole directory.
controls.setSearchScope(javax.naming.directory.Search
Controls.SUBTREE_SCOPE);
// Limit our attributes, AD has 100+ fields, we don't need all of
them.
controls.setReturningAttributes(requestedAttrs);
// Define our connection string, this format is required for LDA
P.
// TODO: Refactor this.
NamingEnumeration<SearchResult> result = context.search("O
U=User_New,DC=kings,DC=edu","(& (userPrincipalName="+e
mail+")(objectClass=user))", controls);
// Search our attributes until we come across one that matches th
e email we specified.
if(result.hasMore()){
Attributes attr = result.next().getAttributes();
Attribute user = attr.get("userPrincipalName");
if(user!=null)returnnewAuthenticatedUser(attr);
}
}
catch(NamingException e){
// TODO: Handle this gracefully.
//System.out.println(e.toString());
e.printStackTrace();
15. * This class is responsible for handling method used in the Map
Manager Page.
*
*/
@Service
publicclassBuildingAdapter{
/** Used to query data from the buildings table in the database.
*/
@Autowired
privateBuildingRepository buildingRepo;
/** Handles calls to the database about the users in the BluePrin
ts System. */
@Autowired
privateAppUserRepository userRepo;
/** Handles calls to the database about the coordinate data for b
uildings. */
@Autowired
privateCoordinateRepository coordinateRepo;
/**
* Returns all the buildings stored in the system.
*
* @return all the buildings stored in the system.
*/
publicList<Building> getBuildings(){
return buildingRepo.findAll();
}
/**
* Returns the building with the corresponding id provided.
*
* @param buildingId
* - the id of the building being returned.
16. * @return the building corresponding to the provided id.
*/
publicBuilding getBuilding(UUID buildingId){
Building building =null;
building = buildingRepo.findOne(buildingId);
return building;
}
/**
* Updates the building with corresponding id, with the infor
mation provided.
*
* @param buildingId
* - the id of the building being updated.
* @param buildingName
* - the new name of the building.
* @return whether, or not, the building was successfully upd
ated.
*/
publicboolean updateBuilding(UUID buildingId,String building
Name){
boolean updated =false;
Building building = buildingRepo.findOne(buildingId);
if(building !=null){
building.setName(buildingName);
buildingRepo.save(building);
updated =true;
}
return updated;
17. }
/**
* Removes the building with the provided id from the system
.
*
* @param buildingId
* - the id of the building being deleted.
* @return whether, or not, the building was successfully rem
oved.
*/
publicboolean deleteBuilding(UUID buildingId){
boolean deleted =false;
Building building = getBuilding(buildingId);
if(building !=null){
buildingRepo.delete(building);
deleted =true;
}
return deleted;
}
/**
* Adds a new building with the provided name, and creator i
d.
*
* @param buildingName
* - the name of the building.
* @param creatorId
* - the id of the person creating the building.
* @return the newly added building.
*/
publicBuilding addBuilding(String buildingName, UUID creator
Id){
18. Building building =null;
AppUser creator = userRepo.findOne(creatorId);
if(creator !=null){
building =newBuilding(buildingName, creator);
buildingRepo.save(building);
}
return building;
}
/**
* Adds the coordinates to the database for the building with
the corresponding
* building id.
*
* @param buildingId
* - the id of the building the coordinate belongs to.
* @param coordinateData
* - the data being stored in the database.
* @return whether, or not, the data was successfully added.
*/
publicboolean addCoordinates(UUID buildingId,String coordina
teData){
boolean added =false;
Building building = buildingRepo.findOne(buildingId);
if(building !=null){
BuildingCoordinate coordinates =newBuildingCoordinate(buildi
ng, coordinateData);
19. coordinateRepo.save(coordinates);
added =true;
}
return added;
}
/**
* Updates the coordinate data for the building with the corre
sponding building
* id.
*
* @param buildingId
* - the id of the building the coordinate belongs to.
* @param coordinateData
* - the data being stored in the database.
* @return whether, or not, the data was successfully updated
.
*/
publicboolean updateCoordinates(UUID buildingId,String coord
inateData){
boolean updated =false;
Building building = buildingRepo.findOne(buildingId);
if(building !=null){
BuildingCoordinate coordinates = coordinateRepo.findByBuildi
ng(building);
coordinates.setCoordinateData(coordinateData);
coordinateRepo.save(coordinates);
updated =true;
}
return updated;
20. }
/**
* Returns the coordinate data for the building with the corre
sponding building
* id.
*
* @param buildingId
* -
the id of the building the coordinates are being requested for.
* @return the coordinates for the building.
*/
publicBuildingCoordinate getCoordinates(UUID buildingId){
BuildingCoordinate coordinates =null;
Building building = buildingRepo.findOne(buildingId);
if(building !=null){
coordinates = coordinateRepo.findByBuilding(building)
;
}
return coordinates;
}
}
BluePrints/src/main/java/edu/kings/cs480/BluePrints/Adapters/
CommentAdapter.javaBluePrints/src/main/java/edu/kings/cs480/
BluePrints/Adapters/CommentAdapter.java
package edu.kings.cs480.BluePrints.Adapters;
import org.springframework.beans.factory.annotation.Autowired
;
21. import org.springframework.stereotype.Service;
import edu.kings.cs480.BluePrints.Database.Comment;
import edu.kings.cs480.BluePrints.Database.CommentRepositor
y;
import edu.kings.cs480.BluePrints.Database.Floor;
import edu.kings.cs480.BluePrints.Database.FloorRepository;
import edu.kings.cs480.BluePrints.Database.AppUser;
import edu.kings.cs480.BluePrints.Database.AppUserRepository
;
import java.util.UUID;
import java.util.List;
/**
* This adapter is responsible for handling data involving comm
ent.
*
*/
@Service
publicclassCommentAdapter{
/** Handles calls to the Floor table in the database. */
@Autowired
publicFloorRepository floorRepo;
/** Handles calls to the App User table in the database. */
@Autowired
publicAppUserRepository userRepo;
/** Handles calls to the floor comment table in the database. */
@Autowired
publicCommentRepository commentRepo;
/**
* This method adds a comment to the floor.
22. *
* @param floorId
* -
the id of the floor that comment is being added to.
* @param creatorId
* - the id of the creator of this comment.
* @param commentMsg
* - the comment being added to the floor.
*
*/
publicboolean addComment(UUID floorId, UUID creatorId,Stri
ng commentMsg){
boolean added =false;
AppUser user = userRepo.getOne(creatorId);
Floor floor = floorRepo.getOne(floorId);
if(floor !=null&& user !=null){
Comment newComment =newComment(floor, user, commentMs
g);
commentRepo.save(newComment);
added =true;
}
return added;
}
/**
* This method updates a comment with the new message pro
vided.
*
23. * @param commentId
* - the id of the comment being updated.
* @param editorId
* - the id of the user updating this comment.
* @param newMsg
* - the content of the new message for the comment.
*/
publicboolean updateComment(UUID commentId, UUID editorI
d,String newMsg){
boolean updated =false;
AppUser user = userRepo.findOne(editorId);
Comment comment = commentRepo.findOne(commentId);
if(comment !=null&& user !=null){
comment.setCreator(user);
comment.setMessage(newMsg);
commentRepo.save(comment);
updated =true;
}
return updated;
}
/**
* This method returns the comments which corresponds to th
e floor id provided.
*
* @param floorId
* - the id of the floor the comment belong to.
* @return the comment for corresponding floor id.
*/
25. import edu.kings.cs480.BluePrints.Database.Floor;
import edu.kings.cs480.BluePrints.Database.Building;
import edu.kings.cs480.BluePrints.Database.BuildingRepository
;
/**
* This adapter is responsible for handling data involing
* floors.
*/
@Service
publicclassFloorAdapter{
/** Used to handle calls to the database. */
@Autowired
privateFloorRepository floorRepo;
/** Used to query data from the buildings table in the database.
*/
@Autowired
privateBuildingRepository buildingRepo;
/**
* This method takes a building id, and the name of a floor,
* then adds it to the system.
*
* @param buildingId -
the id of the building the floor is being added to.
* @param floorName -
the name of the floor being added to the building.
*
*/
publicFloor addFloor(UUID buildingId,String floorName){
Floor newFloor =null;
28. buildingFloors.get(buildingId).add(floor);
System.out.println(String.format("added Floor %s to list.", floor
.getName()));
}else{
LinkedList<Floor> newFloorList =newLinkedList<>();
newFloorList.add(floor);
buildingFloors.put(buildingId, newFloorList);
System.out.println(String.format("Created a new list for Buildin
g %s, and added Floor %s.", building.getName(), floor.getName
()));
}
}
return buildingFloors;
}
/**
* This method returns the floor which corresponds
* to the id provided.
*
* @param floorId - the id of the floor being requested.
* @return the floor corresponding to the id provided.
*/
publicFloor getFloor(UUID floorId){
Floor floor =null;
floor = floorRepo.getOne(floorId);
return floor;
}
}
30. package edu.kings.cs480.BluePrints.Adapters;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import javax.naming.NamingException;
import javax.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired
;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import edu.kings.cs480.BluePrints.Database.AppUser;
/**
* This class represents a wrapper for an active directory connec
tion, which
* provides information about employees and students of King's
College.
*/
@Service
publicclassLoginAdapter{
// /** Used to log any errors that may error while using the acti
ve directory adapter. */
// @Autowired
// private LoggingAdapter loggingAdapter;
@Autowired
privateUserAdapter userAdapter;
/**
* Returns whether, or not, there is a user currently logged in
31. to the
* BluePrints system.
*
* @param model
* -
the model used to store attributes that can be used in the
* page currently being viewed by the user.
* @param session
* -
the session which keeps track of the currently active user.
* @return whether, or not, there is a user currently logged in
.
*/
publicboolean checkLogin(Model model,HttpSession session){
boolean loggedIn =false;
Object user = session.getAttribute("activeUser");
if(user !=null){
AppUser activeUser =(AppUser) user;
loggedIn =true;
model.addAttribute("activeUser", activeUser);
}
return loggedIn;
}
/**
* This helper method tries to log in with the provided passw
ord and user
* name and returns whether, or not, it was successful.
*
32. * @param email
* - the email of the user trying to log in.
* @param password
* - the password of the user trying to log in.
* @param session
* -
the session which keeps track of the currently active user.
* @return whether, or not, the user was able to login.
* @throws NamingException
*/
publicboolean login(String email,String password,HttpSession s
ession){
boolean loggedIn =false;
AppUser user = userAdapter.getUserByEmail(email);
if(user !=null){
String stored = user.getPassword();
try{
if(SecurityAdapter.check(password, stored)){
loggedIn =true;
session.setAttribute("activeUser", user);
}
}catch(InvalidKeySpecException|NoSuchAlgorithmException e)
{
e.printStackTrace();
}
}
33. return loggedIn;
}
/**
* Returns the active user in the provided session, if any.
*
* @param session - the session containing the active user.
* @return the active user in the provided session, if any.
*/
publicAppUser getActiveUser(HttpSession session){
AppUser activeUser =null;
Object user = session.getAttribute("activeUser");
if(user !=null){
activeUser =(AppUser) user;
}
return activeUser;
}
}
BluePrints/src/main/java/edu/kings/cs480/BluePrints/Adapters/
Mock/MockStaffAdapter.javaBluePrints/src/main/java/edu/kings
/cs480/BluePrints/Adapters/Mock/MockStaffAdapter.javapackag
e edu.kings.cs480.BluePrints.Adapters.Mock;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import edu.kings.cs480.BluePrints.Adapters.StaffAdapter;
44. d);
staffRepo.save(assignment);
CS 300 Final Project/Exam
You’ve been presented with a copy of BluePrints, the 2017-
2018 CS480/481 project. This project
is a web site designed to allow easy editing of building, floor,
and room data for the MonarchMaps
project (’16-’17). This project has a number of dependencies,
and zero unit tests. It relies fairly heavily
on Spring and Spring MVC to manage *many* of those
dependencies so you are in reasonably good
shape compared to other legacy projects. This represents a
fairly realistic request in business and the
time frame (2 weeks) is likely a much larger timeframe than you
would normally have OR the
application’s scope would be much larger.
I have updated this project to no longer depend on a remote
Postgres SQL database, but instead
use Spring’s built-in, in-memory database H2. This means you
do not have to connect to or worry about
45. conflicts with a database, however, nothing is actually persisted
between sessions. When you run this
project (using Eclipse’s “Run on Server” feature), you’ll be able
to point your browser at
http://localhost:8080/BluePrints to investigate the live app. I’ll
be pushing a .sql file into your repository
within a few days to auto-seed the H2 database with some test
data and will supply you a dummy
login/password at that point. In the meantime, you can still get
familiar with the code!
Your task is to add the following feature/change, leveraging the
techniques you’ve learned
throughout this course and make sure you are creating proper
unit tests for the feature and any code
you must modify. Some areas of the code may not work
properly, and you’ll need to investigate/fix
those areas using characterization tests to explore. I am not
mandating a specific number of tests, but
you should adequately ensure you are testing what you’re
changing.
We no longer want to “hard delete” any comment from the
system. Comments are
attached to floors. Instead “soft delete” them by setting a
deleted flag on the
46. comment. Soft-deleted comments should not normally be
accessible under normal
operations but should still be stored in the table. We want to
capture the date/time
the comment was deleted, and the user who did the deletion.
There are several things to consider, here. The project is using
Jpa, which you can read more
about at https://spring.io/guides/gs/accessing-data-jpa/. Pay
particular attention to how the
@Repository annotation works, especially in creating “find”
methods… Here are a few suggestions to
get you started:
• Do some quick sketching/outlining to see how the classes
interact
• Refactor the classes and interfaces in the
edu.kings.cs480.BluePrints.Database
package to split the “Model” classes from the @Repository
interfaces to simplify the scope of
what you’re working on
• Start by getting the field on each object to work, then look to
override the delete behavior, and
finally the find behavior
http://localhost:8080/BluePrints
47. http://localhost:8080/BluePrints
https://spring.io/guides/gs/accessing-data-jpa/
https://spring.io/guides/gs/accessing-data-jpa/
• You may or may not have to create concrete implementations
of the @Repository interfaces
depending on your approach
• Follow the existing application conventions for how “users”
are stored my mimicking how the
“creator”/created_by fields work
• Be *cautious* when a floor is deleted – currently, a deleted
floor hard-deletes all of its
comments; this behavior must also change
o Pay attention to the relationship between Floor and Comment;
and note how a
Comment ignores if the comment creator cannot be found in the
AppUsers data… <that
is a hint>
Your work is your own. Please do not share code as that will
fall under the college’s academic
dishonesty and plagiarism guidelines.
48. I pushed a few changes to everyone's repos for the final project.
Changes include:
* SQL script to automatically seed test data
* Fixed a number of issues with unavailable/out of date
dependencies
* I adjusted the LoginAdapter so you can login with any
password and the username of 'admin'; the passwords in the
database are one-way encrypted and there was no
documentation... :-(
Please make sure to *PULL* before you continue working. If
you run into any issues, please let me know.
I've created a private copy repo for each of you based on the
"BluePrints" project that was a CS480 final project last year.
This is an Eclipse project, targeting Tomcat 8.5, Java 1.8, and
JUnit 4, which is as close as I can reasonably get to the lab
computers in Admin 425.
If you want to run at home, get Eclipse for JEE (exact version
I'm
using: https://www.eclipse.org/downloads/download.php?file=/t
echnology/epp/downloads/release/2018-12/R/eclipse-jee-2018-
12-R-win32-x86_64.zip&mirror_id=1249), Tomcat 8.5
(http://mirror.olnevhost.net/pub/apache/tomcat/tomcat-
8/v8.5.40/bin/apache-tomcat-8.5.40-windows-x64.zip), and Java
EE JDK 8 (1.8)
(https://www.oracle.com/technetwork/java/javaee/downloads/ja
va-ee-sdk-downloads-3908423.html). I created a folder at
C:Java and unzipped/installed all to there. (If you're using a
Mac, you'll need to download alternate links, of course!)
In Eclipse, go to Window -> Preferences, Servers +-> Runtime
Environments, and click Add. Choose Tomcat 8.5, then pick the
directory you unzipped from.
From there, File -> Import..., Choose "Git" +-> "Projects from
Git", "Clone from URI", and clone from GitHub as usual. On
the new project wizard, it should detect the Eclipse project and
get things going pretty smoothly from there. It should build
49. after a few moments, and allow you to choose "Run", and then
set up a new Apache Tomcat run configuration. If you browse
out to http://localhost:8080/BluePrints , you should receive a
login window (note: nothing works from here).
For now, focus on exploring the code a bit, and make sure it
builds. I'll have the actual final assignment published in Moodle
in the next couple of days.
CS 300 Final Project/Exam
You’ve been presented with a copy of BluePrints, the 2017-
2018 CS480/481 project. This project
is a web site designed to allow easy editing of building, floor,
and room data for the MonarchMaps
project (’16-’17). This project has a number of dependencies,
and zero unit tests. It relies fairly heavily
on Spring and Spring MVC to manage *many* of those
dependencies so you are in reasonably good
shape compared to other legacy projects. This represents a
fairly realistic request in business and the
time frame (2 weeks) is likely a much larger timeframe than you
would normally have OR the
application’s scope would be much larger.
I have updated this project to no longer depend on a remote
Postgres SQL database, but instead
50. use Spring’s built-in, in-memory database H2. This means you
do not have to connect to or worry about
conflicts with a database, however, nothing is actually persisted
between sessions. When you run this
project (using Eclipse’s “Run on Server” feature), you’ll be able
to point your browser at
http://localhost:8080/BluePrints to investigate the live app. I’ll
be pushing a .sql file into your repository
within a few days to auto-seed the H2 database with some test
data and will supply you a dummy
login/password at that point. In the meantime, you can still get
familiar with the code!
Your task is to add the following feature/change, leveraging the
techniques you’ve learned
throughout this course and make sure you are creating proper
unit tests for the feature and any code
you must modify. Some areas of the code may not work
properly, and you’ll need to investigate/fix
those areas using characterization tests to explore. I am not
mandating a specific number of tests, but
you should adequately ensure you are testing what you’re
changing.
We no longer want to “hard delete” any comment from the
system. Comments are
51. attached to floors. Instead “soft delete” them by setting a
deleted flag on the
comment. Soft-deleted comments should not normally be
accessible under normal
operations but should still be stored in the table. We want to
capture the date/time
the comment was deleted, and the user who did the deletion.
There are several things to consider, here. The project is using
Jpa, which you can read more
about at https://spring.io/guides/gs/accessing-data-jpa/. Pay
particular attention to how the
@Repository annotation works, especially in creating “find”
methods… Here are a few suggestions to
get you started:
• Do some quick sketching/outlining to see how the classes
interact
• Refactor the classes and interfaces in the
edu.kings.cs480.BluePrints.Database
package to split the “Model” classes from the @Repository
interfaces to simplify the scope of
what you’re working on
• Start by getting the field on each object to work, then look to
override the delete behavior, and
52. finally the find behavior
http://localhost:8080/BluePrints
http://localhost:8080/BluePrints
https://spring.io/guides/gs/accessing-data-jpa/
https://spring.io/guides/gs/accessing-data-jpa/
• You may or may not have to create concrete implementations
of the @Repository interfaces
depending on your approach
• Follow the existing application conventions for how “users”
are stored my mimicking how the
“creator”/created_by fields work
• Be *cautious* when a floor is deleted – currently, a deleted
floor hard-deletes all of its
comments; this behavior must also change
o Pay attention to the relationship between Floor and Comment;
and note how a
Comment ignores if the comment creator cannot be found in the
AppUsers data… <that
is a hint>
Your work is your own. Please do not share code as that will
fall under the college’s academic
dishonesty and plagiarism guidelines.