Skip to content

Commit

Permalink
Merge pull request hxt001#5 from tabriszhu913/main
Browse files Browse the repository at this point in the history
Version 2
  • Loading branch information
tabriszhu913 authored May 1, 2022
2 parents a09fe53 + 47df09e commit 3da3639
Show file tree
Hide file tree
Showing 41 changed files with 933 additions and 3,073 deletions.
56 changes: 56 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# This is a basic workflow to help you get started with Actions

name: CI

# Controls when the workflow will run
on: push

# Allows you to run this workflow manually from the Actions tab
# workflow_dispatch:

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest

# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2

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

- name: Set up docker
uses: docker-practice/actions-setup-docker@master

- name: Test backend
run: |
cd backend
./gradlew test
- name: Build backend image
run: |
cd backend
./gradlew bootJar
docker build -t backend .
- name: Set up Node
uses: actions/setup-node@v2
with:
node-version: 'lts/erbium'

- name: Build frontend image
run: |
cd booking-system-ui
npm install
npm run build
docker build -t frontend .
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# Mac
.DS_Store

# Compiled class file
*.class

Expand Down
4 changes: 4 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
FROM openjdk:11-jdk-slim
ARG JAR_FILE=build/libs/*.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
32 changes: 31 additions & 1 deletion backend/build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,34 @@
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath("io.spring.javaformat:spring-javaformat-gradle-plugin:0.0.31")
}
}

plugins {
id 'org.springframework.boot' version '2.5.4'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}

apply plugin: 'io.spring.javaformat'

group = 'com.pivottech'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

springBoot {
mainClass = 'com.pivottech.booking.BookingApplication'
}

bootJar {
manifest {
attributes 'Start-Class': 'com.pivottech.booking.BookingApplication'
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
Expand All @@ -33,7 +54,9 @@ dependencies {
// Spring JPA
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'mysql:mysql-connector-java:8.0.26'
// runtimeOnly 'mysql:mysql-connector-java:8.0.26'
runtimeOnly 'org.postgresql:postgresql:42.3.4'


// Mockito
testImplementation 'org.mockito:mockito-core:3.12.4'
Expand All @@ -42,6 +65,13 @@ dependencies {
// https://mvnrepository.com/artifact/org.apache.commons/commons-lang3
implementation 'org.apache.commons:commons-lang3:3.12.0'

// Security
implementation 'org.springframework.boot:spring-boot-starter-security'
testImplementation 'org.springframework.security:spring-security-test'

// Spring Session JDBC
implementation 'org.springframework.session:spring-session-jdbc'

}

test {
Expand Down
106 changes: 90 additions & 16 deletions backend/src/main/java/com/pivottech/booking/BookingApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,104 @@
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.pivottech.booking.handler.LoginSuccessHandler;
import com.pivottech.booking.intercepter.LogInterceptor;
import com.pivottech.booking.intercepter.TodaysDateArgumentResolver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
import org.springframework.stereotype.Service;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@SpringBootApplication
public class BookingApplication {

@Service
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
this.registerModule(new JavaTimeModule());
}
}

@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}

public static void main(String[] args) {
SpringApplication.run(BookingApplication.class, args);
}
@Service
public class CustomObjectMapper extends ObjectMapper {

public CustomObjectMapper() {
this.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
this.registerModule(new JavaTimeModule());
}

}

@Configuration
public class WebMVCConfig implements WebMvcConfigurer {

@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor());
WebMvcConfigurer.super.addInterceptors(registry);
}

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new TodaysDateArgumentResolver());
WebMvcConfigurer.super.addArgumentResolvers(resolvers);
}

}

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.csrf().disable()
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers(HttpMethod.POST, "/users").permitAll()
.anyRequest().authenticated()
.and()
.exceptionHandling()
.authenticationEntryPoint(new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED))
.and()
.formLogin()
.loginPage("/login").permitAll()
.successHandler(loginSuccessHandler())
.and()
.logout().permitAll();
// @formatter:on
}

}

@Bean
public javax.validation.Validator localValidatorFactoryBean() {
return new LocalValidatorFactoryBean();
}

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

@Bean
public LoginSuccessHandler loginSuccessHandler() {
return new LoginSuccessHandler();
}

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

}
16 changes: 0 additions & 16 deletions backend/src/main/java/com/pivottech/booking/CrosConfig.java

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

import javax.annotation.security.RolesAllowed;
import javax.validation.Valid;
import java.time.Duration;
import java.time.LocalDateTime;
Expand All @@ -19,40 +20,38 @@
@RequestMapping("{username}/availabilities")
public class AvailabilityController {

@Autowired
BookingService bookingService;

@Autowired
UserService userService;

@GetMapping("")
public Iterable<Availability> list(
@PathVariable("username") String username,
@RequestParam(name = "from") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") LocalDateTime from,
@RequestParam(name = "to") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") LocalDateTime to
) {
User user = userService.getUserByUsername(username);
if (user == null || user.getInstructor() == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "instructor doesn't exist");
}
return bookingService.findAvailabilitiesBetween(user.getInstructor(), from, to);
}

@PostMapping("")
public Iterable<Availability> create(
@PathVariable("username") String username,
@Valid @RequestBody CreateAvailabilityRequest request
) {
User user = userService.getUserByUsername(username);
if (user == null || user.getInstructor() == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "instructor doesn't exist");
}
LocalDateTime from = request.getFromUtc();
LocalDateTime to = request.getToUtc();
if (from.isAfter(to)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "from must be earlier than to");
}
Duration duration = Duration.ofMinutes(request.getDurationMinutes());
return bookingService.createAvailability(user.getInstructor(), from, to, duration);
}
@Autowired
BookingService bookingService;

@Autowired
UserService userService;

@GetMapping("")
public Iterable<Availability> list(@PathVariable("username") String username,
@RequestParam(name = "from") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") LocalDateTime from,
@RequestParam(name = "to") @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm") LocalDateTime to) {
User user = userService.getUserByUsername(username);
if (user == null || user.getInstructor() == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "instructor doesn't exist");
}
return bookingService.findAvailabilitiesBetween(user.getInstructor(), from, to);
}

@PostMapping("")
@RolesAllowed({ "Instructor" })
public Iterable<Availability> create(@PathVariable("username") String username,
@Valid @RequestBody CreateAvailabilityRequest request) {
User user = userService.getUserByUsername(username);
if (user == null || user.getInstructor() == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "instructor doesn't exist");
}
LocalDateTime from = request.getFromUtc();
LocalDateTime to = request.getToUtc();
if (from.isAfter(to)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "from must be earlier than to");
}
Duration duration = Duration.ofMinutes(request.getDurationMinutes());
return bookingService.createAvailability(user.getInstructor(), from, to, duration);
}

}
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
package com.pivottech.booking.controller;

import com.pivottech.booking.intercepter.TodaysDate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;

@RestController
public class HelloWorldController {

@GetMapping("/")
public String index() {
return "Hello World!2";
}
@GetMapping("/")
public String index() {
return "Hello World!2";
}

@GetMapping("todaysDate")
public String todaysDate(@TodaysDate LocalDate todaysDate) {
return todaysDate.toString();
}
}
Loading

0 comments on commit 3da3639

Please sign in to comment.