Skip to content

Commit

Permalink
Merge pull request #104 from COS301-SE-2023/development
Browse files Browse the repository at this point in the history
Development!
  • Loading branch information
SkulderLock authored Aug 1, 2023
2 parents f0c0b52 + fb4ab32 commit 13d80a5
Show file tree
Hide file tree
Showing 143 changed files with 7,534 additions and 1,797 deletions.
24 changes: 22 additions & 2 deletions .github/workflows/buildAndTest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,28 @@ jobs:
cache-dependency-path: package-lock.json
- run: npm ci
- run: npm run build --if-present
- run: npm run test:dev
- run: npm run test:unit

- name: Test with Angular
run: npm run test:dev

- name: Set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'

- name: Grant execute permission for gradlew
run: chmod +x gradlew
working-directory: backend

- name: Test with Gradle
run: ./gradlew test
working-directory: backend
env:
JWT_SECRET: ${{ secrets.JWT_SECRET }}
DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
DB_USERNAME: ${{ secrets.DB_USERNAME }}
DB_URI: ${{ secrets.DB_URI }}

- name: Download artifacts
uses: actions/download-artifact@v2
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -106,3 +106,5 @@ out/
### VS Code ###
.vscode/
angular.json
package-lock.json
package.json
5 changes: 0 additions & 5 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,5 +0,0 @@
{
"recommendations": [
"ionic.ionic"
]
}
5 changes: 4 additions & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@ repositories {

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-neo4j'
// implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'io.github.cdimascio:java-dotenv:5.2.2'
Expand Down
2 changes: 1 addition & 1 deletion backend/gradlew
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -237,4 +237,4 @@ eval "set -- $(
tr '\n' ' '
)" '"$@"'

exec "$JAVACMD" "$@"
exec "$JAVACMD" "$@"
Empty file modified backend/gradlew.bat
100644 → 100755
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package fellowship.mealmaestro.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

import fellowship.mealmaestro.services.UserService;

@Configuration
public class ApplicationConfig {

private final UserService userService;

public ApplicationConfig(UserService userService){
this.userService = userService;
}

@Bean
public UserDetailsService userDetailsService(){
return username -> userService.findByEmail(username)
.orElseThrow(() -> new UsernameNotFoundException("User '" + username + "' not found"));
}

@Bean
public AuthenticationProvider authenticationProvider(){
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService());
provider.setPasswordEncoder(passwordEncoder());
return provider;
}

@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
//TODO
}

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
return config.getAuthenticationManager();
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fellowship.mealmaestro.config;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

@RestControllerAdvice
public class GlobalExceptionHandler {


@ExceptionHandler(RuntimeException.class)
public ResponseEntity<String> handleUserNotFoundException(RuntimeException e){
return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package fellowship.mealmaestro.config;

import java.io.IOException;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import fellowship.mealmaestro.models.UserModel;
import fellowship.mealmaestro.services.auth.JwtService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

private final JwtService jwtService;

private final UserDetailsService userDetailsService;

public JwtAuthenticationFilter(JwtService jwtService, UserDetailsService userDetailsService){
this.jwtService = jwtService;
this.userDetailsService = userDetailsService;
}

@Override
protected void doFilterInternal(
HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {

final String authHeader = request.getHeader("Authorization");
final String jwtToken;
final String userEmail;

if (authHeader == null || !authHeader.startsWith("Bearer ")) {
filterChain.doFilter(request, response);
return;
}

jwtToken = authHeader.substring(7);
userEmail = jwtService.extractUserEmail(jwtToken);

if (userEmail != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserModel userDetails = (UserModel) this.userDetailsService.loadUserByUsername(userEmail);
if (jwtService.isTokenValid(jwtToken, userDetails)){
UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(
userDetails,
null,
userDetails.getAuthorities()
);

authToken.setDetails(
new WebAuthenticationDetailsSource().buildDetails(request)
);

SecurityContextHolder.getContext().setAuthentication(authToken);
}
}

filterChain.doFilter(request, response);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,32 @@
public class Neo4jConfig {
@Bean
public Driver neo4jDriver() {
Dotenv dotenv = Dotenv.load();
String uri = dotenv.get("DB_URI");
String username = dotenv.get("DB_USERNAME");
String password = dotenv.get("DB_PASSWORD");
String uri;
String username;
String password;
Dotenv dotenv;

if (System.getenv("DB_URI") != null) {
uri = System.getenv("DB_URI");
username = System.getenv("DB_USERNAME");
password = System.getenv("DB_PASSWORD");

return GraphDatabase.driver(uri, AuthTokens.basic(username, password));
}

try {
dotenv = Dotenv.load();
uri = dotenv.get("DB_URI");
username = dotenv.get("DB_USERNAME");
password = dotenv.get("DB_PASSWORD");
} catch (Exception e){
dotenv = Dotenv.configure()
.ignoreIfMissing()
.load();
uri = "No DB URI Found";
username = "No DB Username Found";
password = "No DB Password Found";
}

return GraphDatabase.driver(uri, AuthTokens.basic(username, password));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package fellowship.mealmaestro.config;

import java.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig {

private final JwtAuthenticationFilter jwtAuthFilter;

private final AuthenticationProvider authenticationProvider;

public SecurityConfig(JwtAuthenticationFilter jwtAuthFilter, AuthenticationProvider authenticationProvider){
this.jwtAuthFilter = jwtAuthFilter;
this.authenticationProvider = authenticationProvider;
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
http
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authReq -> authReq
.requestMatchers("/register", "/authenticate")
.permitAll()
.anyRequest()
.authenticated()
)
.sessionManagement(session -> session
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
)
.addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);


http.authenticationProvider(authenticationProvider);
return http.build();
}

@Bean
CorsConfigurationSource corsConfigurationSource(){
CorsConfiguration corsConfig = new CorsConfiguration();
corsConfig.setAllowedOrigins(Arrays.asList("http://localhost:4200", "http://localhost:8100"));
corsConfig.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
corsConfig.setAllowedHeaders(Arrays.asList("*"));
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", corsConfig);
return source;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package fellowship.mealmaestro.controllers;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import fellowship.mealmaestro.models.MealModel;
import fellowship.mealmaestro.services.BrowseService;
//import fellowship.mealmaestro.services.PantryService;
import jakarta.validation.Valid;

@RestController
public class BrowseController {

@Autowired
private BrowseService browseService;

@GetMapping("/getPopularMeals")
public ResponseEntity<List<MealModel>> getPopularMeals(@RequestHeader("Authorization") String token){
if (token == null || token.isEmpty()) {
return ResponseEntity.badRequest().build();
}
String authToken = token.substring(7);
return ResponseEntity.ok(browseService.getPopularMeals(authToken));
}

@GetMapping("/getSearchedMeals")
public ResponseEntity<List<MealModel>> getSearcedhMeals(@RequestParam("query") String mealName, @RequestHeader("Authorization") String token){
if (token == null || token.isEmpty()) {
return ResponseEntity.badRequest().build();
}
String authToken = token.substring(7);
return ResponseEntity.ok(browseService.getSearchedMeals(mealName,authToken));
}

}
Loading

0 comments on commit 13d80a5

Please sign in to comment.