Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,6 @@ out/

### VS Code ###
.vscode/

### Ignore application.yml file ###
src/main/resources/application.yml
21 changes: 15 additions & 6 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,21 @@ repositories {
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'io.jsonwebtoken:jjwt-api:0.12.6'
implementation 'io.jsonwebtoken:jjwt-impl:0.12.6'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.6'

compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'org.postgresql:postgresql'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

implementation 'jakarta.validation:jakarta.validation-api:3.1.0'
}

tasks.named('test') {
Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/booleanuk/api/cinema/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.booleanuk.api.cinema;

import com.booleanuk.api.cinema.models.ERole;
import com.booleanuk.api.cinema.models.Role;
import com.booleanuk.api.cinema.repositories.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Main implements CommandLineRunner{
@Autowired
private RoleRepository roleRepository;

public static void main(String[] args) {
SpringApplication.run(Main.class, args);
}

@Override
public void run(String... args){
if (!this.roleRepository.existsByName(ERole.ROLE_USER)) {
this.roleRepository.save(new Role(ERole.ROLE_USER));
}

if (!this.roleRepository.existsByName(ERole.ROLE_MODERATOR)) {
this.roleRepository.save(new Role(ERole.ROLE_MODERATOR));
}

if (!this.roleRepository.existsByName(ERole.ROLE_ADMIN)) {
this.roleRepository.save(new Role(ERole.ROLE_ADMIN));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.booleanuk.api.cinema.controllers;

import com.booleanuk.api.cinema.models.ERole;
import com.booleanuk.api.cinema.models.Role;
import com.booleanuk.api.cinema.models.User;
import com.booleanuk.api.cinema.payload.request.LoginRequest;
import com.booleanuk.api.cinema.payload.request.SignupRequest;
import com.booleanuk.api.cinema.payload.response.JwtResponse;
import com.booleanuk.api.cinema.payload.response.MessageResponse;
import com.booleanuk.api.cinema.repositories.RoleRepository;
import com.booleanuk.api.cinema.repositories.UserRepository;
import com.booleanuk.api.cinema.security.jwt.JwtUtils;
import com.booleanuk.api.cinema.security.services.UserDetailsImpl;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class AuthController {
@Autowired
AuthenticationManager authenticationManager;

@Autowired
UserRepository userRepository;

@Autowired
RoleRepository roleRepository;

@Autowired
PasswordEncoder encoder;

@Autowired
JwtUtils jwtUtils;

@PostMapping("/signin")
public ResponseEntity<?> authenticateUser(@Valid @RequestBody LoginRequest loginRequest) {
Authentication authentication = authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);
String jwt = jwtUtils.generateJwtToken(authentication);

UserDetailsImpl userDetails = (UserDetailsImpl) authentication.getPrincipal();
List<String> roles = userDetails.getAuthorities().stream().map((item) -> item.getAuthority())
.collect(Collectors.toList());
return ResponseEntity
.ok(new JwtResponse(jwt, userDetails.getId(), userDetails.getUsername(), userDetails.getEmail(), roles));
}

@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignupRequest signupRequest) {
if (userRepository.existsByUsername(signupRequest.getUsername())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Username is already taken"));
}
if (userRepository.existsByEmail(signupRequest.getEmail())) {
return ResponseEntity.badRequest().body(new MessageResponse("Error: Email is already in use!"));
}
// Create a new user add salt here if using one
User user = new User(signupRequest.getUsername(), signupRequest.getEmail(), encoder.encode(signupRequest.getPassword()));
Set<String> strRoles = signupRequest.getRole();
Set<Role> roles = new HashSet<>();

if (strRoles == null) {
Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(userRole);
} else {
strRoles.forEach((role) -> {
switch (role) {
case "admin":
Role adminRole = roleRepository.findByName(ERole.ROLE_ADMIN).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(adminRole);
break;
case "mod":
Role modRole = roleRepository.findByName(ERole.ROLE_MODERATOR).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(modRole);
break;
default:
Role userRole = roleRepository.findByName(ERole.ROLE_USER).orElseThrow(() -> new RuntimeException("Error: Role is not found"));
roles.add(userRole);
break;
}
});
}
user.setRoles(roles);
userRepository.save(user);
return ResponseEntity.ok((new MessageResponse("User registered successfully")));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.booleanuk.api.cinema.controllers;

import com.booleanuk.api.cinema.models.Customer;
import com.booleanuk.api.cinema.payload.response.CustomerListResponse;
import com.booleanuk.api.cinema.repositories.CustomerRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

@RestController
@RequestMapping("customers")
public class CustomerController {
@Autowired
private CustomerRepository repository;

@GetMapping
public List<Customer> getAll(){
return this.repository.findAll();
}

@PostMapping
public ResponseEntity<Customer> createCustomer(@RequestBody Customer customer){
return new ResponseEntity<Customer>(this.repository.save(customer), HttpStatus.CREATED);
}

@PutMapping("{id}")
public ResponseEntity<Customer> updateCustomer(@PathVariable int id, @RequestBody Customer customer){
Customer customerToUpdate = this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found"));

customerToUpdate.setName(customer.getName());
customerToUpdate.setEmail(customer.getEmail());
customerToUpdate.setPhone(customer.getPhone());

return new ResponseEntity<>(this.repository.save(customerToUpdate), HttpStatus.CREATED);
}

@DeleteMapping("{id}")
public ResponseEntity<Customer> DeleteCustomer(@PathVariable int id) {
Customer customerToDelete = this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found"));
this.repository.delete(customerToDelete);
return ResponseEntity.ok(customerToDelete);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.booleanuk.api.cinema.controllers;

import com.booleanuk.api.cinema.models.Movie;
import com.booleanuk.api.cinema.repositories.MovieRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

@RestController
@RequestMapping("movies")
public class MovieController {
@Autowired
private MovieRepository repository;

@GetMapping
public List<Movie> getAll(){
return this.repository.findAll();
}

@PostMapping
public ResponseEntity<Movie> createMovie(@RequestBody Movie movie){
return new ResponseEntity<Movie>(this.repository.save(movie), HttpStatus.CREATED);
}

@PutMapping("{id}")
public ResponseEntity<Movie> updateMovie(@PathVariable int id, @RequestBody Movie movie){
Movie movieToUpdate = this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found"));

movieToUpdate.setTitle(movie.getTitle());
movieToUpdate.setDescription(movie.getDescription());
movieToUpdate.setRating(movie.getRating());
movieToUpdate.setRuntimeMins(movie.getRuntimeMins());

return new ResponseEntity<>(this.repository.save(movieToUpdate), HttpStatus.CREATED);
}


@DeleteMapping("{id}")
public ResponseEntity<Movie> DeleteMovie(@PathVariable int id) {
Movie movieToDelete = this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found"));
this.repository.delete(movieToDelete);
return ResponseEntity.ok(movieToDelete);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.booleanuk.api.cinema.controllers;

import com.booleanuk.api.cinema.models.Movie;
import com.booleanuk.api.cinema.models.Screening;
import com.booleanuk.api.cinema.repositories.MovieRepository;
import com.booleanuk.api.cinema.repositories.ScreeningRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import java.util.List;

@RestController
@RequestMapping("movies/{id}/screenings")
public class ScreeningController {
@Autowired
private ScreeningRepository screeningRepository;

@Autowired
private MovieRepository movieRepository;

@GetMapping
public ResponseEntity<List<Screening>> getAll(@PathVariable int id){
if (!movieRepository.existsById(id)) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie not found");
}
List<Screening> screeningsToGet = screeningRepository.findByMovieId(id);
return ResponseEntity.ok(screeningsToGet);
}

@PostMapping
public ResponseEntity<Screening> createScreening(@PathVariable int id, @RequestBody Screening screening){
Movie movie = movieRepository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Movie not found"));
screening.setMovie(movie);
return new ResponseEntity<Screening>(this.screeningRepository.save(screening), HttpStatus.CREATED);
}

// @PutMapping("{id}")
// public ResponseEntity<Screening> updateScreening(@PathVariable int id, @RequestBody Screening screening){
// Screening screeningToUpdate = this.repository.findById(id).orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Not found"));
//
// screeningToUpdate.setScreenNumber(screening.getScreenNumber());
// screeningToUpdate.setCapacity(screening.getCapacity());
// screeningToUpdate.setStartsAt(screening.getStartsAt());
//
// return new ResponseEntity<>(this.repository.save(screeningToUpdate), HttpStatus.CREATED);
// }
}
44 changes: 44 additions & 0 deletions src/main/java/com/booleanuk/api/cinema/models/Customer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package com.booleanuk.api.cinema.models;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import org.hibernate.annotations.CreationTimestamp;
import org.hibernate.annotations.UpdateTimestamp;

import java.time.OffsetDateTime;

@Getter
@Setter
@NoArgsConstructor
@Entity
@Table(name = "customers")
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;

@Column
private String name;

@Column
private String email;

@Column
private String phone;

@CreationTimestamp
@Column
private OffsetDateTime createdAt;

@UpdateTimestamp
@Column
private OffsetDateTime updatedAt;

public Customer(String name, String email, String phone) {
this.name = name;
this.email = email;
this.phone = phone;
}
}
7 changes: 7 additions & 0 deletions src/main/java/com/booleanuk/api/cinema/models/ERole.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.booleanuk.api.cinema.models;

public enum ERole {
ROLE_USER,
ROLE_MODERATOR,
ROLE_ADMIN
}
Loading