Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Fabian Vitt
good2go
Commits
94bfe152
Commit
94bfe152
authored
Jun 04, 2020
by
Enrico Bollen
💬
Browse files
Merge branch 'dev' into 'master'
Dev See merge request
!33
parents
f4e7774a
ecb358bc
Pipeline
#1854
failed with stages
in 54 seconds
Changes
37
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
.gitlab-ci.yml
View file @
94bfe152
...
...
@@ -73,6 +73,9 @@ production:
before_script
:
-
gem install dpl
image
:
ruby:latest
environment
:
name
:
"
Production"
url
:
"
https://go-hard-or-go-home.herokuapp.com/"
script
:
-
dpl --provider=heroku --app=$HEROKU_APP_PRODUCTION --api-key=$HEROKU_API_KEY
only
:
...
...
@@ -81,6 +84,9 @@ production:
staging
:
stage
:
deploy
image
:
ruby:latest
environment
:
name
:
"
Staging"
url
:
"
https://go-hard-or-go-home-staging.herokuapp.com/"
before_script
:
-
gem install dpl
script
:
...
...
Makefile
View file @
94bfe152
...
...
@@ -15,8 +15,6 @@ coverage:
build
:
go build
-o
.
./cmd/main.go
clean
:
# Need to install reflex
# go get github.com/cespare/reflex
watch
:
...
...
README.md
View file @
94bfe152
# Good2Go – Room
b
ooking
# Good2Go – Room
B
ooking
[
Error Tracking
](
https://git.coco.study/fvitt/good2go/-/error_tracking
)
[
Coverage Report
](
https://fvitt.pages.coco.study/good2go/master/coverage
)
...
...
api/rest/README.md
View file @
94bfe152
...
...
@@ -10,7 +10,7 @@ RestAPI Module
## Components
The api module is sep
e
rated into three major components
The api module is sep
a
rated into three major components
### Router
...
...
api/rest/controllers/appointment_controller.go
deleted
100644 → 0
View file @
f4e7774a
package
controllers
import
"time"
// CreateAppointment creates an appointment.
func
CreateAppointment
()
{
}
// GetAppointment finds a single appointment by startTime
func
GetAppointment
(
startTime
time
.
Time
)
{
}
// GetAllAppointments returns all the appointments
func
GetAllAppointments
()
{
}
// UpdateAppointment updates a single appointment
func
UpdateAppointment
()
{
}
// DeleteAppointment deletes a single appointment
func
DeleteAppointment
()
{
}
api/rest/controllers/building_controller.go
deleted
100644 → 0
View file @
f4e7774a
package
controllers
// CreateBuilding Creates a single new building
func
CreateBuilding
()
{
// Reservered for future use
}
// GetBuilding gets a single building
func
GetBuilding
()
{
// Reservered for future use
}
// GetAllBuildings Returns all the buildings
func
GetAllBuildings
()
{
// Reservered for future use
}
// UpdateBuilding Updates a single building
func
UpdateBuilding
()
{
// Reservered for future use
}
// DeleteBuilding Deletes a single building
func
DeleteBuilding
(
id
int
)
{
// Reservered for future use
}
api/rest/controllers/room_controller.go
deleted
100644 → 0
View file @
f4e7774a
package
controllers
import
(
m
"git.coco.study/fvitt/good2go/internal/model"
)
// RoomController Controller to handle all types of controller stuff
type
RoomController
struct
{}
// CreateRoom *drumroll* creates a room
func
CreateRoom
(
roomNo
int
,
capacity
int
)
m
.
Room
{
return
m
.
Building
.
AddRoom
(
roomNo
,
capacity
)
}
// GetRoom gets a single room by id
func
GetRoom
(
roomNo
int
)
(
room
*
m
.
Room
,
err
error
)
{
return
m
.
Building
.
GetRoomByNo
(
roomNo
)
}
// GetAllRooms returns all the rooms
func
GetAllRooms
()
[]
*
m
.
Room
{
return
m
.
Building
.
GetRooms
()
}
// UpdateRoom updates a single room
func
UpdateRoom
(
roomNo
int
,
capacity
int
)
(
err
error
)
{
return
m
.
Building
.
UpdateRoomCapacity
(
roomNo
,
capacity
)
}
// DeleteRoom deletes a room by id
func
DeleteRoom
(
roomNo
int
)
{
m
.
Building
.
DeleteRoom
(
roomNo
)
}
api/rest/controllers/room_controller_test.go
deleted
100644 → 0
View file @
f4e7774a
package
controllers
import
(
"reflect"
"testing"
"git.coco.study/fvitt/good2go/internal/model"
)
var
initialRoomAmount
=
0
func
isRoom
(
r
*
model
.
Room
)
bool
{
if
reflect
.
TypeOf
(
r
.
Capacity
)
.
Name
()
!=
"int"
{
return
false
}
if
reflect
.
TypeOf
(
r
.
Number
)
.
Name
()
!=
"int"
{
return
false
}
return
true
}
func
TestCreateRooms
(
t
*
testing
.
T
)
{
room
:=
CreateRoom
(
420
,
69
)
if
room
.
Number
!=
420
{
t
.
Errorf
(
"Returned room didnt have the correct room number."
)
}
if
room
.
Capacity
!=
69
{
t
.
Errorf
(
"Returned room didnt have the correct capacity."
)
}
}
func
TestGetRoom
(
t
*
testing
.
T
)
{
CreateRoom
(
666
,
66
)
room
,
err
:=
GetRoom
(
666
)
if
err
!=
nil
{
t
.
Error
(
err
)
}
if
room
.
Capacity
!=
66
{
t
.
Errorf
(
"first element in getAllRooms[] doesnt seem to be a room"
)
}
if
room
.
Number
!=
666
{
t
.
Errorf
(
"Created room didnt have the correct room number"
)
}
}
func
TestGetAllRooms
(
t
*
testing
.
T
)
{
rooms
:=
GetAllRooms
()
initialRoomAmount
=
len
(
rooms
)
if
initialRoomAmount
>
0
&&
!
isRoom
(
rooms
[
0
])
{
t
.
Errorf
(
"first element in getAllRooms[] doesnt seem to be a room"
)
}
}
func
TestUpdateSingleRoom
(
t
*
testing
.
T
)
{
// GIVEN
CreateRoom
(
34
,
34
)
// WHEN
updateErr
:=
UpdateRoom
(
34
,
90
)
if
updateErr
!=
nil
{
t
.
Error
(
updateErr
)
}
// THEN
room
,
err
:=
GetRoom
(
34
)
if
err
!=
nil
{
t
.
Errorf
(
"Could not find created room"
)
}
if
room
.
Capacity
!=
90
{
t
.
Error
(
"Updated room didnt have the correct capacity"
)
}
}
func
TestDeleteRoom
(
t
*
testing
.
T
)
{
// GIVEN
CreateRoom
(
100
,
100
)
_
,
err
:=
GetRoom
(
100
)
if
err
!=
nil
{
t
.
Error
(
err
.
Error
())
}
// WHEN
DeleteRoom
(
100
)
// THEN
_
,
err
=
GetRoom
(
100
)
if
err
==
nil
{
t
.
Error
(
"Deleted room was not deleted"
)
}
}
api/rest/
router
.go
→
api/rest/
main
.go
View file @
94bfe152
...
...
@@ -9,7 +9,7 @@ import (
"github.com/gorilla/mux"
m
"git.coco.study/fvitt/good2go/api/rest/middlewares"
h
"git.coco.study/fvitt/good2go/api/rest/
sub
route
r
s"
h
"git.coco.study/fvitt/good2go/api/rest/routes"
)
func
getPort
()
string
{
...
...
@@ -26,18 +26,19 @@ func Init() {
// INIT ALL THE THINGS
r
:=
mux
.
NewRouter
()
// Add all the middleware
s
// Add all the middleware
r
.
Use
(
m
.
LogRequests
)
r
.
Use
(
m
.
SentryHandler
)
// Register all the Routers
h
.
RoomRouter
.
AttachRouter
(
r
)
h
.
AppointmentRouter
.
AttachRouter
(
r
)
h
.
RoomRouter
.
AttachRouter
(
r
)
h
.
HomeRouter
.
AttachRouter
(
r
)
// Create a new server
srv
:=
&
http
.
Server
{
Handler
:
r
,
Addr
:
"0.0.0.0:
"
+
getPort
()
,
Addr
:
"0.0.0.0:
8080"
,
// Good practice: enforce timeouts for servers you create!
WriteTimeout
:
5
*
time
.
Second
,
ReadTimeout
:
5
*
time
.
Second
,
...
...
api/rest/middlewares/logger.go
View file @
94bfe152
...
...
@@ -8,7 +8,7 @@ import (
// LogRequests logs requests
func
LogRequests
(
next
http
.
Handler
)
http
.
Handler
{
return
http
.
HandlerFunc
(
func
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
log
.
Println
(
"[REST
-
API] "
+
r
.
Method
+
" request on: "
+
r
.
RequestURI
)
log
.
Println
(
"[RESTAPI] "
+
r
.
Method
+
" request on: "
+
r
.
RequestURI
)
next
.
ServeHTTP
(
w
,
r
)
})
}
api/rest/middlewares/sentry.go
0 → 100644
View file @
94bfe152
package
restapi
import
(
sentryhttp
"github.com/getsentry/sentry-go/http"
)
var
SentryHandler
=
sentryhttp
.
New
(
sentryhttp
.
Options
{})
.
Handle
api/rest/
sub
route
r
s/home_router.go
→
api/rest/routes/home_router.go
View file @
94bfe152
package
restapi
import
(
"encoding/json"
"fmt"
"html"
"net/http"
"github.com/gorilla/mux"
...
...
@@ -18,19 +21,61 @@ var (
var
name
=
"Home"
func
createHome
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Write
([]
byte
(
"Why would you want to create a new /? This one is perfectly fine!"
))
_
,
err
:=
w
.
Write
([]
byte
(
"Why would you want to create a new /? This one is perfectly fine!"
))
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
getHome
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Write
([]
byte
(
"Hello from "
+
name
))
_
,
err
:=
w
.
Write
([]
byte
(
"Hello from "
+
name
))
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
deleteHome
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Write
([]
byte
(
"What are you thinking, you cant delete /, are you crazy!?!?"
))
func
min
(
a
,
b
int
)
int
{
if
a
<
b
{
return
a
}
return
b
}
func
limitString
(
input
string
,
maxLength
int
)
string
{
output
:=
""
runes
:=
[]
rune
(
input
)
length
:=
min
(
len
(
input
),
maxLength
)
for
i
:=
0
;
i
<
length
;
i
++
{
output
+=
string
(
runes
[
i
])
}
return
output
}
func
updateHome
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
r
struct
{
name
string
}
parseBodyErr
:=
json
.
NewDecoder
(
req
.
Body
)
.
Decode
(
&
r
)
if
parseBodyErr
!=
nil
{
http
.
Error
(
res
,
parseBodyErr
.
Error
(),
http
.
StatusBadRequest
)
return
}
name
=
limitString
(
html
.
EscapeString
(
r
.
name
),
20
)
_
,
err
:=
res
.
Write
([]
byte
(
"Updated home: new name "
+
name
+
"!?!?"
))
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
updateHome
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
w
.
Write
([]
byte
(
"What are you thinking, you cant delete /, are you crazy!?!?"
))
func
deleteHome
(
w
http
.
ResponseWriter
,
r
*
http
.
Request
)
{
_
,
err
:=
w
.
Write
([]
byte
(
"What are you thinking, you cant delete /, are you crazy!?!?"
))
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
(
a
homeRouter
)
AttachRouter
(
r
*
mux
.
Router
)
{
...
...
api/rest/
sub
route
r
s/room_router.go
→
api/rest/routes/room_router.go
View file @
94bfe152
...
...
@@ -2,12 +2,14 @@ package restapi
import
(
"encoding/json"
"fmt"
"log"
"net/http"
"strconv"
c
"git.coco.study/fvitt/good2go/api/rest/controllers"
u
"git.coco.study/fvitt/good2go/api/rest/utils"
model
"git.coco.study/fvitt/good2go/internal/model"
"git.coco.study/fvitt/good2go/internal/model"
s
"git.coco.study/fvitt/good2go/internal/services"
"github.com/gorilla/mux"
)
...
...
@@ -19,58 +21,54 @@ var (
)
func
createRoom
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
// Decode the body
var
r
model
.
Room
err
:=
json
.
NewDecoder
(
req
.
Body
)
.
Decode
(
&
r
)
if
err
!=
nil
{
http
.
Error
(
res
,
err
.
Error
(),
http
.
StatusBadRequest
)
return
}
room
,
err
:=
s
.
RoomService
.
CreateRoom
(
&
r
)
if
err
!=
nil
{
http
.
Error
(
res
,
err
.
Error
(),
http
.
StatusBadRequest
)
return
}
room
:=
c
.
CreateRoom
(
r
.
Number
,
r
.
Capacity
)
u
.
SendJSON
(
res
)
.
Encode
(
room
)
err
=
u
.
SendJSON
(
res
)
.
Encode
(
room
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
getRoom
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
var
roomNo
int
roomNo
,
parseErr
:=
strconv
.
Atoi
(
mux
.
Vars
(
req
)[
"roomNo"
])
roomNumberString
:=
mux
.
Vars
(
req
)[
"roomNumber"
]
if
parseErr
==
nil
{
roomNumber
,
_
:=
strconv
.
Atoi
(
roomNumberString
)
room
,
roomErr
:=
c
.
GetRoom
(
roomN
o
)
room
,
roomErr
:=
s
.
RoomService
.
GetRoomByNumber
(
roomN
umber
)
if
roomErr
==
nil
{
u
.
SendJSON
(
res
)
.
Encode
(
room
)
}
else
{
http
.
Error
(
res
,
roomErr
.
Error
(),
http
.
StatusNotFound
)
}
if
roomErr
==
nil
{
u
.
SendJSON
(
res
)
.
Encode
(
room
)
}
else
{
http
.
Error
(
res
,
parse
Err
.
Error
(),
http
.
Status
BadRequest
)
http
.
Error
(
res
,
room
Err
.
Error
(),
http
.
Status
NotFound
)
}
}
func
getAllRooms
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
rooms
:=
c
.
GetAllRooms
()
u
.
SendJSON
(
res
)
.
Encode
(
rooms
)
rooms
:=
s
.
RoomService
.
GetAllRooms
()
err
:=
u
.
SendJSON
(
res
)
.
Encode
(
rooms
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
func
updateRoom
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
// Parse to integer
roomNo
,
parseURLError
:=
strconv
.
Atoi
(
mux
.
Vars
(
req
)[
"roomNo"
])
if
parseURLError
!=
nil
{
http
.
Error
(
res
,
parseURLError
.
Error
(),
http
.
StatusBadRequest
)
return
}
roomNumberString
:=
mux
.
Vars
(
req
)[
"roomNumber"
]
roomNumber
,
_
:=
strconv
.
Atoi
(
roomNumberString
)
// Parse the body
var
r
model
.
Room
parseBodyErr
:=
json
.
NewDecoder
(
req
.
Body
)
.
Decode
(
&
r
)
if
parseBodyErr
!=
nil
{
...
...
@@ -78,9 +76,13 @@ func updateRoom(res http.ResponseWriter, req *http.Request) {
return
}
err
:=
c
.
UpdateRoom
(
roomNo
,
r
.
Capacity
)
room
,
err
:=
s
.
RoomService
.
UpdateRoomCapacity
(
roomNumber
,
r
.
Capacity
)
if
err
==
nil
{
getRoom
(
res
,
req
)
err
:=
u
.
SendJSON
(
res
)
.
Encode
(
room
)
if
err
!=
nil
{
fmt
.
Println
(
err
)
}
}
else
{
http
.
Error
(
res
,
err
.
Error
(),
http
.
StatusNotFound
)
}
...
...
@@ -88,35 +90,35 @@ func updateRoom(res http.ResponseWriter, req *http.Request) {
func
deleteRoom
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
// get the roomNo from the url variables
var
roomNo
int
roomNo
,
urlError
:=
strconv
.
Atoi
(
mux
.
Vars
(
req
)[
"roomNo"
])
if
urlError
!=
nil
{
http
.
Error
(
res
,
urlError
.
Error
(),
http
.
StatusBadRequest
)
return
}
roomNumberString
:=
mux
.
Vars
(
req
)[
"roomNumber"
]
roomNumber
,
_
:=
strconv
.
Atoi
(
roomNumberString
)
c
.
DeleteRoom
(
roomNo
)
err
:=
s
.
RoomService
.
DeleteRoom
(
roomNumber
)
if
err
!=
nil
{
http
.
Error
(
res
,
err
.
Error
(),
http
.
StatusBadRequest
)
log
.
Fatal
(
err
)
}
res
.
Write
([]
byte
(
"deleted room with number "
+
roomNumberString
))
res
.
WriteHeader
(
http
.
StatusOK
)
}
// AttachRouter initialize Router
func
(
a
roomRouter
)
AttachRouter
(
router
*
mux
.
Router
)
{
r
:=
router
.
PathPrefix
(
"/rooms"
)
.
Subrouter
()
//todo addd single room route
multipleR
:=
router
.
PathPrefix
(
"/rooms"
)
.
Subrouter
()
.
StrictSlash
(
true
)
singleR
:=
router
.
PathPrefix
(
"/room"
)
.
Subrouter
()
.
StrictSlash
(
true
)
// CREATE
r
.
HandleFunc
(
"/"
,
createRoom
)
.
Methods
(
"POST"
)
singleR
.
HandleFunc
(
"/"
,
createRoom
)
.
Methods
(
"POST"
)
// READ
r
.
HandleFunc
(
"/{roomN
o
}"
,
getRoom
)
.
Methods
(
"GET"
)
r
.
HandleFunc
(
"/"
,
getAllRooms
)
.
Methods
(
"GET"
)
singleR
.
HandleFunc
(
"/{roomN
umber
}"
,
getRoom
)
.
Methods
(
"GET"
)
multipleR
.
HandleFunc
(
"/"
,
getAllRooms
)
.
Methods
(
"GET"
)
// UPDATE
r
.
HandleFunc
(
"/{roomN
o
}"
,
updateRoom
)
.
Methods
(
"PUT"
)
singleR
.
HandleFunc
(
"/{roomN
umber
}"
,
updateRoom
)
.
Methods
(
"PUT"
)
// DELETE
r
.
HandleFunc
(
"/{roomN
o
}"
,
deleteRoom
)
.
Methods
(
"DELETE"
)
singleR
.
HandleFunc
(
"/{roomN
umber
}"
,
deleteRoom
)
.
Methods
(
"DELETE"
)
}
api/rest/subrouters/appointment_router.go
deleted
100644 → 0
View file @
f4e7774a
package
restapi
import
(
"net/http"
"github.com/gorilla/mux"
)
type
appointmentRouter
struct
{}
var
(
// AppointmentRouter handles appointment requests
AppointmentRouter
=
&
appointmentRouter
{}
)
func
createAppointment
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
}
func
getAppointment
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
}
func
getAllAppointments
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
}
func
updateAppointment
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
}
func
deleteAppointment
(
res
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
}
// AttachRouter Creates and attaches a subrouter to the given routers
func
(
a
appointmentRouter
)
AttachRouter
(
router
*
mux
.
Router
)
{
r
:=
router
.
PathPrefix
(
"/appointments"
)
.
Subrouter
()
// CREATE
r
.
HandleFunc
(
"/"
,
createAppointment
)
.
Methods
(
"POST"
)
// READ
r
.
HandleFunc
(
"/{id}"
,
getAppointment
)
.
Methods
(
"GET"
)
r
.
HandleFunc
(
"/"
,
getAllAppointments
)
.
Methods
(
"GET"
)
// UPDATE
r
.
HandleFunc
(
"/{id}"
,
updateAppointment
)
.
Methods
(
"PUT"
)
// DELETE
r
.
HandleFunc
(
"/{id}"
,
deleteAppointment
)
.
Methods
(
"DELETE"
)
}
cmd/main.go
View file @
94bfe152
package
main
import
(
"fmt"
"log"
"time"
"git.coco.study/fvitt/good2go/api"
"git.coco.study/fvitt/good2go/database"
"git.coco.study/fvitt/good2go/internal/model"
"git.coco.study/fvitt/good2go/internal/services"
"github.com/getsentry/sentry-go"
)