Skip to content

Commit

Permalink
Merge pull request #75 from deco-finter/docs/documentation
Browse files Browse the repository at this point in the history
Added documentation
  • Loading branch information
daystram committed Oct 23, 2021
2 parents e431b0c + 7170f21 commit bce8b8d
Show file tree
Hide file tree
Showing 51 changed files with 245 additions and 48 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@
- Guided walkthrough
- Audio annotations and TTS (Text-to-Speech)

## External Links
This project is hosted on a VPS, deployed and running via Docker containers. Source code is hosted on GitHub, and static code analysis is run by SonarCloud to ensure code maintainability.
- [Fableous](https://fableous.daystram.com)
- [GitHub](https://github.com/deco-finter/fableous)
- [DockerHub](https://hub.docker.com/r/daystram/fableous)
- [SonarCloud](https://sonarcloud.io/project/overview?id=deco-finter_fableous)

## Service

The application is divided into two parts:
Expand Down
5 changes: 5 additions & 0 deletions fableous-be/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,20 @@ import (
"github.com/spf13/viper"
)

// AppConfig is a global reference to the application config.
var AppConfig Config

// Config is the base application configuration struct.
type Config struct {
Version string
Port int
Environment string
Debug bool

// Directory to store static gallery files
StaticDir string

// PostgreSQL database configuration
DBHost string
DBPort int
DBDatabase string
Expand All @@ -25,6 +29,7 @@ type Config struct {
JWTSecret string
}

// InitializeAppConfig loads AppConfig from environment variables.
func InitializeAppConfig() {
viper.SetConfigName(".env") // allow directly reading from .env file
viper.SetConfigType("env")
Expand Down
1 change: 1 addition & 0 deletions fableous-be/constants/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ import (
)

const (
// AuthenticationTimeout is the expiry duration for issued JWT tokens.
AuthenticationTimeout = time.Hour * 24 * 2
)
1 change: 1 addition & 0 deletions fableous-be/constants/classroom.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package constants

const (
// ClassroomTokenLength is the length of the session token.
ClassroomTokenLength = 4
)
6 changes: 5 additions & 1 deletion fableous-be/constants/router.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package constants

const (
// RouterKeyIsAuthenticated is the key for the request authentication status injected by the auth middleware.
RouterKeyIsAuthenticated = "is_authenticated"
RouterKeyUserID = "user_id"

// RouterKeyUserID is the key for the requesting userID injected by the auth middleware.
// Empty if the request is not authenticated.
RouterKeyUserID = "user_id"
)
2 changes: 2 additions & 0 deletions fableous-be/controllers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/handlers"
)

// POSTLogin handles login request.
func POSTLogin(c *gin.Context) {
var err error
var user datatransfers.UserLogin
Expand All @@ -26,6 +27,7 @@ func POSTLogin(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{})
}

// POSTRegister handles register request.
func POSTRegister(c *gin.Context) {
var err error
var user datatransfers.UserSignup
Expand Down
25 changes: 15 additions & 10 deletions fableous-be/controllers/classroom.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,31 @@ import (
"github.com/deco-finter/fableous/fableous-be/handlers"
)

func GETClassroom(c *gin.Context) {
// GETClassroomList handles classroom list request.
func GETClassroomList(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
classroomInfo.ID = c.Param("classroom_id")
if classroomInfo, err = handlers.Handler.ClassroomGetOneByID(classroomInfo.ID); err != nil {
var classroomInfos []datatransfers.ClassroomInfo
userID := c.GetString(constants.RouterKeyUserID)
if classroomInfos, err = handlers.Handler.ClassroomGetAllByUserID(userID); err != nil {
c.JSON(http.StatusNotFound, datatransfers.Response{Error: "cannot find classroom"})
return
}
c.JSON(http.StatusOK, datatransfers.Response{Data: classroomInfo})
c.JSON(http.StatusOK, datatransfers.Response{Data: classroomInfos})
}

func GETClassroomList(c *gin.Context) {
// GETClassroom handles classroom detail request.
func GETClassroom(c *gin.Context) {
var err error
var classroomInfos []datatransfers.ClassroomInfo
userID := c.GetString(constants.RouterKeyUserID)
if classroomInfos, err = handlers.Handler.ClassroomGetAllByUserID(userID); err != nil {
var classroomInfo datatransfers.ClassroomInfo
classroomInfo.ID = c.Param("classroom_id")
if classroomInfo, err = handlers.Handler.ClassroomGetOneByID(classroomInfo.ID); err != nil {
c.JSON(http.StatusNotFound, datatransfers.Response{Error: "cannot find classroom"})
return
}
c.JSON(http.StatusOK, datatransfers.Response{Data: classroomInfos})
c.JSON(http.StatusOK, datatransfers.Response{Data: classroomInfo})
}

// POSTClassroom handles classroom creation request.
func POSTClassroom(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand All @@ -47,6 +50,7 @@ func POSTClassroom(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: classroomInfo.ID})
}

// PUTClassroom handles classroom update request.
func PUTClassroom(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand All @@ -69,6 +73,7 @@ func PUTClassroom(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{})
}

// DELETEClassroom handles classroom deletion request.
func DELETEClassroom(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand Down
1 change: 1 addition & 0 deletions fableous-be/controllers/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/utils"
)

// InitializeRouter initialize the gin router.
func InitializeRouter() (router *gin.Engine) {
router = gin.Default()
router.Use(
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/controllers/middleware/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/handlers"
)

// AuthMiddleware is a middleware that checks for a valid JWT token.
func AuthMiddleware(c *gin.Context) {
var token string
if token = strings.TrimPrefix(c.GetHeader("Authorization"), "Bearer "); token == "" {
Expand All @@ -38,6 +39,7 @@ func AuthMiddleware(c *gin.Context) {
c.Next()
}

// parseToken parses a JWT token and returns the claims.
func parseToken(tokenString, secret string) (claims datatransfers.JWTClaims, err error) {
if token, err := jwt.ParseWithClaims(tokenString, &claims, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil
Expand Down
1 change: 1 addition & 0 deletions fableous-be/controllers/middleware/cors.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/gin-gonic/gin"
)

// CORSMiddleware allows cross-origin resource sharing.
func CORSMiddleware(c *gin.Context) {
cors.New(cors.Config{
AllowOrigins: []string{"*"},
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/controllers/ping.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import (
"github.com/deco-finter/fableous/fableous-be/config"
)

// GETPing is a healthcheck endpoint.
// It reponds with the application version.
func GETPing(c *gin.Context) {
c.JSON(http.StatusOK, map[string]string{"version": config.AppConfig.Version})
}
7 changes: 7 additions & 0 deletions fableous-be/controllers/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/handlers"
)

// GETSessionList handles session list for a classroom request.
func GETSessionList(c *gin.Context) {
var err error
var sessionInfos []datatransfers.SessionInfo
Expand All @@ -24,6 +25,7 @@ func GETSessionList(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: sessionInfos})
}

// GETSession handles session detail request.
func GETSession(c *gin.Context) {
var err error
var sessionInfo datatransfers.SessionInfo
Expand All @@ -37,6 +39,8 @@ func GETSession(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: sessionInfo})
}

// GETOngoinSession handles ongoing session request.
// 404 if no ongoing session is found.
func GETOngoingSession(c *gin.Context) {
var err error
var sessionInfo datatransfers.SessionInfo
Expand All @@ -50,6 +54,7 @@ func GETOngoingSession(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: sessionInfo})
}

// POSTSession handles session creation request.
func POSTSession(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand Down Expand Up @@ -84,6 +89,7 @@ func POSTSession(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: sessionInfo.ID})
}

// PUTSession handles session update request.
func PUTSession(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand Down Expand Up @@ -112,6 +118,7 @@ func PUTSession(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{})
}

// DELETESession handles session deletion request.
func DELETESession(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/controllers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/handlers"
)

// GETUser handles user detail request.
func GETUser(c *gin.Context) {
var err error
var userInfo datatransfers.UserInfo
Expand All @@ -20,6 +21,7 @@ func GETUser(c *gin.Context) {
c.JSON(http.StatusOK, datatransfers.Response{Data: userInfo})
}

// PUTUser handles user update request.
func PUTUser(c *gin.Context) {
var err error
var user datatransfers.UserUpdate
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/controllers/websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
pb "github.com/deco-finter/fableous/fableous-be/protos"
)

// GETConnectHubWS handles WebSocket connection from the hub.
func GETConnectHubWS(c *gin.Context) {
var err error
var classroomInfo datatransfers.ClassroomInfo
Expand All @@ -30,6 +31,7 @@ func GETConnectHubWS(c *gin.Context) {
_ = handlers.Handler.ConnectHubWS(c, classroomInfo.ID)
}

// GETConnectControllerWS handles WebSocket connection from the controller.
func GETConnectControllerWS(c *gin.Context) {
var err error
var classroomToken string
Expand Down
1 change: 1 addition & 0 deletions fableous-be/datatransfers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"time"
)

// JWTClaims is the JWT claims struct.
type JWTClaims struct {
ID string `json:"sub,omitempty"`
ExpiresAt int64 `json:"exp,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions fableous-be/datatransfers/classroom.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"time"
)

// ClassroomInfo is the data transfer object for the Classroom entity.
type ClassroomInfo struct {
ID string `json:"id" binding:"-"`
UserID string `json:"-" binding:"-"`
Expand Down
1 change: 1 addition & 0 deletions fableous-be/datatransfers/response.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package datatransfers

// Response is the API response wrapper.
type Response struct {
Code int `json:"code,omitempty"`
Data interface{} `json:"data,omitempty"`
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/datatransfers/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package datatransfers

import "time"

// SessionUpdate is the data transfer object used for updating the Session entity.
type SessionUpdate struct {
ID string `json:"id" binding:"-"`
ClassroomID string `json:"-" binding:"-"`
Title string `json:"title" binding:"required"`
Description string `json:"description" binding:"required"`
}

// SessionInfo is the data transfer object for the Session entity.
type SessionInfo struct {
ID string `json:"id" binding:"-"`
ClassroomID string `json:"-" binding:"-"`
Expand Down
4 changes: 4 additions & 0 deletions fableous-be/datatransfers/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,26 @@ import (
"time"
)

// UserLogin is the data transfer object used for logging in a user.
type UserLogin struct {
Email string `json:"email" binding:"required"`
Password string `json:"password" binding:"required"`
}

// UserSignup is the data transfer object used for signing up a new user.
type UserSignup struct {
Name string `json:"name" binding:"required"`
Email string `json:"email" binding:"required"`
Password string `json:"password" binding:"required"`
}

// UserUpdate is the data transfer object used for updating the User entity.
type UserUpdate struct {
Name string `json:"name" binding:"-"`
Email string `json:"email" binding:"-"`
}

// UserInfo is the data transfer object for the User entity.
type UserInfo struct {
ID string `json:"id" uri:"id"`
Name string `json:"name"`
Expand Down
2 changes: 2 additions & 0 deletions fableous-be/handlers/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/models"
)

// Authenticate issues a token for the given user credentials
func (m *module) Authenticate(credentials datatransfers.UserLogin) (token string, err error) {
var user models.User
if user, err = m.db.userOrmer.GetOneByEmail(credentials.Email); err != nil {
Expand All @@ -24,6 +25,7 @@ func (m *module) Authenticate(credentials datatransfers.UserLogin) (token string
return generateToken(user)
}

// generateToken generates a JWT token for the given user
func generateToken(user models.User) (string, error) {
now := time.Now()
expiry := time.Now().Add(constants.AuthenticationTimeout)
Expand Down
6 changes: 6 additions & 0 deletions fableous-be/handlers/classroom.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/deco-finter/fableous/fableous-be/models"
)

// ClassroomGetByID returns a classroom by its ID.
func (m *module) ClassroomGetOneByID(id string) (classroomInfo datatransfers.ClassroomInfo, err error) {
var classroom models.Classroom
if classroom, err = m.db.classroomOrmer.GetOneByID(id); err != nil {
Expand All @@ -25,6 +26,7 @@ func (m *module) ClassroomGetOneByID(id string) (classroomInfo datatransfers.Cla
return
}

// ClassroomGetAllByUserID returns all classrooms owned by a user.
func (m *module) ClassroomGetAllByUserID(userID string) (classroomInfos []datatransfers.ClassroomInfo, err error) {
var classrooms []models.Classroom
classroomInfos = make([]datatransfers.ClassroomInfo, 0)
Expand All @@ -44,6 +46,7 @@ func (m *module) ClassroomGetAllByUserID(userID string) (classroomInfos []datatr
return
}

// ClassroomInsert inserts a new classroom.
func (m *module) ClassroomInsert(classroomInfo datatransfers.ClassroomInfo) (classroomID string, err error) {
if classroomID, err = m.db.classroomOrmer.Insert(models.Classroom{
UserID: classroomInfo.UserID,
Expand All @@ -54,6 +57,7 @@ func (m *module) ClassroomInsert(classroomInfo datatransfers.ClassroomInfo) (cla
return
}

// ClassroomUpdate updates a classroom.
func (m *module) ClassroomUpdate(classroomInfo datatransfers.ClassroomInfo) (err error) {
if err = m.db.classroomOrmer.Update(models.Classroom{
ID: classroomInfo.ID,
Expand All @@ -64,6 +68,8 @@ func (m *module) ClassroomUpdate(classroomInfo datatransfers.ClassroomInfo) (err
return
}

// ClassroomDeleteByID deletes a classroom by its ID.
// It also stops any ongoing session and removes all its sessions' static files.
func (m *module) ClassroomDeleteByID(classroomID string) (err error) {
m.sessions.mutex.Lock()
for classroomToken, sess := range m.sessions.keys {
Expand Down

0 comments on commit bce8b8d

Please sign in to comment.