Skip to content
This repository has been archived by the owner on May 24, 2022. It is now read-only.

Commit

Permalink
Merge pull request #265 from SELab-2/development
Browse files Browse the repository at this point in the history
Dev into main
  • Loading branch information
lars-vc authored Apr 28, 2022
2 parents c5ef92b + 405eb56 commit 35f27bc
Show file tree
Hide file tree
Showing 142 changed files with 12,784 additions and 1,983 deletions.
14 changes: 14 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
### Checklist

Remove items if they're not applicable.

**New feature checklist**:
- [ ] I've added tests for the new feature (100% coverage)
- [ ] I've thoroughly documented the code
- [ ] I've updated the `osoc.yaml` file


**Breaking change checklist**:
- [ ] I've updated the existing tests to account for the changes in expected behavior
- [ ] I've updated the documentation to reflect the new behavior
- [ ] I've updated the `osoc.yaml` file
26 changes: 5 additions & 21 deletions .github/workflows/all_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,24 @@ name: Run backend all tests with maven
on:
push:
branches: [ master, development ]
paths:
- 'backend/**'
pull_request:
branches:
- '**'
paths:
- 'backend/**'

jobs:
container-job:

runs-on: self-hosted
container:
image: mikxox/maven-test-action:latest
options: --rm
env:
GITHUB_WORKSPACE: /home/selab2/actions-runner/workspace

# Service containers to run with `container-job`
services:
# Label used to access the service container
# Need to actually run a postgres container to allow app to build
postgres:
image: postgres
ports:
- 5432

env:
POSTGRES_USER: ${{ secrets.database_username }}
POSTGRES_PASSWORD: ${{ secrets.database_password }}
POSTGRES_DB: ${{ secrets.database_name }}

# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
with:
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/backend-linting.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
name: backend-linting
on: [pull_request]
on:
pull_request:
paths:
- 'backend/**'

jobs:
ktlint:
name: Check Code Quality
runs-on: self-hosted
container:
image: mikxox/maven-test-action:latest
options: --rm
env:
GITHUB_WORKSPACE: /home/selab2/actions-runner/workspace

Expand Down Expand Up @@ -34,4 +38,4 @@ jobs:
if: always()
run: |
cd /__w/OSOC-1/OSOC-1/
sudo rm -rf temppath
sudo rm -rf temppath
2 changes: 1 addition & 1 deletion .github/workflows/commitlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ jobs:
runs-on: self-hosted
container:
image: mikxox/maven-test-action:latest

options: --rm
env:
GITHUB_WORKSPACE: /home/selab2/actions-runner/workspace

Expand Down
6 changes: 5 additions & 1 deletion .github/workflows/prettier.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@ name: Run prettier and eslint
on:
push:
branches: [ master, development ]
paths:
- 'frontend/**'
pull_request:
branches: [ master, development ]
paths:
- 'frontend/**'

jobs:
container-job:

runs-on: self-hosted
container:
image: mikxox/maven-test-action:latest

options: --rm
steps:
- uses: actions/checkout@v2
with:
Expand Down
26 changes: 5 additions & 21 deletions .github/workflows/unittests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,42 +6,26 @@ on:
- '**' # matches every branch
- '!master' # excludes master
- '!development' # excludes development
paths:
- 'backend/**'
pull_request:
branches:
- '**' # matches every branch
- '!master' # excludes master
- '!development' # excludes development
paths:
- 'backend/**'

jobs:
container-job:

runs-on: self-hosted
container:
image: mikxox/maven-test-action:latest
options: --rm
env:
GITHUB_WORKSPACE: /home/selab2/actions-runner/workspace

# Service containers to run with `container-job`
services:
# Label used to access the service container
# Need to actually run a postgres container to allow app to build
postgres:
image: postgres
ports:
- 5432

env:
POSTGRES_USER: ${{ secrets.database_username }}
POSTGRES_PASSWORD: ${{ secrets.database_password }}
POSTGRES_DB: ${{ secrets.database_name }}

# Set health checks to wait until postgres has started
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
with:
Expand Down
9 changes: 2 additions & 7 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,9 @@ server.error.include-exception=false

## Running tests
When running integration tests, Spring needs to load the entire application. \
This means Spring will also need a database to connect to. \
For this ```/backend/src/test/resources/application.properties``` is used. \
These properties are setup as used by github actions, to run tests locally change \
```spring.datasource.url=jdbc:postgresql://postgres:5432/osoc```
to ```spring.datasource.url=jdbc:postgresql://localhost:5432/osoc``` \
This is setup to automatically create and start docker containers, so make sure docker is installed. \
On windows this means docker desktop should be up and running. \
Then simply run the test command in /backend to run all tests.
```
./mvnw test
Expand All @@ -29,6 +27,3 @@ To remove old reports and force a rebuild you can run
```
./mvnw clean
```
#### Note on integration tests
Integration tests (using testcontainers) will not use /api in request paths.
They ignore ```server.servlet.context-path=/api```.
13 changes: 9 additions & 4 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,19 +64,19 @@
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.16.3</version>
<version>1.17.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>postgresql</artifactId>
<version>1.16.3</version>
<version>1.17.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.16.3</version>
<version>1.17.1</version>
<scope>test</scope>
</dependency>
<dependency>
Expand Down Expand Up @@ -108,8 +108,13 @@
<version>4.5.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
<version>7.0.4.Final</version>
</dependency>

</dependencies>
</dependencies>

<build>
<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ class DataSourceConfig {
@Bean
fun getDataSource(): DataSource {
val dataSourceBuilder = DataSourceBuilder.create()
dataSourceBuilder.driverClassName("org.postgresql.Driver")
dataSourceBuilder.url(getProperty("OSOC_DB_URL", "spring.datasource.url"))
dataSourceBuilder.username(getProperty("OSOC_DB_USERNAME", "spring.datasource.username"))
dataSourceBuilder.password(getProperty("OSOC_DB_PASSWORD", "spring.datasource.password"))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package be.osoc.team1.backend.controllers

import be.osoc.team1.backend.entities.Answer
import be.osoc.team1.backend.entities.Assignment
import be.osoc.team1.backend.entities.Position
import be.osoc.team1.backend.entities.Skill
import be.osoc.team1.backend.entities.StatusSuggestion
import be.osoc.team1.backend.services.AnswerService
import be.osoc.team1.backend.services.AssignmentService
import be.osoc.team1.backend.services.BaseService
import be.osoc.team1.backend.services.PositionService
import be.osoc.team1.backend.services.SkillService
import be.osoc.team1.backend.services.StatusSuggestionService
import org.springframework.security.access.annotation.Secured
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.util.UUID

abstract class BaseController<T, K>(open val service: BaseService<T, K>) {

/**
* Returns the [T] with the corresponding [id]. If no such [T] exists, returns a
* "404: Not Found" message instead.
*/
@GetMapping("/{id}")
@Secured("ROLE_COACH")
fun getById(@PathVariable id: K): T = service.getById(id)
}

abstract class BaseAllController<T, K>(service: BaseService<T, K>) : BaseController<T, K>(service) {

/**
* Returns all objects of type [T].
*/
@GetMapping
@Secured("ROLE_COACH")
fun getAll(): Iterable<T> = service.getAll()
}

@RestController
@RequestMapping("/assignments")
class AssignmentController(service: AssignmentService) : BaseController<Assignment, UUID>(service)

@RestController
@RequestMapping("/positions")
class PositionController(service: PositionService) : BaseController<Position, UUID>(service)

@RestController
@RequestMapping("/statusSuggestions")
class StatusSuggestionController(service: StatusSuggestionService) : BaseController<StatusSuggestion, UUID>(service)

@RestController
@RequestMapping("/answers")
class AnswerController(service: AnswerService) : BaseController<Answer, UUID>(service)

@RestController
@RequestMapping("/skills")
class SkillController(service: SkillService) : BaseAllController<Skill, String>(service)
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,23 @@ package be.osoc.team1.backend.controllers
import be.osoc.team1.backend.entities.Communication
import be.osoc.team1.backend.services.CommunicationService
import be.osoc.team1.backend.services.StudentService
import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.security.access.annotation.Secured
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
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.ResponseStatus
import org.springframework.web.bind.annotation.RestController
import org.springframework.web.servlet.support.ServletUriComponentsBuilder
import java.util.UUID

@RestController
@RequestMapping("/communications")
@RequestMapping("/{edition}/communications")
class CommunicationController(
private val communicationService: CommunicationService,
private val studentService: StudentService
) {

/**
* Gets all communications that belong to a student, if this [studentId] doesn't exist the service will return a 404
*/
@GetMapping("/{studentId}")
@Secured("ROLE_COACH")
fun getCommunicationsByStudentId(@PathVariable studentId: UUID): Collection<Communication> =
studentService.getStudentById(studentId).communications
) : BaseController<Communication, UUID>(communicationService) {

/**
* Add a communication to the database. The communication should be passed in the request body
Expand All @@ -49,15 +38,13 @@ class CommunicationController(
@PostMapping("/{studentId}")
@ResponseStatus(value = HttpStatus.NO_CONTENT)
@Secured("ROLE_COACH")
fun createCommunication(@PathVariable studentId: UUID, @RequestBody communication: Communication): ResponseEntity<Void> {
val id = communicationService.createCommunication(communication)
communication.id = id
studentService.addCommunicationToStudent(studentId, communication)
val location = ServletUriComponentsBuilder
.fromCurrentRequest()
.path("/{id}")
.buildAndExpand(id)
.toUriString()
return ResponseEntity.status(HttpStatus.CREATED).header(HttpHeaders.LOCATION, location).build()
fun createCommunication(
@PathVariable studentId: UUID,
@PathVariable edition: String,
@RequestBody communication: Communication
): ResponseEntity<Communication> {
val createdCommunication = communicationService.createCommunication(communication)
studentService.addCommunicationToStudent(studentId, communication, edition)
return getObjectCreatedResponse(createdCommunication.id, createdCommunication)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package be.osoc.team1.backend.controllers

import org.springframework.http.HttpHeaders
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import org.springframework.web.servlet.support.ServletUriComponentsBuilder

/**
* Utility method that takes an object that was just created by a service method and it's [id],
* and returns a [ResponseEntity] with the [HttpStatus.CREATED] status containing the [createdObject] in the body.
* Additionally, the location header will be set to the path of the POST request that requested the creation
* of the object, with the given [id] added at the end.
*
* For example, if the path to the POST request is:
*
* `/api/students`
*
* Then the location header will contain:
*
* `/api/students/(INSERT ID)`
*/
fun <ID, T> getObjectCreatedResponse(id: ID, createdObject: T, status: HttpStatus = HttpStatus.CREATED): ResponseEntity<T> {
val postRequestPath = ServletUriComponentsBuilder.fromCurrentRequest()
val pathWithIdAdded = postRequestPath.path("/{id}").buildAndExpand(id).toUriString()
return ResponseEntity
.status(status)
.header(HttpHeaders.LOCATION, pathWithIdAdded)
.body(createdObject)
}
Loading

0 comments on commit 35f27bc

Please sign in to comment.