Skip to content

Commit

Permalink
feat: HandleDashboardUserPostLogin API
Browse files Browse the repository at this point in the history
  • Loading branch information
Yatanvesh committed Aug 20, 2023
1 parent 40e1c98 commit 5d965ce
Show file tree
Hide file tree
Showing 15 changed files with 524 additions and 117 deletions.
7 changes: 7 additions & 0 deletions .idea/sqldialects.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ repos:
rev: 'v1.54.1'
hooks:
- id: golangci-lint
args: ['--timeout', '3m0s']
2 changes: 2 additions & 0 deletions Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
version: '3'

includes:
win: ./Taskfile_windows.yaml
tasks:
# repository management
install-pre-commit:
Expand Down
6 changes: 6 additions & 0 deletions Taskfile_windows.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: '3'

tasks:
sqlc-generate:
cmds:
- docker run --rm -v ${PWD}:/src -w /src kjconroy/sqlc generate
2 changes: 1 addition & 1 deletion docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ services:
start_period: 5s
dashboard-backend:
build:
dockerfile: Dockerfile
dockerfile: docker/Dockerfile
context: .
args:
BUILD_TARGET: dashboard-backend
Expand Down
1 change: 0 additions & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ WORKDIR /go/src/app
ARG BUILD_TARGET
COPY go.mod go.sum ./
RUN go mod download
COPY db db
COPY go-shared lib
COPY go-services/$BUILD_TARGET services/$BUILD_TARGET
RUN CGO_ENABLED=0 go build -o /go/bin/app github.com/basemind-ai/monorepo/go-services/$BUILD_TARGET
Expand Down
71 changes: 62 additions & 9 deletions go-services/dashboard-backend/api/api.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,80 @@
package api

import (
"net/http"

"github.com/basemind-ai/monorepo/go-services/dashboard-backend/config"
"github.com/basemind-ai/monorepo/go-services/dashboard-backend/constants"
"github.com/basemind-ai/monorepo/go-shared/apierror"
"github.com/basemind-ai/monorepo/go-shared/db"
"github.com/basemind-ai/monorepo/go-shared/serialization"
"github.com/rs/zerolog/log"
"net/http"

"github.com/go-chi/chi/v5"
)

func HandleDashboardUserPostLogin(w http.ResponseWriter, r *http.Request) {
firebaseId := r.Context().Value(constants.FireBaseIdContextKey).(string)

if userExists, queryErr := db.GetQueries().CheckUserExists(r.Context(), firebaseId); queryErr != nil {
// respond with internal server error
panic("not implemented")
log.Error().Err(queryErr).Msg("failed to retrieve user")
_ = apierror.InternalServerError().Render(w, r)
} else if !userExists {
// insert a new user here and create a default project for the user connected with an owner level permission
// response with the user (DB id, project and project permission)
panic("not implemented")
user, queryErr := db.GetQueries().CreateUser(r.Context(), firebaseId)
if queryErr != nil {
log.Error().Err(queryErr).Msg("failed to create user")
_ = apierror.InternalServerError().Render(w, r)
return
}

project, queryErr := db.GetQueries().CreateProject(r.Context(), db.CreateProjectParams{Name: "Default Project", Description: "Default Project"})
if queryErr != nil {
log.Error().Err(queryErr).Msg("failed to create project")
_ = apierror.InternalServerError().Render(w, r)
return
}

userProject, queryErr := db.GetQueries().CreateUserProject(r.Context(), db.CreateUserProjectParams{
UserID: user.ID,
ProjectID: project.ID,
Permission: db.AccessPermissionTypeADMIN,
IsUserDefaultProject: true,
})
if queryErr != nil {
log.Error().Err(queryErr).Msg("failed to create user project mapping")
_ = apierror.InternalServerError().Render(w, r)
return
}

var userProjects = []db.FindProjectsByUserIdRow{{
ID: project.ID,
CreatedAt: project.CreatedAt,
Name: project.Name,
Description: project.Description,
Permission: userProject.Permission,
IsUserDefaultProject: userProject.IsUserDefaultProject,
}}

responseDTO := HandleDashboardUserPostLoginDTO{User: user, Projects: userProjects}

_ = serialization.RenderJsonResponse(w, http.StatusCreated, responseDTO)
} else {
// retrieve the user and project from the db and return them as a response with the permission
panic("not implemented")
user, queryErr := db.GetQueries().FindUserByFirebaseId(r.Context(), firebaseId)
if queryErr != nil {
log.Error().Err(queryErr).Msg("failed to find user")
_ = apierror.InternalServerError().Render(w, r)
return
}

userProjects, queryErr := db.GetQueries().FindProjectsByUserId(r.Context(), user.ID)
if queryErr != nil {
log.Error().Err(queryErr).Msg("failed to find user projects")
_ = apierror.InternalServerError().Render(w, r)
return
}

responseDTO := HandleDashboardUserPostLoginDTO{User: user, Projects: userProjects}

_ = serialization.RenderJsonResponse(w, http.StatusOK, responseDTO)
}
}

Expand Down
8 changes: 8 additions & 0 deletions go-services/dashboard-backend/api/models.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package api

import "github.com/basemind-ai/monorepo/go-shared/db"

type HandleDashboardUserPostLoginDTO struct {
User db.User `json:"user"`
Projects []db.FindProjectsByUserIdRow `json:"projects"`
}
26 changes: 17 additions & 9 deletions go-shared/apierror/apierror.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package apierror

import (
"net/http"
"reflect"

"github.com/basemind-ai/monorepo/go-shared/serialization"
)
Expand All @@ -16,22 +17,29 @@ func (e *ApiError) Render(w http.ResponseWriter, r *http.Request) error {
return serialization.RenderJsonResponse(w, e.StatusCode, e)
}

func NewApiError(message string, statusCode int) *ApiError {
func NewApiError(statusCode int, args ...interface{}) *ApiError {
var message string
if l := len(args); l == 1 && reflect.TypeOf(args[0]).Kind() == reflect.String {
message = args[0].(string)
} else {
message = http.StatusText(statusCode)
}

return &ApiError{StatusCode: statusCode, Message: message, StatusText: http.StatusText(statusCode)}
}

func BadRequest(message string) *ApiError {
return NewApiError(message, http.StatusBadRequest)
func BadRequest(message ...interface{}) *ApiError {
return NewApiError(http.StatusBadRequest, message...)
}

func Unauthorized(message string) *ApiError {
return NewApiError(message, http.StatusUnauthorized)
func Unauthorized(message ...interface{}) *ApiError {
return NewApiError(http.StatusUnauthorized, message...)
}

func UnprocessableContent(message string) *ApiError {
return NewApiError(message, http.StatusUnprocessableEntity)
func UnprocessableContent(message ...interface{}) *ApiError {
return NewApiError(http.StatusUnprocessableEntity, message...)
}

func InternalServerError(message string) *ApiError {
return NewApiError(message, http.StatusInternalServerError)
func InternalServerError(message ...interface{}) *ApiError {
return NewApiError(http.StatusInternalServerError, message...)
}
54 changes: 43 additions & 11 deletions go-shared/apierror/apierror_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package apierror_test

import (
"context"
"encoding/json"
"net/http"
"testing"

Expand All @@ -12,32 +13,63 @@ import (
)

func TestApiError(t *testing.T) {
t.Parallel()

for _, testCase := range []struct {
ApiErrType *apierror.ApiError
ExpectedStatus int
ApiErrType *apierror.ApiError
ExpectedStatus int
ExpectedMessage string
}{
{
ApiErrType: apierror.BadRequest("err"),
ExpectedStatus: http.StatusBadRequest,
ApiErrType: apierror.BadRequest("err"),
ExpectedStatus: http.StatusBadRequest,
ExpectedMessage: "err",
},
{
ApiErrType: apierror.BadRequest(),
ExpectedStatus: http.StatusBadRequest,
ExpectedMessage: http.StatusText(http.StatusBadRequest),
},
{
ApiErrType: apierror.Unauthorized("err"),
ExpectedStatus: http.StatusUnauthorized,
ExpectedMessage: "err",
},
{
ApiErrType: apierror.Unauthorized("err"),
ExpectedStatus: http.StatusUnauthorized,
ApiErrType: apierror.Unauthorized(),
ExpectedStatus: http.StatusUnauthorized,
ExpectedMessage: http.StatusText(http.StatusUnauthorized),
},
{
ApiErrType: apierror.UnprocessableContent("err"),
ExpectedStatus: http.StatusUnprocessableEntity,
ApiErrType: apierror.UnprocessableContent("err"),
ExpectedStatus: http.StatusUnprocessableEntity,
ExpectedMessage: "err",
},
{
ApiErrType: apierror.InternalServerError("err"),
ExpectedStatus: http.StatusInternalServerError,
ApiErrType: apierror.UnprocessableContent(),
ExpectedStatus: http.StatusUnprocessableEntity,
ExpectedMessage: http.StatusText(http.StatusUnprocessableEntity),
},
{
ApiErrType: apierror.InternalServerError("err"),
ExpectedStatus: http.StatusInternalServerError,
ExpectedMessage: "err",
},
{
ApiErrType: apierror.InternalServerError(),
ExpectedStatus: http.StatusInternalServerError,
ExpectedMessage: http.StatusText(http.StatusInternalServerError),
},
} {
client := testutils.CreateTestClient(t, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_ = testCase.ApiErrType.Render(w, r)
}))
res, err := client.Get(context.TODO(), "/")
assert.Nil(t, err)
assert.Equal(t, res.StatusCode, testCase.ExpectedStatus)
assert.Equal(t, testCase.ExpectedStatus, res.StatusCode)

var body apierror.ApiError
_ = json.Unmarshal(res.Body, &body)
assert.Equal(t, testCase.ExpectedMessage, body.Message)
}
}
Loading

0 comments on commit 5d965ce

Please sign in to comment.