diff --git a/.gitignore b/.gitignore index 0276604..1176c27 100644 --- a/.gitignore +++ b/.gitignore @@ -19,9 +19,6 @@ *.tar.gz *.rar -# Resources -# src/main/resources - # IntelliJ \.idea @@ -30,3 +27,4 @@ hs_err_pid* # ignore any .properties files *.properties +/.jpb/ diff --git a/README.md b/README.md index 4cf1f23..cda6844 100644 --- a/README.md +++ b/README.md @@ -6,30 +6,41 @@ Team Vanquish Project 2 Implementation - [ ] Users are interfacing with an advanced UI built with Angular running in a browser - [ ] CRUD operations are supported for one or more domain objects via the web application's API endpoints - [ ] Client/Server communication is done with JSON in HTTP request and response bodies. -- [ ] Client/Server communication is done with JSON in HTTP request and response bodies. - [ ] All low-level persistence logic is abstracted away with Hibernate/Spring Data - [ ] Documentation (all classes and methods have adequate Javadoc comments) -- [ ] All Exceptions are caught and logged to a file +- [ ] All VanquishP2.Exceptions are caught and logged to a file/database - [ ] Data useful to the application is retrieved from a third party API - [ ] Adequate test coverage for the service-layer - [ ] DevOps CI/CD pipeline is used to build and deploy project to a publicly available remote location -## -- App Name Here -- -You will need to write a small paragraph describing your application. It should be 4-6 sentences and briefly cover the important points and features. +## -- 4TheMusic -- -### Minimum Viable Product -Your team will need to work with the trainer to come up with a satisfactory list of user stories for MVP as well as bonus stories. They should begin with "As a [stakeholder] I can... and describe what the user should be able to do. Aim for at least 2 different roles, user and administrator. Try to come up with 8 or so user stories for MVP. Carefully consider what your team can accomplish in 3 weeks and try not to set yourselves too great a task. +"4TheMusic" is a social web service that brings music fans and concert-goers together with their favorite artists, +while allowing premium users to gain valuable insights from user trends and analytics. + +Users can create and share playlists of their favorite songs and artists, +along with viewing songs by similar artists and genres, and connecting to the social media accounts of their +favorite artists. -* As a user, I can see... -* As a user, I can purchase... -* As a user, I can check... -* As an administrator, I can schedule... -* As an administrator, I can cancel... -* As an administrator, I can view... +Premium users (concert organizers, artists, tour managers, etc.) can browse artists and see high-level, real-time analytics on +the users that like particular artists. + + +### Minimum Viable Product +* As a user, I can create a playlist. +* As a user, I can add or remove songs from a playlist. +* As a user, I can rate a song with a like or dislike. +* As a user, I can look up an album and see what songs are on it. +* As a user, I can look up an artist and see a [limited] list of their songs. +* As a premium user, I can schedule a concert. +* As a premium user, I can cancel a concert. +* As a premium user, I can see a list of liked songs for a user. +* As a premium user, I can see a like/dislike ratio for a particular song. ### Bonus Stories -* As an administrator, I can... +* As a user, I can view a list of users who like the same songs. +* As a premium user, I can see a like/dislike ratio for an entire artist. ## Tech Stack You should be employing the following technologies in your project. diff --git a/pom.xml b/pom.xml index 33fd8cc..804653e 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ com.revature.vanquish P2 - 0.0.1-SNAPSHOT + 0.0.1 war P2 Project 2 with Spring Boot Implementation @@ -22,30 +22,114 @@ org.springframework.boot spring-boot-starter-data-jpa + org.springframework.boot spring-boot-starter-validation + 2.5.5 + org.springframework.boot spring-boot-starter-web - - org.mariadb.jdbc - mariadb-java-client - runtime - org.springframework.boot spring-boot-starter-tomcat + 2.5.5 provided + org.springframework.boot spring-boot-starter-test test + + + com.vaadin.external.google + android-json + 0.0.20131108.vaadin1 + compile + + + + + com.fasterxml.jackson.core + jackson-databind + 2.13.0 + + + + + com.fasterxml.jackson.core + jackson-core + 2.13.0 + + + + + org.mariadb.jdbc + mariadb-java-client + 2.7.3 + runtime + + + + + org.json + json + 20210307 + + + + + io.jsonwebtoken + jjwt-api + 0.11.2 + + + + io.jsonwebtoken + jjwt-impl + 0.11.2 + runtime + + + + io.jsonwebtoken + jjwt-jackson + 0.11.2 + runtime + + + + + org.mockito + mockito-core + 4.0.0 + + + + + com.h2database + h2 + 1.4.200 + + + + com.squareup.okhttp3 + okhttp + 4.9.2 + + + junit + junit + 4.13.2 + test + + diff --git a/src/main/java/Application/P2Application.java b/src/main/java/Application/P2Application.java deleted file mode 100644 index 530bbe9..0000000 --- a/src/main/java/Application/P2Application.java +++ /dev/null @@ -1,13 +0,0 @@ -package Application; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; - -@SpringBootApplication -public class P2Application { - - public static void main(String[] args) { - SpringApplication.run(P2Application.class, args); - } - -} diff --git a/src/main/java/VanquishP2/Application/Beans/Aspects/LoggerAspect.java b/src/main/java/VanquishP2/Application/Beans/Aspects/LoggerAspect.java new file mode 100644 index 0000000..04a5a79 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Aspects/LoggerAspect.java @@ -0,0 +1,52 @@ +package VanquishP2.Application.Beans.Aspects; + +import VanquishP2.Application.Beans.ModelServices.LoggerService; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.AfterThrowing; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; + +/** + * LoggerAspect + * Logs all method calls and exceptions for all classes except filters. + * + * @author Kollier Martin + */ + + +@Aspect +@Component +public class LoggerAspect { + private final LoggerService loggerService; + + public LoggerAspect(LoggerService loggerService) { + this.loggerService = loggerService; + } + + @Pointcut("within(VanquishP2.*.*.*.*)") + public void logAll() { + + } + + @Around("within(VanquishP2.*.*.*.*)") + public void logAroundAll(ProceedingJoinPoint joinPoint) throws Throwable { + try { + joinPoint.proceed(); + } catch (Exception ignored){ + + } + } + + @AfterThrowing(pointcut = "logAll()", throwing = "e") + public void logMethodException(JoinPoint jp, Throwable e) { + String methodSig = extractMethodSignature(jp); + loggerService.writeLog(String.format("%s was thrown in method %s with message: %s", e.getClass().getSimpleName(), methodSig, e.getMessage()), 3); + } + + private String extractMethodSignature(JoinPoint jp) { + return jp.getTarget().getClass().toString() + "." + jp.getSignature().getName(); + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Filters/AuthenticationFilter.java b/src/main/java/VanquishP2/Application/Beans/Filters/AuthenticationFilter.java new file mode 100644 index 0000000..2c5fb7d --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Filters/AuthenticationFilter.java @@ -0,0 +1,63 @@ +package VanquishP2.Application.Beans.Filters; + +import VanquishP2.Application.Beans.Service.JWTUtil; +import VanquishP2.DTOs.PrincipalDTO; +import VanquishP2.Exceptions.AuthenticationException; +import io.jsonwebtoken.Claims; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; +import org.springframework.web.context.support.WebApplicationContextUtils; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * Authentication Filter + * Chains with other filters on every endpoint call to make sure the current request is from a valid source + * @author Kollier Martin + * @date 11/8/2021 + */ + +@Component +public class AuthenticationFilter implements Filter { + private JWTUtil jwtUtil; + + @Override + public void init(FilterConfig config) { + ApplicationContext container = WebApplicationContextUtils.getRequiredWebApplicationContext(config.getServletContext()); + this.jwtUtil = container.getBean(JWTUtil.class); + } + + @Override + public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException { + HttpServletRequest request = (HttpServletRequest) req; + HttpServletResponse response = (HttpServletResponse) resp; + + if (!request.getRequestURI().equals("/4TheMusic/login") + && !request.getRequestURI().equals("/4TheMusic/register/basic") + && !request.getRequestURI().equals("/4TheMusic/register/premium") + && !request.getRequestURI().equals("/4TheMusic/user/all")) { + parseToken(request); + } + + chain.doFilter(request, response); + } + + private void parseToken(HttpServletRequest request) throws AuthenticationException { + String errMessage = "Unauthorized user tried to barge their way in here! Don't worry, I caught this transgression. Error: %s"; + + String header = request.getHeader(jwtUtil.getHeader()); + + if (header == null || !header.startsWith(jwtUtil.getPrefix())) { + throw new AuthenticationException(errMessage); + } else { + String token = header.replaceAll(jwtUtil.getPrefix(), ""); + + Claims jwtClaims = jwtUtil.parseJWT(token); + PrincipalDTO principalDTO = new PrincipalDTO(jwtClaims); + request.setAttribute("principal", principalDTO); + } + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Filters/CORSFilter.java b/src/main/java/VanquishP2/Application/Beans/Filters/CORSFilter.java new file mode 100644 index 0000000..4a68eea --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Filters/CORSFilter.java @@ -0,0 +1,22 @@ +package VanquishP2.Application.Beans.Filters; + +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class CORSFilter extends OncePerRequestFilter { + + @Override + protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws ServletException, IOException { + resp.setHeader("Access-Control-Allow-Origin", "*"); + resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, PUT, PATCH"); + resp.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Authentication"); + chain.doFilter(req, resp); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/AlbumService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/AlbumService.java new file mode 100644 index 0000000..7137cd9 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/AlbumService.java @@ -0,0 +1,86 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Album; +import VanquishP2.Application.Beans.Repos.AlbumRepository; +import VanquishP2.Exceptions.AlbumDoesNotExistException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.Optional; + +/** + * AlbumService + * The middle man, or service, that connects to the persistence layer for everything Album related + * + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Service +@Transactional +public class AlbumService { + private final AlbumRepository albumRepository; + + @Autowired + public AlbumService(AlbumRepository albumRepository) { + this.albumRepository = albumRepository; + } + + /** + * Get all Albums + * @return List of Albums + */ + public List getAll() { + return albumRepository.findAll(); + } + + /** + * Fetch Album by its ID + * @param id Album ID + * @return Album Object + * @throws AlbumDoesNotExistException Album does not exist in DB + */ + public Album getByID(int id) throws AlbumDoesNotExistException { + return albumRepository.findByAlbumID(id) + .orElseThrow(AlbumDoesNotExistException::new); + } + + /** + * Fetch Album by its Title + * @param title Album Title + * @return Album Object + * @throws AlbumDoesNotExistException Album does not exist in DB + */ + public Album getByTitle(String title) throws AlbumDoesNotExistException { + return albumRepository.getAlbumByAlbumTitle(title) + .orElseThrow(AlbumDoesNotExistException::new); + } + + /** + * Delete album by ID + * @param id Album ID + * @throws AlbumDoesNotExistException Album does not exist in DB + */ + public void delete(int id) throws AlbumDoesNotExistException { + albumRepository.delete(getByID(id)); + } + + /** + * Delete album by album + * @param album Album object + * @throws AlbumDoesNotExistException Album does not exist in DB + */ + public void delete(Optional album) throws AlbumDoesNotExistException { + albumRepository.delete(album.get()); + } + + /** + * This method saves an album to the DB + * @param album Album object that we'll be saving to the DB + */ + public void save(Album album) { + albumRepository.save(album); + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/ArtistService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/ArtistService.java new file mode 100644 index 0000000..1497cb9 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/ArtistService.java @@ -0,0 +1,30 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Artist; +import VanquishP2.Application.Beans.Repos.ArtistRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class ArtistService { + private final ArtistRepository artistRepository; + + @Autowired + public ArtistService(ArtistRepository artistRepository) { + this.artistRepository = artistRepository; + } + + public void save(Artist artist){ + artistRepository.save(artist); + } + + public Artist getArtist(Integer id){ + return artistRepository.getById(id); + } + + public Artist getArtistByName(String name){ + return artistRepository.findByName(name); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/ConcertService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/ConcertService.java new file mode 100644 index 0000000..d174b99 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/ConcertService.java @@ -0,0 +1,40 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Concert; +import VanquishP2.Application.Beans.Repos.ConcertRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +public class ConcertService { + private final ConcertRepository concertRepository; + + @Autowired + public ConcertService(ConcertRepository concertRepository) { + this.concertRepository = concertRepository; + } + + public void save(Concert concert){ + concertRepository.save(concert); + } + + public Concert getConcert(Integer id){ + return concertRepository.getById(id); + } + + public List getConcertList(){ + return concertRepository.findAll(); + } + + public void deleteConcert(Concert concert) { + concertRepository.delete(concert); + } + + public void deleteAllConcerts() { + concertRepository.deleteAll(); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/GenreService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/GenreService.java new file mode 100644 index 0000000..3d462d3 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/GenreService.java @@ -0,0 +1,26 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Genre; +import VanquishP2.Application.Beans.Repos.GenreRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class GenreService { + private final GenreRepository repo; + + @Autowired + public GenreService(GenreRepository repo){ + this.repo = repo; + } + + public void save(Genre genre){ + repo.save(genre); + } + + public Genre getGenre(Integer id){ + return repo.getById(id); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/LikeDislikeService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/LikeDislikeService.java new file mode 100644 index 0000000..322916c --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/LikeDislikeService.java @@ -0,0 +1,57 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Application.Beans.Repos.TrackRepository; +import VanquishP2.Application.Beans.Repos.UserInfoRepository; +import VanquishP2.Application.Beans.Repos.UserRepository; +import VanquishP2.Exceptions.UserDoesNotExistException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Optional; + +@Service +@Transactional +public class LikeDislikeService { + private final TrackRepository trackRepository; + private final UserRepository userRepository; + private final UserInfoRepository userInfoRepository; + private final String exceptionError = "User: %s does not exist."; + + @Autowired + public LikeDislikeService(TrackRepository trackRepository, UserRepository userRepository, UserInfoRepository userInfoRepository){ + this.trackRepository = trackRepository; + this.userRepository = userRepository; + this.userInfoRepository = userInfoRepository; + } + + public void saveTrack(Track track){ + trackRepository.save(track); + } + + public Track getTrack(Integer id){ + return trackRepository.getById(id); + } + + public void saveUser(User user) + { + userRepository.save(user); + } + + public User getUser(Integer id) + { + return userRepository.getById(id); + } + + public Optional getUserByUsername(String username) throws UserDoesNotExistException + { + Optional optionalUserInfo = userInfoRepository.findByUsername(username); + return optionalUserInfo + .map(userInfo -> userRepository.findUserByUserInfo(userInfo) + .orElseThrow(() -> new UserDoesNotExistException(String.format(exceptionError, username)))); + + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/LocationService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/LocationService.java new file mode 100644 index 0000000..f80cae2 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/LocationService.java @@ -0,0 +1,54 @@ +package VanquishP2.Application.Beans.ModelServices; + + +import VanquishP2.Application.Beans.Models.Location; +import VanquishP2.Application.Beans.Repos.LocationRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +public class LocationService { + private final LocationRepository locationRepository; + + @Autowired + public LocationService(LocationRepository locationRepository){ + this.locationRepository = locationRepository; + } + + public Location saveLocation(Location location){ + locationRepository.save(location); + return locationRepository.getById(location.getLocationID()); + } + + // Kollier added this + public List getAll(){ + return locationRepository.findAll(); + } + + public Location getLocationById(Integer id){ + return locationRepository.getById(id); + } + + public void save(Location location) { + locationRepository.save(location); + } + + public void deleteLocationById(Integer id){ + locationRepository.delete(locationRepository.getById(id)); + } + + public void deleteLocation(Location location){ + locationRepository.delete(location); + } + + /** + * To reset DB data if necessary + */ + public void deleteAllLocations(){ + locationRepository.deleteAll(); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/LoggerService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/LoggerService.java new file mode 100644 index 0000000..37756f7 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/LoggerService.java @@ -0,0 +1,31 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Logger; +import VanquishP2.Application.Beans.Repos.LoggerRepo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.text.SimpleDateFormat; + +@Service +@Transactional +public class LoggerService { + private final LoggerRepo repo; + + @Autowired + public LoggerService(LoggerRepo repo) { + this.repo = repo; + } + + public void writeLog(String message, int level) { + Logger logger = new Logger(getCurrentDateTime(), message, level); + + repo.save(logger); + } + + private String getCurrentDateTime() { + SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + return formatter.format(System.currentTimeMillis()); + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/PlaylistService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/PlaylistService.java new file mode 100644 index 0000000..d370473 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/PlaylistService.java @@ -0,0 +1,24 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Playlist; +import VanquishP2.Application.Beans.Repos.PlaylistRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class PlaylistService { + private PlaylistRepository repo; + + @Autowired + public PlaylistService(PlaylistRepository repo){ + this.repo = repo; + } + public void save(Playlist playlist){ + repo.save(playlist); + } + public Playlist getPlaylist_name (Integer playlist_id){ + return repo.getById(playlist_id); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/TrackService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/TrackService.java new file mode 100644 index 0000000..79fcaf0 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/TrackService.java @@ -0,0 +1,31 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Repos.TrackRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class TrackService { + private final TrackRepository repo; + + @Autowired + public TrackService(TrackRepository repo){ + this.repo = repo; + } + + public void save(Track track){ + repo.save(track); + } + + public Track getTrack(Integer id){ + return repo.getById(id); + } + + public boolean trackExists(Integer id) + { + return repo.existsById(id); + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/UserInfoService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/UserInfoService.java new file mode 100644 index 0000000..9441dde --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/UserInfoService.java @@ -0,0 +1,105 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Application.Beans.Repos.UserInfoRepository; +import VanquishP2.Exceptions.UserDoesNotExistException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.LinkedList; +import java.util.List; +import java.util.Optional; + +@Service +@Transactional +public class UserInfoService { + private final UserInfoRepository userInfoRepository; + private final String exceptionError = "User: %s does not exist."; + + @Autowired + public UserInfoService(UserInfoRepository userInfoRepository) { + this.userInfoRepository = userInfoRepository; + } + + public UserInfo saveUserInfo(UserInfo userInfo){ + userInfoRepository.save(userInfo); + return userInfoRepository.getById(userInfo.getID()); + } + + public UserInfo getUserInfoById(Integer id){ + return userInfoRepository.getById(id); + } + + public String getEmailById(Integer id){ + UserInfo info = userInfoRepository.getById(id); + return info.getEmail(); + } + + public String getUsernameById(Integer id){ + UserInfo info = userInfoRepository.getById(id); + return info.getUsername(); + } + + public String getPasswordById(Integer id){ + UserInfo info = userInfoRepository.getById(id); + return info.getPassword(); + } + + public List getLoginById(Integer id){ + UserInfo info = userInfoRepository.getById(id); + List login = new LinkedList<>(); + login.add(info.getUsername()); + login.add(info.getPassword()); + return login; + } + + public UserInfo getByFirstName(String firstName) { + return userInfoRepository.findByFirstName(firstName).get(); + } + + public void save(UserInfo userInfo) { + userInfoRepository.save(userInfo); + } + + public void deleteUserInfo(UserInfo info){ + userInfoRepository.delete(info); + } + + /** + * To reset DB data if necessary + */ + public void deleteAllInfo(){ + userInfoRepository.deleteAll(); + } + + /** + * This method fetches all User Info in the DB + * @author Kollier Martin + * @date 11/8/2021 + * @return List of users present in DB + */ + public List getAll() { + return userInfoRepository.findAll(); + } + + /** + * Authenticate User + * @date 11/8/2021 + * @author Kollier Martin + * @param username Username + * @param password Password + * @return User Info, either null or not null + */ + public Optional authenticate(String username, String password) throws UserDoesNotExistException { + Optional userInfo; + + userInfo = userInfoRepository.findByUsernameAndPassword(username, password); + + if (!userInfo.isPresent()) { + throw new UserDoesNotExistException(exceptionError); + } + + return userInfo; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/ModelServices/UserService.java b/src/main/java/VanquishP2/Application/Beans/ModelServices/UserService.java new file mode 100644 index 0000000..85623ec --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/ModelServices/UserService.java @@ -0,0 +1,119 @@ +package VanquishP2.Application.Beans.ModelServices; + +import VanquishP2.Application.Beans.Models.Location; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Application.Beans.Repos.LocationRepository; +import VanquishP2.Application.Beans.Repos.UserInfoRepository; +import VanquishP2.Application.Beans.Repos.UserRepository; +import VanquishP2.DTOs.UserRegistrationDTO; +import VanquishP2.Exceptions.UserDoesNotExistException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; + +/** + * This service bean is used to talk to its designated repository and handle data retrieval + * + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Service +@Transactional +public class UserService { + private final UserRepository userRepository; + private final UserInfoRepository userInfoRepository; + private final LocationRepository locationRepository; + private final String exceptionError = "User: %s does not exist."; + + @Autowired + public UserService(UserRepository userRepository, + UserInfoRepository userInfoRepository, + LocationRepository locationRepository) { + this.userRepository = userRepository; + this.userInfoRepository = userInfoRepository; + this.locationRepository = locationRepository; + } + + /** + * This method fetches all Users in the DB + * @return List of users present in DB + */ + public List getAllUsers(){ + return userRepository.findAll(); + } + + /** + * This method fetches User by ID + * @param ID User ID + * @return User object + */ + public User getByID(int ID) throws UserDoesNotExistException { + User user; + + user = userRepository.findByID(ID) + .orElseThrow(() -> new UserDoesNotExistException(String.format(exceptionError, ID))); + + + return user; + } + + /** + * This method fetches a User based on UserInfo + * @param userInfo UserInfo object + * @return User object + */ + public User getByUserInfo(UserInfo userInfo) { + User user; + + user = userRepository.findUserByUserInfo(userInfo) + .orElseThrow(() -> new UserDoesNotExistException(String.format(exceptionError, userInfo))); + + return user; + } + + /** + * Persist User to DB + * @param user User Object + * @return Persisted User Object + */ + public void save(User user) { + userRepository.save(user); + } + + /** + * Delete User by ID + * @param id User ID + * @return User of the specific ID + */ + public void delete(int id) throws UserDoesNotExistException { + userRepository.deleteByID(id); + } + + /** + * Register New User + * @param data UserRegistration data to persist + * @return The new persisted Object + */ + public User registerUser(UserRegistrationDTO data, User.Role role) { + User newUser; + UserInfo newUserInfo; + Location location; + + location = new Location(data.getCity(), data.getState()); + newUserInfo = new UserInfo(data); + newUser = new User(role, newUserInfo); + + locationRepository.save(location); + userRepository.save(newUser); + + newUserInfo.setLocation(location); + newUserInfo.setUser(newUser); + userInfoRepository.save(newUserInfo); + + return newUser; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Album.java b/src/main/java/VanquishP2/Application/Beans/Models/Album.java new file mode 100644 index 0000000..e0a992c --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Album.java @@ -0,0 +1,90 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to declare the POJO, Album + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Table(name = "ALBUMS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, ignoreUnknown = true) +public class Album implements Serializable { + public Album() { + tracks = new ArrayList<>(); + } + + @Id + @Column(name = "AlbumID") + private Integer albumID; + public Integer getAlbumID() { + return albumID; + } + public void setAlbumID(Integer ID) { + this.albumID = ID; + } + + @Column(name = "AlbumTitle") + private String albumTitle; + public String getAlbumTitle() { + return albumTitle; + } + public void setAlbumTitle(String albumTitle) { + this.albumTitle = albumTitle; + } + + @Column(name = "ReleaseDate") + private String date; + public String getDate() { + return date; + } + public void setDate(String date) { + this.date = date; + } + + @ManyToOne + private Artist artist; + public Artist getArtist() { + return artist; + } + public void setArtist(Artist artist) { + this.artist = artist; + } + + @OneToMany + private List tracks; + public List getTracks() { + return tracks; + } + public void setTracks(List tracks) { + this.tracks = tracks; + } + + @ManyToOne + private Genre genre; + public Genre getGenre() { + return genre; + } + public void setGenre(Genre genre) { + this.genre = genre; + } + + @Override + public String toString() { + return "Album {\n" + + "ID: " + albumID + ",\n" + + "albumTitle: " + albumTitle + ",\n" + + "date: " + date + ",\n" + + "artist: " + artist + ",\n" + + "tracks: " + tracks + ",\n" + + "genre: " + genre + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Artist.java b/src/main/java/VanquishP2/Application/Beans/Models/Artist.java new file mode 100644 index 0000000..7083cb7 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Artist.java @@ -0,0 +1,105 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to declare the POJO, Artist + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Table(name = "ARTISTS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, ignoreUnknown = true) +public class Artist { + public Artist() { + tracks = new ArrayList<>(); + albums = new ArrayList<>(); + concerts = new ArrayList<>(); + } + + public Artist(String name) { + this.name = name; + tracks = new ArrayList<>(); + albums = new ArrayList<>(); + concerts = new ArrayList<>(); + } + + public Artist(String name, int artistID, String imageURL) { + this.name = name; + this.artistID = artistID; + this.imageURL = imageURL; + } + + @Id + @Column(name = "ArtistID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int artistID; + public int getID() { + return artistID; + } + public void setID(int artistID) { + this.artistID = artistID; + } + + @Column(name = "Name") + private String name; + public String getName() { + return name; + } + public void setName(String name) { + this.name = name; + } + + @Column(name = "Picture") + private String imageURL; + public String getImageURL() { + return imageURL; + } + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + @ManyToMany + List concerts; + public List getConcerts() { + return concerts; + } + public void setConcerts(List concerts) { + this.concerts = concerts; + } + + @OneToMany(mappedBy = "artist") + List albums; + public List getAlbums() { + return albums; + } + public void setAlbums(List albums) { + this.albums = albums; + } + + @OneToMany + List tracks; + public List getTracks() { + return tracks; + } + public void setTracks(List tracks) { + this.tracks = tracks; + } + + @Override + public String toString() { + return "Artist {\n" + + "artistID: " + artistID + ",\n" + + "name: " + name + ",\n" + + "imageURL: " + imageURL + ",\n" + + "concerts: " + concerts + ",\n" + + "albums: " + albums + ",\n" + + "tracks: " + tracks + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Concert.java b/src/main/java/VanquishP2/Application/Beans/Models/Concert.java new file mode 100644 index 0000000..bb47d98 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Concert.java @@ -0,0 +1,60 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to declare the POJO, Concert + * @date 11/01/2021 + * @author Kollier Martin + */ + +@Table(name = "CONCERTS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, ignoreUnknown = true) +public class Concert { + public Concert() { + artists = new ArrayList<>(); + } + + @Id + @Column(name = "ConcertID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + public Integer getID() { + return ID; + } + public void setID(Integer ID) { + this.ID = ID; + } + + @Column(name = "Location") + private String location; + public String getLocation() { + return location; + } + public void setLocation(String location) { + this.location = location; + } + + @ManyToMany(mappedBy = "concerts") + List artists; + public List getArtists() { + return artists; + } + public void setArtists(List artists) { + this.artists = artists; + } + + @Override + public String toString() { + return "Concert {\n" + + "ID: " + ID + ",\n" + + "location: " + location + ",\n" + + "artists: " + artists + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Genre.java b/src/main/java/VanquishP2/Application/Beans/Models/Genre.java new file mode 100644 index 0000000..70b65ae --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Genre.java @@ -0,0 +1,70 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +@Table(name = "GENRES") +@Entity +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) +public class Genre { + public Genre() { + albumsOfGenre = new ArrayList<>(); + } + + public Genre(Integer genreID, String genreName, String imageURL) { + albumsOfGenre = new ArrayList<>(); + this.genreID = genreID; + this.genreName = genreName; + this.imageURL = imageURL; + } + + @Id + @Column + private Integer genreID; + public Integer getGenreID() { + return genreID; + } + public void setGenreID(Integer genreID) { + this.genreID = genreID; + } + + @Column + private String genreName; + public String getGenreName() { + return genreName; + } + public void setGenreName(String genreName) { + this.genreName = genreName; + } + + @Column + private String imageURL; + public String getImageURL() { + return imageURL; + } + public void setImageURL(String imageURL) { + this.imageURL = imageURL; + } + + @OneToMany + private List albumsOfGenre; + public List getAlbumsOfGenre() { + return albumsOfGenre; + } + public void setAlbumsOfGenre(List albumsOfGenre) { + this.albumsOfGenre = albumsOfGenre; + } + + @Override + public String toString() { + return "Genre {\n" + + "genreID: " + genreID + ",\n" + + "genreName: " + genreName + ",\n" + + "imageURL: " + imageURL + ",\n" + + "albumsOfGenre: " + albumsOfGenre + ",\n" + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Location.java b/src/main/java/VanquishP2/Application/Beans/Models/Location.java new file mode 100644 index 0000000..c6a6f72 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Location.java @@ -0,0 +1,68 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.List; + +@Table(name = "LOCATIONS") +@Entity +@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"}) +public class Location { + public Location(String city, String state) { + this.city = city; + this.state = state; + } + + public Location() { + + } + + @Id + @Column + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer locationID; + public Integer getLocationID() { + return locationID; + } + public void setLocationID(Integer location_id) { + this.locationID = location_id; + } + + @Column + private String city; + public String getCity() { + return city; + } + public void setCity(String city) { + this.city = city; + } + + @Column + private String state; + public String getState() { + return state; + } + public void setState(String state) { + this.state = state; + } + + @OneToMany(mappedBy = "location") + private List userLocations; + public List getUserInfo() { + return userLocations; + } + public void setUserInfo(List userLocations) { + this.userLocations = userLocations; + } + + @Override + public String toString() { + return "Location {\n" + + "locationID: " + locationID + ",\n" + + "city: " + city + ",\n" + + "state: " + state + ",\n" + + "userLocations: " + userLocations + ",\n" + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Logger.java b/src/main/java/VanquishP2/Application/Beans/Models/Logger.java new file mode 100644 index 0000000..3722b51 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Logger.java @@ -0,0 +1,54 @@ +package VanquishP2.Application.Beans.Models; + +import javax.persistence.*; + +@Entity +public class Logger { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + public Integer getId() { + return id; + } + public void setId(Integer id) { + this.id = id; + } + + @Column + private Integer warningLevel; + public Integer getWarningLevel() { + return warningLevel; + } + public void setWarningLevel(Integer warningLevel) { + this.warningLevel = warningLevel; + } + + @Column + private String dataTime; + public String getDataTime() { + return dataTime; + } + public void setDataTime(String dataTime) { + this.dataTime = dataTime; + } + + @Column(columnDefinition = "varchar(20000)") + private String message; + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + + public Logger() { + + } + + public Logger(String dataTime, String message, Integer warningLevel) { + this.dataTime = dataTime; + this.message = message; + this.warningLevel = warningLevel; + } + +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Playlist.java b/src/main/java/VanquishP2/Application/Beans/Models/Playlist.java new file mode 100644 index 0000000..2a3953e --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Playlist.java @@ -0,0 +1,76 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to declare the POJO, Playlist + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Table(name = "PLAYLISTS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, ignoreUnknown = true) +public class Playlist { + public Playlist() { + trackList = new ArrayList<>(); + } + + public Playlist(String playlistName, User user, List trackList) { + this.playlistName = playlistName; + this.user = user; + this.trackList = trackList; + } + + @Id + @Column(name = "PlaylistID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + public Integer getID() { + return ID; + } + public void setID(Integer ID) { + this.ID = ID; + } + + @Column(name = "PlaylistName") + private String playlistName; + public String getPlaylistName() { + return playlistName; + } + public void setPlaylistName(String playlistName) { + this.playlistName = playlistName; + } + + @ManyToOne(cascade = CascadeType.ALL) + User user; + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } + + @ManyToMany + List trackList; + public List getTrackList() { + return trackList; + } + public void setTrackList(List tracks) { + this.trackList = tracks; + } + + @Override + public String toString() { + return "Playlist {\n" + + "ID: " + ID + ",\n" + + "playlistName: " + playlistName + ",\n" + + "user: " + user + ",\n" + + "tracks: " + trackList + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/Track.java b/src/main/java/VanquishP2/Application/Beans/Models/Track.java new file mode 100644 index 0000000..d758f6d --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/Track.java @@ -0,0 +1,127 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.List; + +/** + * This class is used to declare the POJO, Track + * @date 11/01/2021 + * @author Kollier Martin + */ + +@Table(name = "TRACKS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, ignoreUnknown = true) +public class Track { + public Track() { + + } + + public Track(Integer id, String title) { + this.trackID = id; + this.title = title; + } + + public Track(String title, String duration, Artist artist) { + this.title = title; + this.duration = duration; + this.artist = artist; + } + + @Id + @Column(name = "TrackID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer trackID; + public Integer getTrackID() { + return trackID; + } + public void setTrackID(Integer ID) { + this.trackID = ID; + } + + @Column(name = "Title") + private String title; + public String getTitle() { + return title; + } + public void setTitle(String title) { + this.title = title; + } + + @Column(name = "Duration") + private String duration; + public String getDuration() { + return duration; + } + public void setDuration(String duration) { + this.duration = duration; + } + + @ManyToOne + private Artist artist; + public Artist getArtist() { + return artist; + } + public void setArtist(Artist artist) { + this.artist = artist; + } + + @ManyToOne + private User user; + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } + + @ManyToOne + Album album; + public Album getAlbum() { + return album; + } + public void setAlbum(Album album) { + this.album = album; + } + + @ManyToMany(mappedBy = "trackList") + private List playlists; + public List getPlaylists() { + return playlists; + } + public void setPlaylists(List playlists) { + this.playlists = playlists; + } + + @ManyToMany(mappedBy = "likedTracks") + private List userLikes; + public List getUserLikes() { + return userLikes; + } + public void setUserLikes(List userLikes) { + this.userLikes = userLikes; + } + + @ManyToMany(mappedBy = "dislikedTracks") + private List userDislikes; + public List getUserDislikes() { + return userDislikes; + } + public void setUserDislikes(List userDislikes) { + this.userDislikes = userDislikes; + } + + @Override + public String toString() { + return "Track {\n" + + "ID: " + trackID + ",\n" + + "title: " + title + ",\n" + + "duration: " + duration + ",\n" + + "artist: " + artist + ",\n" + + "user: " + user + ",\n" + + "playlists: " + playlists + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/User.java b/src/main/java/VanquishP2/Application/Beans/Models/User.java new file mode 100644 index 0000000..6e96a83 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/User.java @@ -0,0 +1,116 @@ +package VanquishP2.Application.Beans.Models; + +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; +import java.util.ArrayList; +import java.util.List; + +/** + * This class is used to declare the POJO, User + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Table(name = "USERS") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler"}, + ignoreUnknown = true) +public class User { + public User() { + this.role = Role.BASIC; + this.myPlaylists = new ArrayList<>(); + this.favorites = new ArrayList<>(); + this.likedTracks = new ArrayList<>(); + this.dislikedTracks = new ArrayList<>(); + this.userInfo = null; + } + + public User(Role role, UserInfo userInfo) { + this.role = role; + this.myPlaylists = new ArrayList<>(); + this.likedTracks = new ArrayList<>(); + this.dislikedTracks = new ArrayList<>(); + this.favorites = new ArrayList<>(); + this.userInfo = userInfo; + } + + @Id + @Column(name = "UserID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer ID; + public Integer getID() { + return ID; + } + public void setID(Integer ID) { + this.ID = ID; + } + + @Enumerated + private Role role; + public enum Role { + BASIC, + PREMIUM + } + public Role getRole() { + return role; + } + public void setRole(Role role) { + this.role = role; + } + + @OneToMany(mappedBy = "user") + private List myPlaylists; + public List getMyPlaylists() { + return myPlaylists; + } + public void setMyPlaylists(List myPlaylists) { + this.myPlaylists = myPlaylists; + } + + @OneToMany(mappedBy = "user") + private List favorites; + public List getFavorites() { + return favorites; + } + public void setFavorites(List favorites) { + this.favorites = favorites; + } + + @OneToOne(mappedBy = "user") + private UserInfo userInfo; + public UserInfo getUserInfo() { + return userInfo; + } + public void setUserInfo(UserInfo userInfo) { + this.userInfo = userInfo; + } + + @ManyToMany + private List likedTracks; + public List getLikedTracks() { + return likedTracks; + } + public void setLikedTracks(List likedTracks) { + this.likedTracks = likedTracks; + } + + @ManyToMany + private List dislikedTracks; + public List getDislikedTracks() { + return dislikedTracks; + } + public void setDislikedTracks(List dislikedTracks) { + this.dislikedTracks = dislikedTracks; + } + + @Override + public String toString() { + return "User {\n" + + "ID: " + ID + ",\n" + + "role: " + role + ",\n" + + "myPlaylists: " + myPlaylists + ",\n" + + "favorites: " + favorites + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Models/UserInfo.java b/src/main/java/VanquishP2/Application/Beans/Models/UserInfo.java new file mode 100644 index 0000000..cf962c2 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Models/UserInfo.java @@ -0,0 +1,135 @@ +package VanquishP2.Application.Beans.Models; + +import VanquishP2.DTOs.UserRegistrationDTO; +import com.fasterxml.jackson.annotation.JsonIgnoreProperties; + +import javax.persistence.*; + +/** + * This class is used to declare the POJO, UserInfo + * @date 10/29/2021 + * @author Kollier Martin + */ + +@Table(name = "USERINFO") +@Entity +@JsonIgnoreProperties(value = {"hibernateLazyInitializer", "handler", "location", "user"}, + ignoreUnknown = true) +public class UserInfo { + public UserInfo() { + + } + + public UserInfo(String email, String username, String password) { + this.email = email; + this.username = username; + this.password = password; + } + + public UserInfo(Location location, String firstName, String lastName, String username, String password, String email, User user) + { + this.location = location; + this.firstName = firstName; + this.lastName = lastName; + this.username = username; + this.password = password; + this.email = email; + this.user = user; + } + + public UserInfo(UserRegistrationDTO registration) { + this.location = new Location(registration.getCity(), registration.getState()); + this.firstName = registration.getFirstName(); + this.lastName = registration.getLastName(); + this.username = registration.getUsername(); + this.password = registration.getPassword(); + this.email = registration.getEmail(); + } + + @Id + @Column(name = "UserInfoID") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private int ID; + public int getID() { + return ID; + } + public void setID(int ID) { + this.ID = ID; + } + + @Column(name = "FirstName") + private String firstName; + public String getFirstName() { + return firstName; + } + public void setFirstName(String username) { + this.firstName = username; + } + + @Column(name = "LastName") + private String lastName; + public String getLastName() { + return lastName; + } + public void setLastName(String lastName) { + this.lastName = lastName; + } + + @Column(name = "Email") + private String email; + public String getEmail() { + return email; + } + public void setEmail(String email) { + this.email = email; + } + + @Column(name = "Username") + private String username; + public String getUsername() { + return username; + } + public void setUsername(String username) { + this.username = username; + } + + @Column(name = "Password", nullable = false) + private String password; + public String getPassword(){ + return password; + } + public void setPassword(String password) { + this.password = password; + } + + @ManyToOne(cascade = CascadeType.REMOVE) + private Location location; + public Location getLocation() { + return location; + } + public void setLocation(Location location) { + this.location = location; + } + + @OneToOne(cascade = CascadeType.REMOVE) + User user; + public User getUser() { + return user; + } + public void setUser(User user) { + this.user = user; + } + + @Override + public String toString() { + return "UserInfo {\n" + + "ID: " + ID + ",\n" + + "firstName: " + firstName + ",\n" + + "lastName: " + lastName + ",\n" + + "email: " + email + ",\n" + + "username: " + username + ",\n" + + "password: " + password + ",\n" + + "location: " + location + ",\n" + + '}'; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/AlbumRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/AlbumRepository.java new file mode 100644 index 0000000..00cb5dc --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/AlbumRepository.java @@ -0,0 +1,15 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Album; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface AlbumRepository extends JpaRepository { + void deleteByAlbumID(Integer integer); + void deleteByAlbumTitle(String title); + Optional getAlbumByAlbumTitle(String name); + Optional findByAlbumID(Integer id); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/ArtistRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/ArtistRepository.java new file mode 100644 index 0000000..2737ae8 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/ArtistRepository.java @@ -0,0 +1,10 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Artist; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ArtistRepository extends JpaRepository { + Artist findByName(String name); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/ConcertRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/ConcertRepository.java new file mode 100644 index 0000000..a389367 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/ConcertRepository.java @@ -0,0 +1,12 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Concert; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface ConcertRepository extends JpaRepository { + Optional findByID(int ID); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/GenreRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/GenreRepository.java new file mode 100644 index 0000000..a1d1d58 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/GenreRepository.java @@ -0,0 +1,10 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Genre; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface GenreRepository extends JpaRepository { + +} diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/LocationRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/LocationRepository.java new file mode 100644 index 0000000..4eb858d --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/LocationRepository.java @@ -0,0 +1,9 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Location; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface LocationRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/LoggerRepo.java b/src/main/java/VanquishP2/Application/Beans/Repos/LoggerRepo.java new file mode 100644 index 0000000..64e2a03 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/LoggerRepo.java @@ -0,0 +1,10 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Logger; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface LoggerRepo extends JpaRepository{ + +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/PlaylistRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/PlaylistRepository.java new file mode 100644 index 0000000..d0853c7 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/PlaylistRepository.java @@ -0,0 +1,11 @@ +package VanquishP2.Application.Beans.Repos; + + +import VanquishP2.Application.Beans.Models.Playlist; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface PlaylistRepository extends JpaRepository { + +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/TrackRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/TrackRepository.java new file mode 100644 index 0000000..174897d --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/TrackRepository.java @@ -0,0 +1,12 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.Track; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface TrackRepository extends JpaRepository { + Optional findByTrackID(int ID); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/UserInfoRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/UserInfoRepository.java new file mode 100644 index 0000000..8d0063d --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/UserInfoRepository.java @@ -0,0 +1,14 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.UserInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface UserInfoRepository extends JpaRepository { + Optional findByUsernameAndPassword(String username, String password); + Optional findByUsername(String username); + Optional findByFirstName(String firstName); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Repos/UserRepository.java b/src/main/java/VanquishP2/Application/Beans/Repos/UserRepository.java new file mode 100644 index 0000000..41642d0 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Repos/UserRepository.java @@ -0,0 +1,15 @@ +package VanquishP2.Application.Beans.Repos; + +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +@Repository +public interface UserRepository extends JpaRepository { + Optional findByID(int ID); + Optional findUserByUserInfo(UserInfo userInfo); + void deleteByID(Integer ID); +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Application/Beans/Service/APIClientService.java b/src/main/java/VanquishP2/Application/Beans/Service/APIClientService.java new file mode 100644 index 0000000..b9806ad --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Service/APIClientService.java @@ -0,0 +1,26 @@ +package VanquishP2.Application.Beans.Service; + +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; + +import java.io.IOException; + +public class APIClientService { + private static final OkHttpClient apiClient = new OkHttpClient(); + + public static String get(String url) { + Request req = new Request.Builder().url(url).build(); + + try(Response response = apiClient.newCall(req).execute()) + { + return response.body().string(); + } + catch(IOException e) + { + //TODO: Set up file logger or AOP logging and invoke here instead of stack trace. + e.printStackTrace(); + } + return null; + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Service/JWTUtil.java b/src/main/java/VanquishP2/Application/Beans/Service/JWTUtil.java new file mode 100644 index 0000000..cac77e4 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Service/JWTUtil.java @@ -0,0 +1,89 @@ +package VanquishP2.Application.Beans.Service; + +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Exceptions.AuthenticationException; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.security.Keys; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.sql.Date; + +/** + * JWTUtil + * Class used for the creation/parsing of JWTs + * @author Kollier Martin + * @date 11/1/2021 + */ +@Component +public class JWTUtil { + + @Value("${jwt.header}") + private String header; + + @Value("${jwt.prefix}") + private String prefix; + + @Value("#{24*60*60*1000}") + private int expiration; + + private Key key; + + public JWTUtil(){ + createKey(); + } + + private void createKey(){ + key = Keys.secretKeyFor(SignatureAlgorithm.HS256); + } + + public String createJWT(UserInfo userInfo){ + return Jwts.builder() + .setIssuer("Vanquish") + .setSubject(userInfo.getUsername()) + .signWith(key) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .compact(); + } + + public Claims parseJWT(String token) throws AuthenticationException { + return Jwts.parserBuilder() // Creates parser instance + .setSigningKey(key) // Specify the key to verify this jws signature + .build() // Returns a new, thread-safe, parser + .parseClaimsJws(token) + .getBody(); + } + + public String getHeader() { + return header; + } + + public String getPrefix() { + return prefix; + } + + public int getExpiration() { + return expiration; + } + + public Key getKey() { + return key; + } + + @Override + public String toString() { + return "JWTUtil {\n" + + "header: " + header + ",\n" + + "prefix: " + prefix + ",\n" + + "expiration: " + expiration + ",\n" + + "key: " + key + ",\n" + + '}'; + } + + public void printVars(){ + System.out.println(this); + } +} diff --git a/src/main/java/VanquishP2/Application/Beans/Service/ServiceRequests.java b/src/main/java/VanquishP2/Application/Beans/Service/ServiceRequests.java new file mode 100644 index 0000000..7ec3bed --- /dev/null +++ b/src/main/java/VanquishP2/Application/Beans/Service/ServiceRequests.java @@ -0,0 +1,47 @@ +package VanquishP2.Application.Beans.Service; + +import org.springframework.stereotype.Service; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; + +/** + * This class is used to record every request made in a single session. + * + * @author Kollier Martin + */ +@Service +public abstract class ServiceRequests { + private int requestCount = 0; + private final ArrayList requestLog = new ArrayList<>(); + + public void writeSummary() throws IOException { + SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z"); + Date date = new Date(System.currentTimeMillis()); + + File file = new File("requestLog.log"); + FileWriter fileWriter = new FileWriter(file); + BufferedWriter out = new BufferedWriter(fileWriter); + + out.write("There were " + requestCount + " requests in session: " + formatter.format(date)); + out.newLine(); + for (String request : requestLog) { + out.write(request); + out.newLine(); + } + + System.out.println("Request Summary has been written to designated to file."); + } + + public void addRequest(String requestInfo){ + SimpleDateFormat formatter= new SimpleDateFormat("HH:mm:ss z"); + + requestCount++; + requestLog.add(requestInfo + " " + formatter.format(new Date(System.currentTimeMillis()))); + } +} diff --git a/src/main/java/VanquishP2/Application/Config/FilterConfig.java b/src/main/java/VanquishP2/Application/Config/FilterConfig.java new file mode 100644 index 0000000..aff6c34 --- /dev/null +++ b/src/main/java/VanquishP2/Application/Config/FilterConfig.java @@ -0,0 +1,31 @@ +package VanquishP2.Application.Config; + +import VanquishP2.Application.Beans.Filters.AuthenticationFilter; +import VanquishP2.Application.Beans.Filters.CORSFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Collections; + +@Configuration +public class FilterConfig { + + @Bean + @SuppressWarnings({"rawtypes, unchecked"}) + public FilterRegistrationBean authRegistrationBean() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); + filterRegistrationBean.setFilter(new AuthenticationFilter()); + filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*")); + return filterRegistrationBean; + } + + @Bean + @SuppressWarnings({"rawtypes, unchecked"}) + public FilterRegistrationBean corsRegistrationBean() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); + filterRegistrationBean.setFilter(new CORSFilter()); + filterRegistrationBean.setUrlPatterns(Collections.singletonList("/*")); + return filterRegistrationBean; + } +} diff --git a/src/main/java/VanquishP2/Application/P2Application.java b/src/main/java/VanquishP2/Application/P2Application.java new file mode 100644 index 0000000..77a62a7 --- /dev/null +++ b/src/main/java/VanquishP2/Application/P2Application.java @@ -0,0 +1,17 @@ +package VanquishP2.Application; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.domain.EntityScan; +import org.springframework.context.annotation.PropertySource; + +@SpringBootApplication(scanBasePackages = "VanquishP2") +@EntityScan("VanquishP2.Application.Beans.Models") +@PropertySource(value = "classpath:application.properties") +public class P2Application { + + public static void main(String[] args) { + SpringApplication.run(P2Application.class, args); + } + +} diff --git a/src/main/java/Application/ServletInitializer.java b/src/main/java/VanquishP2/Application/ServletInitializer.java similarity index 92% rename from src/main/java/Application/ServletInitializer.java rename to src/main/java/VanquishP2/Application/ServletInitializer.java index 31c43b5..6993336 100644 --- a/src/main/java/Application/ServletInitializer.java +++ b/src/main/java/VanquishP2/Application/ServletInitializer.java @@ -1,4 +1,4 @@ -package Application; +package VanquishP2.Application; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; diff --git a/src/main/java/VanquishP2/Controllers/AlbumController.java b/src/main/java/VanquishP2/Controllers/AlbumController.java new file mode 100644 index 0000000..85567b4 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/AlbumController.java @@ -0,0 +1,104 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.AlbumService; +import VanquishP2.Application.Beans.Models.Album; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; +import java.util.Optional; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +/** + * AlbumController + * Handles requests that involve the manipulating or retrieval of album data + * + * @date 11/3/2021 + * @author Kollier Martin + */ + +@RestController +@RequestMapping(value = "/4TheMusic", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) +public class AlbumController { + private final AlbumService albumService; + + @Autowired + public AlbumController(AlbumService albumService) { + this.albumService = albumService; + } + + /** + * This functions returns all albums cached into DB + * @return ResponseEntity with HttpStatus and/or content + */ + @GetMapping("/album/all") + public ResponseEntity> getAllAlbums() { + List allAlbums = albumService.getAll(); + + if (allAlbums == null) + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + else if (allAlbums.isEmpty()) + return new ResponseEntity<>(allAlbums, HttpStatus.NO_CONTENT); + else + return new ResponseEntity<>(allAlbums, HttpStatus.OK); + } + + /** + * Receives ID from request, then returns an Album object if they exist + * @param id ID Integer to distinguish album + * @return Album Object + */ + @GetMapping("/album/{id}") + @ResponseStatus(HttpStatus.ACCEPTED) + public Album retrieve(@PathVariable int id) { + return albumService.getByID(id); + } + + /** + * Receives name from request, then returns an Album object if they exist + * @param name Name String to distinguish album + * @return Album Object + */ + @GetMapping("/album/{name}") + @ResponseStatus(HttpStatus.ACCEPTED) + public Album retrieve(@PathVariable String name) { + return albumService.getByTitle(name); + } + + /** + * Deletes an Album from the DB, if it exists + * @param id Album ID + * @return ResponseEntity depending on success or failure + */ + @DeleteMapping("/album{/id}") + public ResponseEntity remove(@PathVariable int id) { + Optional album = Optional.ofNullable(albumService.getByID(id)); + + if (!album.isPresent()) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } else { + albumService.delete(id); + return new ResponseEntity<>(album.get(), HttpStatus.NO_CONTENT); + } + } + + /** + * Deletes an Album from the DB, if it exists + * @param title Album title + * @return ResponseEntity depending on success or failure + */ + @DeleteMapping("/album/{title}") + public ResponseEntity remove(@PathVariable String title) { + Optional album = Optional.ofNullable(albumService.getByTitle(title)); + + if (!album.isPresent()) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } else { + albumService.delete(album); + return new ResponseEntity<>(album.get(), HttpStatus.NO_CONTENT); + } + } +} diff --git a/src/main/java/VanquishP2/Controllers/ArtistController.java b/src/main/java/VanquishP2/Controllers/ArtistController.java new file mode 100644 index 0000000..61f55d3 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/ArtistController.java @@ -0,0 +1,33 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.ArtistService; +import VanquishP2.Application.Beans.Models.Artist; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/4TheMusic") +public class ArtistController { + + private final ArtistService artistService; + + @Autowired + public ArtistController(ArtistService artistService) { + this.artistService = artistService; + } + + @PostMapping(path = "/artist", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public Artist saveArtist(@RequestBody Artist artist) { + artistService.save(artist); + return artistService.getArtist(artist.getID()); + } + + @GetMapping(path = "/artist/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Artist getArtistById(@PathVariable("id") Integer id) { + return artistService.getArtist(id); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Controllers/AuthenticationController.java b/src/main/java/VanquishP2/Controllers/AuthenticationController.java new file mode 100644 index 0000000..064d986 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/AuthenticationController.java @@ -0,0 +1,98 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.UserInfoService; +import VanquishP2.Application.Beans.ModelServices.UserService; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Application.Beans.Service.JWTUtil; +import VanquishP2.DTOs.LoginCredentialsDTO; +import VanquishP2.DTOs.UserRegistrationDTO; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; +import java.util.Optional; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +/** + * + */ +@RestController +@RequestMapping("/4TheMusic") +public class AuthenticationController { + + private final JWTUtil jwtUtil; + private final UserInfoService userInfoService; + private final UserService userService; + + @Autowired + public AuthenticationController(JWTUtil jwtUtil, UserInfoService userInfoService, UserService userService) { + this.jwtUtil = jwtUtil; + this.userInfoService = userInfoService; + this.userService = userService; + } + + /** + * Authenticate and Login User + * @param credentials username and password + * @param response The HTTP Response + * @return The new user and their key + */ + @PostMapping(value = "/login", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public ResponseEntity authenticate(@RequestBody LoginCredentialsDTO credentials, HttpServletResponse response) { + System.out.println(credentials); + Optional userInfo = userInfoService.authenticate(credentials.getUsername(), credentials.getPassword()); + + if (userInfo.isPresent()) { + String jwt = jwtUtil.createJWT(userInfo.get()); + response.setHeader(jwtUtil.getHeader(), jwt); + return new ResponseEntity<>(userInfo.get(), HttpStatus.OK); + } else { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + } + + /** + * Register Basic User + * @param regData Registration Data from Frontend + * @return The new registered User Data + */ + @PostMapping(value = "/register/basic", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public ResponseEntity registerBasicUser(@RequestBody @Valid UserRegistrationDTO regData) { + User user = userService.registerUser(regData, User.Role.BASIC); + String jwt = jwtUtil.createJWT(user.getUserInfo()); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(jwtUtil.getHeader(), jwt); + + return ResponseEntity.ok() + .headers(responseHeaders) + .body(user); + } + + /** + * Register Premium User + * @param regData Registration Data from Frontend + * @return The new registered User Data + */ + @PostMapping(value = "/register/premium", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE) + public ResponseEntity registerPremiumUser(@RequestBody @Valid UserRegistrationDTO regData){ + User user = userService.registerUser(regData, User.Role.PREMIUM); + String jwt = jwtUtil.createJWT(user.getUserInfo()); + + HttpHeaders responseHeaders = new HttpHeaders(); + responseHeaders.add(jwtUtil.getHeader(), jwt); + + return ResponseEntity.ok() + .headers(responseHeaders) + .body(user); + } +} diff --git a/src/main/java/VanquishP2/Controllers/ConcertController.java b/src/main/java/VanquishP2/Controllers/ConcertController.java new file mode 100644 index 0000000..0f2e7d1 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/ConcertController.java @@ -0,0 +1,51 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.ConcertService; +import VanquishP2.Application.Beans.Models.Concert; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/4TheMusic") +public class ConcertController { + + private final ConcertService concertService; + + @Autowired + public ConcertController(ConcertService concertService) { + this.concertService = concertService; + } + + @PostMapping(path = "/concert", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public Concert saveConcert(@RequestBody Concert concert){ + concertService.save(concert); + return concertService.getConcert(concert.getID()); + } + + @GetMapping(path = "/concert/all", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.ACCEPTED) + public List concertList(){ + return concertService.getConcertList(); + } + + @GetMapping(path = "/concert/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Concert getConcertById(@PathVariable("id") Integer id){ + return concertService.getConcert(id); + } + + @DeleteMapping(value = "/concert/{id}") + @ResponseStatus(HttpStatus.OK) + public void deleteLocation(@PathVariable ("id") Integer id){ + if(id>0){ + concertService.deleteConcert(concertService.getConcert(id)); + }else{ + concertService.deleteAllConcerts(); + } + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Controllers/GenreController.java b/src/main/java/VanquishP2/Controllers/GenreController.java new file mode 100644 index 0000000..4178add --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/GenreController.java @@ -0,0 +1,34 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.GenreService; +import VanquishP2.Application.Beans.Models.Genre; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(value = "/4TheMusic") +public class GenreController { + private final GenreService genreService; + + @Autowired + public GenreController(GenreService genreService) + { + this.genreService = genreService; + } + + @PostMapping(value = "/genre", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public Genre saveGenre(@RequestBody Genre genre){ + genreService.save(genre); + return genreService.getGenre(genre.getGenreID()); + } + + @GetMapping(value = "/genre/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Genre getGenre(@PathVariable ("id") Integer id){ + return genreService.getGenre(id); + } + +} diff --git a/src/main/java/VanquishP2/Controllers/LikeDislikeController.java b/src/main/java/VanquishP2/Controllers/LikeDislikeController.java new file mode 100644 index 0000000..6ab5c65 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/LikeDislikeController.java @@ -0,0 +1,102 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.LikeDislikeService; +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Service.JWTUtil; +import VanquishP2.Exceptions.UserDoesNotExistException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletResponse; +import java.util.Optional; + +@RestController +@RequestMapping(value = "/4TheMusic") +public class LikeDislikeController { + private final LikeDislikeService likeDislikeService; + private final JWTUtil jwtUtil; + + @Autowired + public LikeDislikeController(JWTUtil jwtUtil, LikeDislikeService likeDislikeService) { + this.jwtUtil = jwtUtil; + this.likeDislikeService = likeDislikeService; + } + + @PostMapping(value = "/like", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Track likeTrack(@RequestBody Track track, HttpServletResponse response) throws UserDoesNotExistException { + String username = jwtUtil.parseJWT(response.getHeader(jwtUtil.getHeader())).getSubject(); + + Optional user = likeDislikeService.getUserByUsername(username); + + if(user.isPresent()) + { + Track serviceTrack = likeDislikeService.getTrack(track.getTrackID()); + if(serviceTrack != null) + { + serviceTrack.getUserLikes().add(user.get()); + likeDislikeService.saveTrack(serviceTrack); + } + else + { + track.getUserLikes().add(user.get()); + likeDislikeService.saveTrack(track); + } + + user.get().getLikedTracks().add(likeDislikeService.getTrack(track.getTrackID())); + likeDislikeService.saveUser(user.get()); + } + + return likeDislikeService.getTrack(track.getTrackID()); + } + + @PostMapping(value = "/dislike", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Track dislikeTrack(@RequestBody Track track, HttpServletResponse response) throws UserDoesNotExistException{ + String username = jwtUtil.parseJWT(response.getHeader(jwtUtil.getHeader())).getSubject(); + Optional user = likeDislikeService.getUserByUsername(username); + + if(user.isPresent()) + { + User presentUser = new User(user.get().getRole(), user.get().getUserInfo()); + Track database = likeDislikeService.getTrack(track.getTrackID()); + if(database != null) + { + database.getUserDislikes().add(presentUser); + likeDislikeService.saveTrack(database); + } + else + { + track.getUserDislikes().add(presentUser); + likeDislikeService.saveTrack(track); + } + + presentUser.getDislikedTracks().add(likeDislikeService.getTrack(track.getTrackID())); + likeDislikeService.saveUser(presentUser); + } + + return likeDislikeService.getTrack(track.getTrackID()); + } + + @GetMapping(value="/track/ratio", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value=HttpStatus.OK) + public String likeDislikeRatio(@RequestBody Track track) + { + Integer id = track.getTrackID(); + + Track currentTrack = likeDislikeService.getTrack(id); + if(currentTrack == null) + { + return "0/0"; + } + else + { + int trackLikes = currentTrack.getUserLikes().size(); + int trackDislikes = currentTrack.getUserDislikes().size(); + return "Likes: " + trackLikes + " Dislikes: " + trackDislikes; + } + } +} diff --git a/src/main/java/VanquishP2/Controllers/LocationController.java b/src/main/java/VanquishP2/Controllers/LocationController.java new file mode 100644 index 0000000..8e9a7c9 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/LocationController.java @@ -0,0 +1,61 @@ +package VanquishP2.Controllers; + + +import VanquishP2.Application.Beans.ModelServices.LocationService; +import VanquishP2.Application.Beans.Models.Location; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/4TheMusic") +public class LocationController { + private final LocationService locationService; + + @Autowired + public LocationController(LocationService locationService) { + this.locationService = locationService; + } + + // Kollier added this + @GetMapping(value = "/location/all", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public List getLocation(){ + return locationService.getAll(); + } + + @GetMapping(value = "/location/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public Location getLocation(@PathVariable ("id") Integer id){ + return locationService.getLocationById(id); + } + + @PostMapping(value = "/location", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.CREATED) + public Location saveLocation(@RequestBody Location location){ + locationService.saveLocation(location); + return locationService.getLocationById(location.getLocationID()); + } + + @PutMapping(value = "/location", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(HttpStatus.OK) + public Location updateLocation(@RequestBody Location location){ + Location updatedLocation = locationService.getLocationById(location.getLocationID()); + updatedLocation.setCity(location.getCity()); + updatedLocation.setState(location.getState()); + return locationService.saveLocation(updatedLocation); + } + + @DeleteMapping(value = "/location/{id}") + @ResponseStatus(HttpStatus.OK) + public void deleteLocation(@PathVariable ("id") Integer id){ + if(id>0){ + locationService.deleteLocation(locationService.getLocationById(id)); + }else{ + locationService.deleteAllLocations(); + } + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Controllers/PlaylistController.java b/src/main/java/VanquishP2/Controllers/PlaylistController.java new file mode 100644 index 0000000..2a3317b --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/PlaylistController.java @@ -0,0 +1,33 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.PlaylistService; +import VanquishP2.Application.Beans.Models.Playlist; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +@RestController +public class PlaylistController { + private final PlaylistService playlistService; + + @Autowired + public PlaylistController(PlaylistService playlistService){ + this.playlistService = playlistService; + } + + @PostMapping(value = "/Playlist_Name", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public Playlist savePlaylist_name(@RequestBody Playlist playlist){ + playlistService.save(playlist); + return playlistService.getPlaylist_name(playlist.getID()); + } + + @GetMapping(value = "/playlist_name/{playlist_id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Playlist getPlaylistById(@PathVariable("playlist_id") Integer id){ + return playlistService.getPlaylist_name(id); + } + + +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Controllers/TrackController.java b/src/main/java/VanquishP2/Controllers/TrackController.java new file mode 100644 index 0000000..e284f02 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/TrackController.java @@ -0,0 +1,33 @@ +package VanquishP2.Controllers; + + +import VanquishP2.Application.Beans.ModelServices.TrackService; +import VanquishP2.Application.Beans.Models.Track; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping(value = "/4TheMusic") +public class TrackController { + private final TrackService trackService; + + @Autowired + public TrackController(TrackService trackService) { + this.trackService = trackService; + } + + @PostMapping(value = "/track", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public Track saveTrack(@RequestBody Track track){ + trackService.save(track); + return trackService.getTrack(track.getTrackID()); + } + + @GetMapping(value = "/track/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public Track getTrackById(@PathVariable ("id") Integer id){ + return trackService.getTrack(id); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Controllers/UserController.java b/src/main/java/VanquishP2/Controllers/UserController.java new file mode 100644 index 0000000..81bf200 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/UserController.java @@ -0,0 +1,74 @@ +package VanquishP2.Controllers; + +import VanquishP2.Application.Beans.ModelServices.UserService; +import VanquishP2.Application.Beans.Models.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; + +/** + * UserController + * Handles requests that involve the manipulating or retrieval of user data + * + * @date 11/1/2021 + * @author Kollier Martin + */ + +@RestController +@RequestMapping(value = "/4TheMusic", produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) +public class UserController { + private final UserService userService; + + @Autowired + public UserController(UserService userService) { + this.userService = userService; + } + + /** + * Receives ID from request, then returns a User object if they exist + * @param id ID Integer to distinguish user + * @return User Object + */ + @GetMapping("/user/{id}") + public User retrieve(@PathVariable int id) { + return userService.getByID(id); + } + + /** + * Get all users in DB + * @return List of Registered Users + */ + @GetMapping("/user/all") + public ResponseEntity> getAllUsers() { + List allUsers = userService.getAllUsers(); + + if (allUsers == null) + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + else if (allUsers.isEmpty()) + return new ResponseEntity<>(allUsers, HttpStatus.NO_CONTENT); + else + return new ResponseEntity<>(allUsers, HttpStatus.OK); + } + + /** + * Delete user by ID + * @param id User ID + * @return Response Entity + */ + @DeleteMapping("/user/{id}") + public ResponseEntity delete(@PathVariable("id") int id) { + User user = userService.getByID(id); + + if (user == null) { + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + } + + userService.delete(id); + return new ResponseEntity<>(user, HttpStatus.NO_CONTENT); + } +} diff --git a/src/main/java/VanquishP2/Controllers/UserInfoController.java b/src/main/java/VanquishP2/Controllers/UserInfoController.java new file mode 100644 index 0000000..8d4c3e0 --- /dev/null +++ b/src/main/java/VanquishP2/Controllers/UserInfoController.java @@ -0,0 +1,76 @@ +package VanquishP2.Controllers; + + +import VanquishP2.Application.Beans.ModelServices.UserInfoService; +import VanquishP2.Application.Beans.Models.UserInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping(value = "/4TheMusic") +public class UserInfoController { + private final UserInfoService userInfoService; + + @Autowired + public UserInfoController(UserInfoService userInfoService) { + this.userInfoService = userInfoService; + } + + @GetMapping(value = "/userinfo/{id}", produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public UserInfo getUserInfoById(@PathVariable ("id") Integer id){ + return userInfoService.getUserInfoById(id); + } + + @PostMapping(value = "/userinfo", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.CREATED) + public UserInfo saveUserInfo(@RequestBody UserInfo userInfo){ + return userInfoService.saveUserInfo(userInfo); + } + + // Kollier took out setLocation and setUser until we get the Front End together + @PutMapping(value = "/userinfo/update", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public UserInfo updateUserInfo(@RequestBody UserInfo userInfo){ + UserInfo updatedInfo = userInfoService.getUserInfoById(userInfo.getID()); + updatedInfo.setEmail(userInfo.getEmail()); + updatedInfo.setPassword(userInfo.getPassword()); + updatedInfo.setFirstName(userInfo.getFirstName()); + updatedInfo.setLastName(userInfo.getLastName()); + updatedInfo.setUsername(userInfo.getUsername()); + userInfoService.saveUserInfo(updatedInfo); + return userInfoService.getUserInfoById(updatedInfo.getID()); + } + + @DeleteMapping(value = "/userinfo/{id}",produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseStatus(value = HttpStatus.OK) + public void deleteUserInfoById(@PathVariable ("id") Integer id){ + if(id>0){ + userInfoService.deleteUserInfo(userInfoService.getUserInfoById(id)); + }else{ + userInfoService.deleteAllInfo(); + } + } + + /** + * Get all users in DB + * @return List of Registered Users + * @author Kollier Martin + */ + @GetMapping("/userinfo/all") + public ResponseEntity> getAllUsers() { + List allUsers = userInfoService.getAll(); + + if (allUsers == null) + return new ResponseEntity<>(HttpStatus.NOT_FOUND); + else if (allUsers.isEmpty()) + return new ResponseEntity<>(allUsers, HttpStatus.NO_CONTENT); + else + return new ResponseEntity<>(allUsers, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/DTOs/LoginCredentialsDTO.java b/src/main/java/VanquishP2/DTOs/LoginCredentialsDTO.java new file mode 100644 index 0000000..148e717 --- /dev/null +++ b/src/main/java/VanquishP2/DTOs/LoginCredentialsDTO.java @@ -0,0 +1,39 @@ +package VanquishP2.DTOs; + +public class LoginCredentialsDTO { + + private String username; + private String password; + + public LoginCredentialsDTO(String username, String password) { + this.username = username; + this.password = password; + } + + public LoginCredentialsDTO() { + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + @Override + public String toString() { + return "LoginCredentialsDTO {\n" + + "username: " + username + ",\n" + + "password: " + password + ",\n" + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/DTOs/PrincipalDTO.java b/src/main/java/VanquishP2/DTOs/PrincipalDTO.java new file mode 100644 index 0000000..dc044fd --- /dev/null +++ b/src/main/java/VanquishP2/DTOs/PrincipalDTO.java @@ -0,0 +1,51 @@ +package VanquishP2.DTOs; + +import VanquishP2.Application.Beans.Models.User; +import io.jsonwebtoken.Claims; + +/** + * Custom Authentication Principal + * Used for validation of user + * @author Kollier Martin + * @date 11/8/2021 + */ +public class PrincipalDTO { + + private int userID; + private String username; + private User.Role role; + + /** + * Parameterized Constructor + * @param jwtClaims Claims object that includes an authorized user's information + */ + public PrincipalDTO(Claims jwtClaims) { + this.userID = Integer.parseInt(jwtClaims.getId()); + this.username = jwtClaims.getSubject(); + this.role = User.Role.valueOf(jwtClaims.get("role", String.class)); + } + + public int getUserID() { + return userID; + } + + public void setUserID(int userID) { + this.userID = userID; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public User.Role getRole() { + return role; + } + + public void setRole(User.Role role) { + this.role = role; + } +} diff --git a/src/main/java/VanquishP2/DTOs/UserRegistrationDTO.java b/src/main/java/VanquishP2/DTOs/UserRegistrationDTO.java new file mode 100644 index 0000000..787d810 --- /dev/null +++ b/src/main/java/VanquishP2/DTOs/UserRegistrationDTO.java @@ -0,0 +1,123 @@ +package VanquishP2.DTOs; + +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; + +/** + * UserRegistrationDTO + * The DTO for User Registration + * + * @date 10/29/2021 + * @author Kollier Martin + */ +public class UserRegistrationDTO { + + @Length(min = 5, max = 20) + @NotNull(message = "Null, a username can not be.") + @Pattern(message = "Username is not valid for the supreme overlord. Try again.", + regexp = "^[a-zA-Z0-9]*$") + private String username; + + @NotNull(message = "*crickets*. There's no password here.") + @Pattern(message = "Come on. Your password should be strong, like Russian.", + regexp = "(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[a-zA-Z]).{8,}$") + private String password; + + @Email(message = "This email is not valid >:(") + private String email; + + private String firstName, lastName, city, state; + + public UserRegistrationDTO() { + + } + + public UserRegistrationDTO(String firstName, String lastName, + String username, String password, String email, String city, String state) { + this.firstName = firstName; + this.lastName = lastName; + this.username = username; + this.password = password; + this.email = email; + this.city = city; + this.state = state; + } + + public UserRegistrationDTO(String username, String password, String email) { + this.username = username; + this.password = password; + this.email = email; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + @Override + public String toString() { + return "UserRegistrationDTO {\n" + + "username: " + username + ",\n" + + "password: " + password + ",\n" + + "email: " + email + ",\n" + + "firstName: " + firstName + ",\n" + + "lastName: " + lastName + ",\n" + + "city: " + city + ",\n" + + "state: " + state + ",\n" + + '}'; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/DataGenerators/UserGen.java b/src/main/java/VanquishP2/DataGenerators/UserGen.java new file mode 100644 index 0000000..eb25fe0 --- /dev/null +++ b/src/main/java/VanquishP2/DataGenerators/UserGen.java @@ -0,0 +1,190 @@ +package VanquishP2.DataGenerators; + +import VanquishP2.Application.Beans.ModelServices.LocationService; +import VanquishP2.Application.Beans.ModelServices.UserInfoService; +import VanquishP2.Application.Beans.ModelServices.UserService; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.DTOs.UserRegistrationDTO; +import org.hibernate.validator.constraints.Length; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Pattern; +import java.util.Random; + +import static VanquishP2.DataGenerators.UserGen.DataLists.*; + + +//@Service +public class UserGen { + private final static Random rand = new Random(); + private static int index; + private final UserService userService; + private final UserInfoService userInfoService; + private final LocationService locationService; + + //@Autowired + public UserGen(UserService userService, UserInfoService userInfoService, LocationService locationService) { + this.locationService = locationService; + this.userInfoService = userInfoService; + this.userService = userService; + } + + //@PostConstruct + private void populate() { + for (int i = 0; i < 20; i++) { + UserRegistrationDTO userRegistrationDTO = new UserRegistrationDTO(getAFirstName(), getALastName(), + getAUsername(), getAPassword(), getAEmail(), getACity(), getAState()); + + UserInfo userInfo = new UserInfo(userRegistrationDTO); + locationService.save(userInfo.getLocation()); + userInfoService.save(userInfo); + + User user = new User(User.Role.BASIC, userInfo); + userService.save(user); + + userInfo = userInfoService.getByFirstName(userInfo.getFirstName()); + userInfo.setUser(user); + userInfoService.save(userInfo); + } + } + + public static String getACity(){ + Random rand = new Random(); + int index = rand.nextInt(cities.length); + return cities[index]; + } + + public static String getAState(){ + Random rand = new Random(); + int index = rand.nextInt(cities.length); + return states[index]; + } + + public static String getAFirstName() { + index = rand.nextInt(names.length); + return names[index]; + } + + public static String getALastName() { + index = rand.nextInt(names.length); + return names[index]; + } + + public static String getAPassword() { + index = rand.nextInt(passwords.length); + return passwords[index]; + } + + public static String getAUsername() { + index = rand.nextInt(usernames.length); + return usernames[index]; + } + + public static String getAEmail() { + index = rand.nextInt(emails.length); + return emails[index]; + } + + static class DataLists { + public static String[] states = { + "Freeport", + "Alcoa", + "Fayetteville", + "Vail", + "Pekin", + "Ishpeming", + "Puyallup", + "Houlton", + "Rome", + "Pampa", + }; + + public static String[] cities = { + "Nacogdoches", + "Queens", + "Elgin", + "West Lafayette", + "Cushing", + "Payson", + "South Hadley", + "Daytona Beach", + "Meriden", + "Randolph", + }; + + public static String[] names = { + "Chace", "Nielsen", + "Leticia", "Allen", + "Lyric", "Branch", + "Cooper", "Malone", + "Kasen", "Hardy", + "Keira", "Poole", + "Braedon", "Wood", + "Porter", "Gentry", + "Augustus", "James", + "Rodolfo", "Patton", + "Iyana", "Berry", + "Dawson", "Sheppard" + }; + + public static @Length(min = 8, max = 20) + @NotNull(message = "*Crickets*.. That's an empty password!") + @Pattern(regexp = "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#&()–{}:;',?/*~$^+=<>])$", + message = "Come on. Your password should be strong, like Russian.") + String[] passwords = { + "m]hQB7>d", "wRr^){3Q", + "h@w/V[8k", "]tqWC_D4", + "kKL9?sx6", "WmHu{V9K", + "(@veR46w", ">?x&D2N9", + ">6J.yd7t", "6Qm@av{/", + "t(6_R8^{", "j)4A?[=h", + "!kZ%h[6b", "q7yS[gB{", + "_3$nJQ,r", "UCaH5[$S", + "D5p_,yVG", "J29a-j?@", + "DRyQp3}]", "n3cYM@B^" + }; + + public static @Length(min = 5, max = 20) + @NotNull(message = "Null, a username can not be.") + @Pattern(regexp = "^[a-zA-Z0-9]*$", message = "Username does not follow constraints!") + String[] usernames = { + "Aireril", "Alisomet", + "Anostung", "Aspenbo", + "AuthorPlatinum", "Astroboy", + "Bigg2free", "Bookwood", + "Bucklippe", "Chwiredu", + "Clubbieli", "Conveonsu", + "FreshTary", "HiVibrant", + "Katrien", "Leadessl", + "Litachet", "Manpsler", + "MoLight", "Nonpactel", + "Onitypema", "Perachet", + "Pherietm", "Puffro" + }; + + public static @Email(message = "Email is incorrectly formatted.") String[] emails = { + "andre.kling@mills.com", + "gayle.turcotte@connelly.biz", + "adelbert.bauch@reilly.com", + "jerel.von@dach.biz", + "qtillman@krajcik.com", + "joyce.wuckert@mayert.com", + "tillman03@terry.com", + "jeremie.altenwerth@yahoo.com", + "pemmerich@yahoo.com", + "gpouros@hessel.biz", + "percy.jaskolski@hotmail.com", + "apaucek@hotmail.com", + "hessel.gideon@yahoo.com", + "sydney31@nolan.org", + "freda.tromp@hotmail.com", + "leonie.lemke@maggio.com", + "agustina50@hotmail.com", + "graham.bertha@hotmail.com", + "alessandra68@kuphal.com", + "mraz.cory@yahoo.com" + }; + } +} diff --git a/src/main/java/VanquishP2/Deezer/AlbumSearch.java b/src/main/java/VanquishP2/Deezer/AlbumSearch.java new file mode 100644 index 0000000..e51ee3e --- /dev/null +++ b/src/main/java/VanquishP2/Deezer/AlbumSearch.java @@ -0,0 +1,46 @@ +package VanquishP2.Deezer; + +import VanquishP2.Application.Beans.Models.Album; +import VanquishP2.Application.Beans.Service.APIClientService; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class AlbumSearch { + public static List albumSearch(String albumTitle, int numberOfResults) throws JSONException { + List albumSearch = new ArrayList<>(); + + String urlStart = "https://api.deezer.com/search/album?q=" + albumTitle + "&index="; + for(int i = 0; i < numberOfResults; i++){ + //This limits the results of our get request to 1 result per request + String url = urlStart + i + "&limit=1"; + + //This sends the request and assigns the response to a String + String jsonResponse = APIClientService.get(url); + + //This section gets the artist data from the response + JSONObject jsonObject = new JSONObject(jsonResponse); + + //data is NOT a string, it is a JSONArray with 1 JSONObject in it... + JSONArray data = jsonObject.getJSONArray("data"); + + if(data.length() == 0){ + return albumSearch; + } + JSONObject jsonData = data.getJSONObject(0); + + int id = jsonData.getInt("id"); + + String newUrl = "https://api.deezer.com/album/" + id; + String stringJsonAlbum = APIClientService.get(newUrl); + + Album resultAlbum = JSONStringToModelConverter.albumConverter(stringJsonAlbum); + + albumSearch.add(resultAlbum); + } + return albumSearch; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Deezer/ArtistSearch.java b/src/main/java/VanquishP2/Deezer/ArtistSearch.java new file mode 100644 index 0000000..45771c0 --- /dev/null +++ b/src/main/java/VanquishP2/Deezer/ArtistSearch.java @@ -0,0 +1,74 @@ +package VanquishP2.Deezer; + +import VanquishP2.Application.Beans.Models.Album; +import VanquishP2.Application.Beans.Models.Artist; +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Service.APIClientService; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class ArtistSearch { + + public static List artistSearch(String artistName, int numberOfResults) throws JSONException { + List artistSearch = new ArrayList<>(); + + String urlStart = "https://api.deezer.com/search/artist?q=" + artistName + "&index="; + for(int i = 0; i < numberOfResults; i++){ + //This limits the results of our get request to 1 result per request + String url = urlStart + i + "&limit=1"; + + //This sends the request and assigns the response to a String + String jsonResponse = APIClientService.get(url); + + //This section gets the artist data from the response + JSONObject jsonObject = new JSONObject(jsonResponse); + + //data is NOT a string, it is a JSONArray with 1 JSONObject in it... + JSONArray data = jsonObject.getJSONArray("data"); + if(data.length() == 0){ + return artistSearch; + } + + JSONObject jsonData = data.getJSONObject(0); + + int id = jsonData.getInt("id"); + + String newUrl = "https://api.deezer.com/artist/" + id; + String stringJsonArtist = APIClientService.get(newUrl); + + Artist resultArtist = JSONStringToModelConverter.artistConverter(stringJsonArtist); + + artistSearch.add(resultArtist); + } + return artistSearch; + } + + public static List getTopTracks(Artist artist, int numberOfTracks) throws JSONException { + + List topTracks = new ArrayList<>(); + String request = "https://api.deezer.com/artist/"+artist.getID() + "/top?limit=" + numberOfTracks; + + String stringJsonTracks = APIClientService.get(request); + JSONObject jsonObject = new JSONObject(stringJsonTracks); + + JSONArray data = jsonObject.getJSONArray("data"); + for(int i = 0; i < data.length(); i++){ + + JSONObject jsonTrack = data.getJSONObject(i); + JSONObject jsonAlbum = jsonTrack.getJSONObject("album"); + int albumID = jsonAlbum.getInt("id"); + + String albumRequest = "https://api.deezer.com/album/" + albumID; + String albumJsonString = APIClientService.get(albumRequest); + Album album = JSONStringToModelConverter.albumConverter(albumJsonString); + + Track track = JSONObjectToModelConverter.topTrackConverter(jsonTrack, artist, album); + topTracks.add(track); + } + return topTracks; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Deezer/JSONObjectToModelConverter.java b/src/main/java/VanquishP2/Deezer/JSONObjectToModelConverter.java new file mode 100644 index 0000000..0d18d8c --- /dev/null +++ b/src/main/java/VanquishP2/Deezer/JSONObjectToModelConverter.java @@ -0,0 +1,90 @@ +package VanquishP2.Deezer; + +import VanquishP2.Application.Beans.Models.Album; +import VanquishP2.Application.Beans.Models.Artist; +import VanquishP2.Application.Beans.Models.Genre; +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Service.APIClientService; +import org.json.JSONException; +import org.json.JSONObject; + +public class JSONObjectToModelConverter { + public static Track trackConverter(JSONObject jsonObject) throws JSONException { + + int trackID = jsonObject.getInt("id"); + String title = jsonObject.getString("title"); + + //This gets the artist JSONObject and pulls data from it + JSONObject artistJson = jsonObject.getJSONObject("artist"); + int artistId = artistJson.getInt("id"); + String name = artistJson.getString("name"); + String pictureUrl = artistJson.getString("picture_medium"); + Artist artist = new Artist(name,artistId,pictureUrl); + + JSONObject albumJson = jsonObject.getJSONObject("album"); + int albumID = albumJson.getInt("id"); + String albumTitle = albumJson.getString("title"); + String releaseDate = albumJson.getString("release_date"); + + Album album = new Album(); + album.setAlbumID(albumID); + album.setAlbumTitle(albumTitle); + album.setDate(releaseDate); + + Track track = new Track(); + track.setTrackID(trackID); + track.setTitle(title); + track.setAlbum(album); + track.setArtist(artist); + return track; + } + + public static Artist artistConverter(JSONObject jsonObject) throws JSONException { + int artistId = jsonObject.getInt("id"); + String name = jsonObject.getString("name"); + String pictureUrl = jsonObject.getString("picture_medium"); + + return new Artist(name, artistId, pictureUrl); + } + + public static Album albumConverter(JSONObject jsonObject) throws JSONException { + int albumID = jsonObject.getInt("id"); + String title = jsonObject.getString("title"); + String releaseDate = jsonObject.getString("release_date"); + + int genre_id = jsonObject.getInt("genre_id"); + + //GET from deezer the Genre by the ID + String genreJsonString = "https://api.deezer.com/genre/"+genre_id; + String genre_json_response = APIClientService.get(genreJsonString); + + //call genreConverter here + Genre genre = genreConverter(genre_json_response); + + Album album = new Album(); + album.setAlbumID(albumID); + album.setAlbumTitle(title); + album.setDate(releaseDate); + album.setGenre(genre); + + return album; + } + + public static Genre genreConverter(String json) throws JSONException { + JSONObject jsonObject = new JSONObject(json); + int genre_id = jsonObject.getInt("id"); + String name = jsonObject.getString("name"); + String pictureUrl = jsonObject.getString("picture_medium"); + + return new Genre(genre_id,name,pictureUrl); + } + + public static Track topTrackConverter(JSONObject jsonTrack, Artist artist, Album album) throws JSONException { + int trackID = jsonTrack.getInt("id"); + String title = jsonTrack.getString("title"); + Track track = new Track(trackID, title); + track.setArtist(artist); + track.setAlbum(album); + return track; + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Deezer/JSONStringToModelConverter.java b/src/main/java/VanquishP2/Deezer/JSONStringToModelConverter.java new file mode 100644 index 0000000..996b686 --- /dev/null +++ b/src/main/java/VanquishP2/Deezer/JSONStringToModelConverter.java @@ -0,0 +1,84 @@ +package VanquishP2.Deezer; + +import VanquishP2.Application.Beans.Models.Album; +import VanquishP2.Application.Beans.Models.Artist; +import VanquishP2.Application.Beans.Models.Genre; +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Service.APIClientService; +import org.json.JSONException; +import org.json.JSONObject; + +public class JSONStringToModelConverter { + + public static Track trackConverter(String json) throws JSONException { + + JSONObject jsonObject = new JSONObject(json); + int track_id = jsonObject.getInt("id"); + String title = jsonObject.getString("title"); + + //This gets the artist JSONObject and pulls data from it + JSONObject artistJson = jsonObject.getJSONObject("artist"); + int artist_id = artistJson.getInt("id"); + String name = artistJson.getString("name"); + String pictureUrl = artistJson.getString("picture_medium"); + Artist artist = new Artist(name,artist_id,pictureUrl); + + JSONObject albumJson = jsonObject.getJSONObject("album"); + int album_id = albumJson.getInt("id"); + String album_title = albumJson.getString("title"); + String release_date = albumJson.getString("release_date"); + + Album album = new Album(); + album.setAlbumID(album_id); + album.setAlbumTitle(title); + album.setDate(release_date); + + Track track = new Track(); + track.setTrackID(track_id); + track.setTitle(title); + track.setAlbum(album); + track.setArtist(artist); + return track; + } + + public static Artist artistConverter(String json) throws JSONException { + JSONObject jsonObject = new JSONObject(json); + int artistID = jsonObject.getInt("id"); + String name = jsonObject.getString("name"); + String pictureUrl = jsonObject.getString("picture_medium"); + + return new Artist(name, artistID, pictureUrl); + } + + public static Album albumConverter(String json) throws JSONException { + JSONObject jsonObject = new JSONObject(json); + int album_id = jsonObject.getInt("id"); + String title = jsonObject.getString("title"); + String releaseDate = jsonObject.getString("release_date"); + + int genre_id = jsonObject.getInt("genre_id"); + //GET from deezer the Genre by the ID + String genreJsonString = "https://api.deezer.com/genre/"+genre_id; + String genre_json_response = APIClientService.get(genreJsonString); + + //call genreConverter here + Genre genre = genreConverter(genre_json_response); + + Album album = new Album(); + album.setAlbumID(album_id); + album.setAlbumTitle(title); + album.setDate(releaseDate); + album.setGenre(genre); + + return album; + } + + public static Genre genreConverter(String json) throws JSONException { + JSONObject jsonObject = new JSONObject(json); + int genre_id = jsonObject.getInt("id"); + String name = jsonObject.getString("name"); + String pictureUrl = jsonObject.getString("picture_medium"); + + return new Genre(genre_id,name,pictureUrl); + } +} \ No newline at end of file diff --git a/src/main/java/VanquishP2/Deezer/TrackSearch.java b/src/main/java/VanquishP2/Deezer/TrackSearch.java new file mode 100644 index 0000000..978940c --- /dev/null +++ b/src/main/java/VanquishP2/Deezer/TrackSearch.java @@ -0,0 +1,65 @@ +package VanquishP2.Deezer; + +import VanquishP2.Application.Beans.Models.Track; +import VanquishP2.Application.Beans.Service.APIClientService; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.List; + +public class TrackSearch { + + public static List searchTracks(String track_title, int numberOfResults) throws JSONException { + List trackSearch = new ArrayList<>(); + + String urlStart = "https://api.deezer.com/search/track?q="+track_title+"&index="; + for(int i=0;i + + + \ No newline at end of file diff --git a/src/test/java/Models/UserDBTest.java b/src/test/java/Models/UserDBTest.java new file mode 100644 index 0000000..0b056d9 --- /dev/null +++ b/src/test/java/Models/UserDBTest.java @@ -0,0 +1,50 @@ +package Models; + +import VanquishP2.Application.Beans.Models.Location; +import VanquishP2.Application.Beans.Models.User; +import VanquishP2.Application.Beans.Models.UserInfo; +import VanquishP2.Application.Beans.Repos.UserInfoRepository; +import VanquishP2.Application.Beans.Repos.UserRepository; +import VanquishP2.Application.P2Application; +import VanquishP2.DTOs.UserRegistrationDTO; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +import javax.annotation.Resource; + +@SpringBootTest(classes = P2Application.class) +@ActiveProfiles("test") +@RunWith(SpringRunner.class) +class UserDBTest { + @Resource + private UserRepository userRepository; + + @Resource + private UserInfoRepository userInfoRepository; + + @Test + void contextLoads() { + } + + @Test + public void goodSave(){ + UserInfo userInfo = new UserInfo(new UserRegistrationDTO("Kollier", + "Martin", + "KMART23", + "3t3styG=5!", + "astronomical@space.net", + "Mars", + "Milky Way")); + + userInfoRepository.save(userInfo); + + User user = new User(User.Role.PREMIUM, userInfo); + userRepository.save(user); + + Assertions.assertEquals("Koller", userInfoRepository.findByFirstName("Kollier").get().getFirstName()); + } +} diff --git a/target/classes/beans.xml b/target/classes/beans.xml new file mode 100644 index 0000000..142def2 --- /dev/null +++ b/target/classes/beans.xml @@ -0,0 +1,6 @@ + + + + \ No newline at end of file