Skip to content

Commit

Permalink
release: v0.44.0 (#151)
Browse files Browse the repository at this point in the history
* fix: Add submissions limits (#140)

* fix(submissions): Rate limit students submissions

* refactor: Remove files deletion error logs table

* fix(submissions): Validate if the laboratory is open

* test(submissions): Add test to ensure students can receive real time updates about their submissions

* refactor: Create static files repository implementation (#141)

* fix: Update SSE controller (#144)

* feat: Delete rubric (#147)

* fix(db): Add missing on delete cascade statement

* feat(rubrics): Delete rubric by UUID

* test: Add test to ensure teachers can delete rubrics

* fix(tests): Close SSE connections early in testing environment

* feat: Get progress of students in laboratory (#149)

* fix(submissions): Add missing `where` on `update` clause

* feat(db): Create new view to obtain students progress in laboratory

* feat(labs): Get students progress

* test(labs): Ensure teachers can obtain the progress of the students in their labs

* docs: Update documentation (#150)

* docs: Update README and md files

* docs(openapi): Update spec

Fix typos and update response of `/progress` endpoint
  • Loading branch information
PedroChaparro authored Jan 11, 2024
1 parent 5f7806e commit 9dc0f8d
Show file tree
Hide file tree
Showing 34 changed files with 643 additions and 78 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/coverage.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
run: docker-compose up -d

- name: Clean and coverage
env:
EXEC_ENVIRONMENT: testing
run: |
export DB_MIGRATIONS_PATH=file://$(pwd)/sql/migrations
go clean -cache
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/integration.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ jobs:
run: docker-compose up -d

- name: Test
env:
EXEC_ENVIRONMENT: testing
run: |
export DB_MIGRATIONS_PATH=file://$(pwd)/sql/migrations
go clean -cache
Expand Down
24 changes: 12 additions & 12 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
## [0.42.1](https://github.com/upb-code-labs/main-api/compare/v0.42.0...v0.42.1) (2024-01-07)
# [0.44.0](https://github.com/upb-code-labs/main-api/compare/v0.43.0...v0.44.0) (2024-01-11)


### Bug Fixes
### Features

* Add submissions limits ([#140](https://github.com/upb-code-labs/main-api/issues/140)) ([b2255a1](https://github.com/upb-code-labs/main-api/commit/b2255a1e68212a788356e57f78504f2e441239f1))
* Get progress of students in laboratory ([#149](https://github.com/upb-code-labs/main-api/issues/149)) ([893017f](https://github.com/upb-code-labs/main-api/commit/893017f0461f978a33d49469b0a2ead25ceb1409))



# [0.42.0](https://github.com/upb-code-labs/main-api/compare/v0.41.0...v0.42.0) (2024-01-06)
# [0.43.0](https://github.com/upb-code-labs/main-api/compare/v0.42.2...v0.43.0) (2024-01-10)


### Features

* Real time submission status ([#138](https://github.com/upb-code-labs/main-api/issues/138)) ([4e879f3](https://github.com/upb-code-labs/main-api/commit/4e879f36655914e51ff835e3266b112c5291c24e))
* Delete rubric ([#147](https://github.com/upb-code-labs/main-api/issues/147)) ([6394ee9](https://github.com/upb-code-labs/main-api/commit/6394ee9deeb2b7e072a65fc2afcabd7dfa000566))



# [0.41.0](https://github.com/upb-code-labs/main-api/compare/v0.40.1...v0.41.0) (2024-01-03)
## [0.42.2](https://github.com/upb-code-labs/main-api/compare/v0.42.1...v0.42.2) (2024-01-09)


### Features
### Bug Fixes

* Submit archive to test block ([#137](https://github.com/upb-code-labs/main-api/issues/137)) ([b000f9b](https://github.com/upb-code-labs/main-api/commit/b000f9b2ab4d1f4863859525e39366de6d8e33e4))
* Update SSE controller ([#144](https://github.com/upb-code-labs/main-api/issues/144)) ([cd6091d](https://github.com/upb-code-labs/main-api/commit/cd6091d3b2d78c369f82bd9ad100b74b1b089421))



## [0.40.1](https://github.com/upb-code-labs/main-api/compare/v0.40.0...v0.40.1) (2024-01-02)
## [0.42.1](https://github.com/upb-code-labs/main-api/compare/v0.42.0...v0.42.1) (2024-01-07)


### Bug Fixes

* Update test block without sending a new test archive ([#135](https://github.com/upb-code-labs/main-api/issues/135)) ([63266f0](https://github.com/upb-code-labs/main-api/commit/63266f07a667844eb0ba7f3263c1bb84678c9ce4))
* Add submissions limits ([#140](https://github.com/upb-code-labs/main-api/issues/140)) ([b2255a1](https://github.com/upb-code-labs/main-api/commit/b2255a1e68212a788356e57f78504f2e441239f1))



# [0.40.0](https://github.com/upb-code-labs/main-api/compare/v0.39.0...v0.40.0) (2023-12-30)
# [0.42.0](https://github.com/upb-code-labs/main-api/compare/v0.41.0...v0.42.0) (2024-01-06)


### Features

* Delete test block ([#132](https://github.com/upb-code-labs/main-api/issues/132)) ([3ddaa80](https://github.com/upb-code-labs/main-api/commit/3ddaa80089b3e88404bfa0f92070d5f1e21722de))
* Real time submission status ([#138](https://github.com/upb-code-labs/main-api/issues/138)) ([4e879f3](https://github.com/upb-code-labs/main-api/commit/4e879f36655914e51ff835e3266b112c5291c24e))



7 changes: 0 additions & 7 deletions CONTRIBUTING.md

This file was deleted.

37 changes: 19 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
# Main API
# Gateway

[![Integration](https://github.com/upb-code-labs/main-api/actions/workflows/integration.yaml/badge.svg?branch=dev)](https://github.com/upb-code-labs/main-api/actions/workflows/integration.yaml)
[![Coverage](https://github.com/upb-code-labs/main-api/actions/workflows/coverage.yaml/badge.svg)](https://github.com/upb-code-labs/main-api/actions/workflows/coverage.yaml)
[![Release](https://github.com/upb-code-labs/main-api/actions/workflows/release.yaml/badge.svg)](https://github.com/upb-code-labs/main-api/actions/workflows/release.yaml)
Welcome to the gateway repository. This service is responsible for the following tasks:

## Development 🧑🏻‍💻
- Authentication
- Authorization
- Serve the REST API
- Send SSE updates to the web client
- Proxy requests to the static files micro-service
- Publish messages to the RabbitMQ submissions queue

### Environment variables
Bellow is a diagram of the overall architecture of the system with the gateway / main api highlighted in green.

| Name | Description |
| ---------------------- | ------------------------------------------ |
| `DB_CONNECTION_STRING` | Connection string to the postgres database |
| `DB_MIGRATIONS_PATH` | Absolute path to the migrations folder |
![Gateway service highlighted with a green rectangle in the overall architecture diagram](./docs/images/gateway-highlighted.jpg)

Environment variables have default values, but you can override them by exporting them in your shell.
## Documentation

```bash
set NAME=VALUE
```
Please, refer to the following documents for more information about the gateway service:

## Coverage 🧪

| [![Sunburst](https://codecov.io/gh/upb-code-labs/main-api/graphs/sunburst.svg?token=Q9QHF616RS)](https://app.codecov.io/gh/upb-code-labs/main-api) | [![square](https://codecov.io/gh/upb-code-labs/main-api/graphs/tree.svg?token=Q9QHF616RS)](https://app.codecov.io/gh/upb-code-labs/main-api) |
| -------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Document | Description |
| --------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| [Contributing](./docs/contributing.md) | Contributing guidelines. |
| [Environment](./docs/environment.md) | A description of the environment variables used by the gateway service. |
| [Bruno Collection](./docs/bruno) | A collection of REST API requests to be used with [Bruno](https://github.com/usebruno/bruno). |
| [Insomnia Collection](./docs/insomnia) | A collection of REST API requests to be used with [Insomnia](https://insomnia.rest/). |
| [OpenAPI Specification](./docs/openapi/spec.openapi.yaml) | A description of the REST API using the [OpenAPI Specification](https://swagger.io/specification/). |
11 changes: 11 additions & 0 deletions __tests__/integration/laboratories_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package integration

import (
"bytes"
"fmt"
"io"
"mime/multipart"
"net/http"
Expand Down Expand Up @@ -102,3 +103,13 @@ func CreateTestBlock(dto *CreateTestBlockUtilsDTO) (response map[string]interfac
jsonResponse := ParseJsonResponse(w.Body)
return jsonResponse, w.Code
}

func GetStudentsProgressInLaboratory(laboratoryUUID string, cookie *http.Cookie) (response map[string]interface{}, statusCode int) {
endpoint := fmt.Sprintf("/api/v1/laboratories/%s/progress", laboratoryUUID)
w, r := PrepareRequest("GET", endpoint, nil)
r.AddCookie(cookie)
router.ServeHTTP(w, r)

jsonResponse := ParseJsonResponse(w.Body)
return jsonResponse, w.Code
}
109 changes: 109 additions & 0 deletions __tests__/integration/laboratorires_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,112 @@ func TestCreateTestBlock(t *testing.T) {
// c.Equal(http.StatusCreated, status)
c.Contains(response, "uuid")
}

func TestGetStudentsProgres(t *testing.T) {
c := require.New(t)

// ## Prepare

// Login as a teacher
w, r := PrepareRequest("POST", "/api/v1/session/login", map[string]interface{}{
"email": registeredTeacherEmail,
"password": registeredTeacherPass,
})
router.ServeHTTP(w, r)
cookie := w.Result().Cookies()[0]

// Create a course
courseUUID, status := CreateCourse("Get students progress test - course")
c.Equal(http.StatusCreated, status)

// Create a laboratory
laboratoryCreationResponse, status := CreateLaboratory(cookie, map[string]interface{}{
"name": "Get students progress test - laboratory",
"course_uuid": courseUUID,
"opening_date": "2023-12-01T08:00",
"due_date": "3023-12-01T00:00",
})
laboratoryUUID := laboratoryCreationResponse["uuid"].(string)
c.Equal(http.StatusCreated, status)

// Add a student to the course
invitationCode, code := GetInvitationCode(courseUUID)
c.Equal(http.StatusOK, code)
c.NotEmpty(invitationCode)

_, code = AddStudentToCourse(invitationCode)
c.Equal(http.StatusOK, code)

// Get languages list
languagesResponse, status := GetSupportedLanguages(cookie)
c.Equal(http.StatusOK, status)

languages := languagesResponse["languages"].([]interface{})
c.Greater(len(languages), 0)

firstLanguage := languages[0].(map[string]interface{})
firstLanguageUUID := firstLanguage["uuid"].(string)

// Create a test block
zipFile, err := GetSampleTestsArchive()
c.Nil(err)

blockCreationResponse, status := CreateTestBlock(&CreateTestBlockUtilsDTO{
laboratoryUUID: laboratoryUUID,
languageUUID: firstLanguageUUID,
blockName: "Get students progress test - block",
cookie: cookie,
testFile: zipFile,
})
c.Equal(http.StatusCreated, status)
testBlockUUID := blockCreationResponse["uuid"].(string)

// Login as a student
w, r = PrepareRequest("POST", "/api/v1/session/login", map[string]interface{}{
"email": registeredStudentEmail,
"password": registeredStudentPass,
})
router.ServeHTTP(w, r)
cookie = w.Result().Cookies()[0]

// Submit a solution
zipFile, err = GetSampleSubmissionArchive()
c.Nil(err)

_, status = SubmitSolutionToTestBlock(&SubmitSToTestBlockUtilsDTO{
blockUUID: testBlockUUID,
file: zipFile,
cookie: cookie,
})
c.Equal(http.StatusCreated, status)

// ## Test

// Login as a teacher again
w, r = PrepareRequest("POST", "/api/v1/session/login", map[string]interface{}{
"email": registeredTeacherEmail,
"password": registeredTeacherPass,
})
router.ServeHTTP(w, r)
cookie = w.Result().Cookies()[0]

// Get the students progress
response, status := GetStudentsProgressInLaboratory(laboratoryUUID, cookie)
c.Equal(http.StatusOK, status)

totalTestBlocks := response["total_test_blocks"].(float64)
studentsProgress := response["students_progress"].([]interface{})
c.Equal(1, int(totalTestBlocks))
c.Equal(1, len(studentsProgress))

studentProgress := studentsProgress[0].(map[string]interface{})
studentPendingSubmissionsCount := studentProgress["pending_submissions"].(float64)
studentRunningSubmissionsCount := studentProgress["running_submissions"].(float64)
studentFailingSubmissionsCount := studentProgress["failing_submissions"].(float64)
StudentSuccessSubmissionsCount := studentProgress["success_submissions"].(float64)

c.GreaterOrEqual(int(studentPendingSubmissionsCount), 0)
c.GreaterOrEqual(int(studentRunningSubmissionsCount), 0)
c.GreaterOrEqual(int(studentFailingSubmissionsCount), 0)
c.GreaterOrEqual(int(StudentSuccessSubmissionsCount), 0)
}
46 changes: 46 additions & 0 deletions __tests__/integration/rubrics_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,52 @@ func TestGetRubricByUUID(t *testing.T) {
}
}

func TestDeleteRubric(t *testing.T) {
c := require.New(t)

// Login as a teacher
w, r := PrepareRequest("POST", "/api/v1/session/login", map[string]interface{}{
"email": secondRegisteredTeacherEmail,
"password": secondRegisteredTeacherPass,
})
router.ServeHTTP(w, r)
cookie := w.Result().Cookies()[0]

// Create a rubric
response, status := CreateRubric(cookie, map[string]interface{}{
"name": "Delete rubric test - Rubric",
})
c.Equal(http.StatusCreated, status)
rubricUUID := response["uuid"].(string)

// Test cases
testCases := []GenericTestCase{
GenericTestCase{
Payload: map[string]interface{}{
"rubricUUID": "not-valid-uuid",
},
ExpectedStatusCode: http.StatusBadRequest,
},
GenericTestCase{
Payload: map[string]interface{}{
"rubricUUID": rubricUUID,
},
ExpectedStatusCode: http.StatusNoContent,
},
GenericTestCase{
Payload: map[string]interface{}{
"rubricUUID": rubricUUID,
},
ExpectedStatusCode: http.StatusNotFound,
},
}

for _, testCase := range testCases {
_, status := DeleteRubric(cookie, testCase.Payload["rubricUUID"].(string))
c.Equal(testCase.ExpectedStatusCode, status)
}
}

func TestUpdateRubricName(t *testing.T) {
c := require.New(t)

Expand Down
9 changes: 9 additions & 0 deletions __tests__/integration/rubrics_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ func GetRubricByUUID(cookie *http.Cookie, uuid string) (response map[string]inte
return ParseJsonResponse(w.Body), w.Code
}

func DeleteRubric(cookie *http.Cookie, uuid string) (response map[string]interface{}, status int) {
endpoint := "/api/v1/rubrics/" + uuid
w, r := PrepareRequest("DELETE", endpoint, nil)
r.AddCookie(cookie)
router.ServeHTTP(w, r)

return ParseJsonResponse(w.Body), w.Code
}

func UpdateRubricName(cookie *http.Cookie, uuid string, payload map[string]interface{}) (response map[string]interface{}, status int) {
w, r := PrepareRequest("PATCH", "/api/v1/rubrics/"+uuid+"/name", payload)
r.AddCookie(cookie)
Expand Down
2 changes: 1 addition & 1 deletion docs/bruno/laboratories/create-laboratory.bru
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ body:json {
"course_uuid": "229e3b99-93b4-47e7-83d2-0d0471fc2261",
"name": "Binary Tree",
"opening_date": "2023-12-01T12:00",
"due_date": "2023-12-02T00:00"
"due_date": "2024-12-02T00:00"
}
}
11 changes: 11 additions & 0 deletions docs/bruno/laboratories/get-students-progress.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
meta {
name: get-students-progress
type: http
seq: 5
}

get {
url: {{BASE_URL}/laboratoryes/}2e6be1e3-389d-4f37-b9d4-711d8de86fb8/progress
body: none
auth: none
}
11 changes: 11 additions & 0 deletions docs/bruno/rubrics/delete-rubric.bru
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
meta {
name: delete-rubric
type: http
seq: 11
}

delete {
url: {{BASE_URL}}/rubrics/e1d8fefa-e6ce-44de-ab23-66f9bde2ccbb
body: none
auth: none
}
Loading

0 comments on commit 9dc0f8d

Please sign in to comment.