Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Switch to GitLab Next
Sign in / Register
Toggle navigation
Menu
Open sidebar
Waleed Gadelkareem
Skeleton
Commits
edc8524d
Commit
edc8524d
authored
Mar 24, 2022
by
Waleed Gadelkareem
🐎
Browse files
add checkout and refund actions
parent
bbbfe9c3
Changes
75
Expand all
Hide whitespace changes
Inline
Side-by-side
src/backend/commands/admin.go
View file @
edc8524d
package
commands
import
(
"fmt"
"fmt"
"backend/kernel"
"backend/services"
h
"github.com/gadelkareem/go-helpers"
"backend/kernel"
"backend/models"
"backend/services"
h
"github.com/gadelkareem/go-helpers"
)
type
admin
struct
{
s
*
services
.
UserService
s
*
services
.
UserService
}
func
NewAdmin
(
s
*
services
.
UserService
)
kernel
.
Command
{
return
&
admin
{
s
:
s
}
return
&
admin
{
s
:
s
}
}
func
(
c
*
admin
)
Run
(
args
[]
string
)
{
if
len
(
args
)
>
1
&&
args
[
0
]
==
"make-admin"
{
c
.
makeAdmin
(
args
[
1
])
}
else
{
c
.
Help
()
}
if
len
(
args
)
>
1
{
if
args
[
0
]
==
"make-admin"
{
c
.
makeAdmin
(
args
[
1
])
}
switch
args
[
0
]
{
case
"make-admin"
:
c
.
makeAdmin
(
args
[
1
])
return
case
"activate-user"
:
c
.
activateUser
(
args
[
1
])
return
}
}
else
{
c
.
Help
()
}
}
func
(
c
*
admin
)
makeAdmin
(
username
string
)
{
err
:=
c
.
s
.
MakeAdmin
(
username
)
h
.
PanicOnError
(
err
)
fmt
.
Printf
(
"User %s is now an admin
\n
"
,
username
)
err
:=
c
.
s
.
MakeAdmin
(
username
)
h
.
PanicOnError
(
err
)
fmt
.
Printf
(
"User %s is now an admin
\n
"
,
username
)
}
func
(
c
*
admin
)
activateUser
(
username
string
)
{
u
,
err
:=
c
.
s
.
FindUser
(
&
models
.
User
{
Username
:
username
},
true
)
h
.
PanicOnError
(
err
)
u
.
Activate
()
err
=
c
.
s
.
Save
(
u
)
h
.
PanicOnError
(
err
)
fmt
.
Printf
(
"User %s is now an active
\n
"
,
username
)
}
func
(
c
*
admin
)
Help
()
{
fmt
.
Printf
(
`
fmt
.
Printf
(
`
Usage: skeleton admin [options] ...
Controls users
...
...
src/backend/commands/dev.go
View file @
edc8524d
...
...
@@ -86,7 +86,7 @@ func (c *dev) delUser(username string) {
func
(
c
*
dev
)
Help
()
{
fmt
.
Printf
(
`
Usage:
proxycloud
dev [options] ...
Usage:
skeleton
dev [options] ...
Dev commands
...
...
src/backend/controllers/ApiController.go
View file @
edc8524d
package
controllers
import
(
"bytes"
"encoding/json"
"net/http"
"backend/di"
"backend/internal"
"backend/kernel"
"backend/models"
"backend/utils/paginator"
"github.com/astaxie/beego/logs"
"github.com/google/jsonapi"
"bytes"
"encoding/json"
"net/http"
"backend/di"
"backend/internal"
"backend/kernel"
"backend/models"
"backend/utils/paginator"
"github.com/astaxie/beego/logs"
"github.com/google/jsonapi"
)
type
(
ApiController
struct
{
BaseController
}
ApiController
struct
{
BaseController
}
)
func
NewApiController
(
c
*
di
.
Container
)
ApiController
{
return
ApiController
{
BaseController
:
BaseController
{
C
:
c
}}
return
ApiController
{
BaseController
:
BaseController
{
C
:
c
}}
}
func
(
c
*
ApiController
)
Prepare
()
{
c
.
EnableRender
=
false
c
.
BaseController
.
Prepare
()
kernel
.
SetCORS
(
c
.
Ctx
)
c
.
setUser
()
u
:=
c
.
Ctx
.
Request
.
URL
.
String
()
method
:=
c
.
Ctx
.
Request
.
Method
c
.
rbac
(
u
,
method
)
c
.
rateLimit
(
u
,
method
)
c
.
EnableRender
=
false
c
.
BaseController
.
Prepare
()
kernel
.
SetCORS
(
c
.
Ctx
)
c
.
setUser
()
u
:=
c
.
Ctx
.
Request
.
URL
.
String
()
method
:=
c
.
Ctx
.
Request
.
Method
c
.
rbac
(
u
,
method
)
c
.
rateLimit
(
u
,
method
)
}
func
(
c
*
ApiController
)
rateLimit
(
u
,
method
string
)
{
ip
:=
c
.
requestIP
()
b
,
err
:=
c
.
C
.
RateLimiter
.
IsRateExceeded
(
c
.
user
,
ip
,
u
,
method
)
c
.
handleError
(
err
)
if
b
{
logs
.
Error
(
"rate exceeded for %s %s %s"
,
ip
,
method
,
c
.
Ctx
.
Request
.
URL
)
c
.
handleError
(
internal
.
ErrTooManyRequests
)
}
ip
:=
c
.
requestIP
()
b
,
err
:=
c
.
C
.
RateLimiter
.
IsRateExceeded
(
c
.
user
,
ip
,
u
,
method
)
c
.
handleError
(
err
)
if
b
{
logs
.
Error
(
"rate exceeded for %s %s %s"
,
ip
,
method
,
c
.
Ctx
.
Request
.
URL
)
c
.
handleError
(
internal
.
ErrTooManyRequests
)
}
}
func
(
c
*
ApiController
)
rbac
(
u
,
method
string
)
{
if
!
c
.
C
.
RBAC
.
CanAccessRoute
(
c
.
user
,
u
,
method
)
{
if
c
.
user
==
nil
{
c
.
handleError
(
internal
.
ErrInvalidJWTToken
)
}
c
.
handleError
(
internal
.
ErrForbidden
)
}
if
!
c
.
C
.
RBAC
.
CanAccessRoute
(
c
.
user
,
u
,
method
)
{
if
c
.
user
==
nil
{
c
.
handleError
(
internal
.
ErrInvalidJWTToken
)
}
c
.
handleError
(
internal
.
ErrForbidden
)
}
}
func
(
c
*
ApiController
)
parseRequest
(
m
interface
{})
{
b
:=
bytes
.
NewBuffer
(
c
.
Ctx
.
Input
.
RequestBody
)
if
err
:=
jsonapi
.
UnmarshalPayload
(
b
,
m
);
err
!=
nil
{
logs
.
Error
(
"Error parsing request %s err: %s"
,
c
.
Ctx
.
Request
.
URL
,
err
)
c
.
handleError
(
internal
.
ErrInvalidRequest
)
}
b
:=
bytes
.
NewBuffer
(
c
.
Ctx
.
Input
.
RequestBody
)
if
err
:=
jsonapi
.
UnmarshalPayload
(
b
,
m
);
err
!=
nil
{
logs
.
Error
(
"Error parsing request %s err: %s"
,
c
.
Ctx
.
Request
.
URL
,
err
)
c
.
handleError
(
internal
.
ErrInvalidRequest
)
}
}
func
(
c
*
ApiController
)
validate
(
m
interface
{})
{
v
:=
kernel
.
Validation
()
b
,
err
:=
v
.
Valid
(
m
)
if
err
!=
nil
{
c
.
handleError
(
err
)
}
if
!
b
{
vErrs
:=
make
(
map
[
string
]
interface
{})
for
_
,
e
:=
range
v
.
Errors
{
vErrs
[
e
.
Key
]
=
e
.
Error
()
}
c
.
handleError
(
internal
.
ValidationErrors
(
vErrs
))
}
return
v
:=
kernel
.
Validation
()
b
,
err
:=
v
.
Valid
(
m
)
if
err
!=
nil
{
c
.
handleError
(
err
)
}
if
!
b
{
vErrs
:=
make
(
map
[
string
]
interface
{})
for
_
,
e
:=
range
v
.
Errors
{
vErrs
[
e
.
Key
]
=
e
.
Error
()
}
c
.
handleError
(
internal
.
ValidationErrors
(
vErrs
))
}
return
}
func
(
c
*
ApiController
)
parseJSONRequest
(
m
interface
{})
{
if
err
:=
json
.
Unmarshal
(
c
.
Ctx
.
Input
.
RequestBody
,
m
);
err
!=
nil
{
logs
.
Error
(
"Error parsing request %s err: %s"
,
c
.
Ctx
.
Request
.
URL
,
err
)
c
.
handleError
(
internal
.
ErrInvalidRequest
)
}
if
err
:=
json
.
Unmarshal
(
c
.
Ctx
.
Input
.
RequestBody
,
m
);
err
!=
nil
{
logs
.
Error
(
"Error parsing request %s err: %s"
,
c
.
Ctx
.
Request
.
URL
,
err
)
c
.
handleError
(
internal
.
ErrInvalidRequest
)
}
}
func
(
c
*
ApiController
)
jsonMany
(
p
*
paginator
.
Paginator
)
{
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
http
.
StatusOK
)
for
_
,
m
:=
range
p
.
Models
{
if
ml
,
k
:=
m
.
(
models
.
BaseInterface
);
k
{
ml
.
Sanitize
()
}
}
pl
,
err
:=
jsonapi
.
Marshal
(
p
.
Models
)
c
.
handleError
(
err
)
py
:=
pl
.
(
*
jsonapi
.
ManyPayload
)
py
.
Links
=
p
.
Links
()
py
.
Meta
=
p
.
Meta
()
b
:=
bytes
.
NewBuffer
(
nil
)
err
=
json
.
NewEncoder
(
b
)
.
Encode
(
py
)
c
.
handleError
(
err
)
err
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
c
.
handleError
(
err
)
c
.
StopRun
()
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
http
.
StatusOK
)
for
_
,
m
:=
range
p
.
Models
{
if
ml
,
k
:=
m
.
(
models
.
BaseInterface
);
k
{
ml
.
Sanitize
()
}
}
pl
,
err
:=
jsonapi
.
Marshal
(
p
.
Models
)
c
.
handleError
(
err
)
py
:=
pl
.
(
*
jsonapi
.
ManyPayload
)
py
.
Links
=
p
.
Links
()
py
.
Meta
=
p
.
Meta
()
b
:=
bytes
.
NewBuffer
(
nil
)
err
=
json
.
NewEncoder
(
b
)
.
Encode
(
py
)
c
.
handleError
(
err
)
err
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
c
.
handleError
(
err
)
c
.
StopRun
()
}
func
(
c
*
ApiController
)
json
(
m
interface
{})
{
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
http
.
StatusOK
)
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
http
.
StatusOK
)
if
ml
,
k
:=
m
.
(
models
.
BaseInterface
);
k
{
ml
.
Sanitize
()
}
if
ml
,
k
:=
m
.
(
models
.
BaseInterface
);
k
{
ml
.
Sanitize
()
}
b
:=
bytes
.
NewBuffer
(
nil
)
err
:=
jsonapi
.
MarshalPayload
(
b
,
m
)
c
.
handleError
(
err
)
b
:=
bytes
.
NewBuffer
(
nil
)
err
:=
jsonapi
.
MarshalPayload
(
b
,
m
)
c
.
handleError
(
err
)
err
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
c
.
handleError
(
err
)
err
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
c
.
handleError
(
err
)
c
.
StopRun
()
c
.
StopRun
()
}
func
(
c
*
ApiController
)
handleError
(
err
error
)
{
if
err
==
nil
{
return
}
internalErr
,
k
:=
err
.
(
internal
.
Error
)
if
!
k
||
internalErr
==
nil
{
logs
.
Error
(
"Error: %s"
,
err
)
internalErr
=
internal
.
ErrInternalError
}
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
internalErr
.
Status
())
b
:=
bytes
.
NewBuffer
(
nil
)
e
:=
jsonapi
.
MarshalErrors
(
b
,
[]
*
jsonapi
.
ErrorObject
{
internalErr
.
Object
()})
if
e
!=
nil
{
logs
.
Error
(
"Error unmarshal errors: %s"
,
e
)
}
e
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
if
e
!=
nil
{
logs
.
Error
(
"Error writing body: %s"
,
e
)
}
go
c
.
log
(
internalErr
.
Status
())
c
.
StopRun
()
if
err
==
nil
{
return
}
internalErr
,
k
:=
err
.
(
internal
.
Error
)
if
!
k
||
internalErr
==
nil
{
logs
.
Error
(
"Error: %s"
,
err
)
internalErr
=
internal
.
ErrInternalError
}
c
.
Ctx
.
Output
.
Header
(
"Content-Type"
,
jsonapi
.
MediaType
)
c
.
Ctx
.
Output
.
SetStatus
(
internalErr
.
Status
())
b
:=
bytes
.
NewBuffer
(
nil
)
e
:=
jsonapi
.
MarshalErrors
(
b
,
[]
*
jsonapi
.
ErrorObject
{
internalErr
.
Object
()})
if
e
!=
nil
{
logs
.
Error
(
"Error unmarshal errors: %s"
,
e
)
}
e
=
c
.
Ctx
.
Output
.
Body
(
b
.
Bytes
())
if
e
!=
nil
{
logs
.
Error
(
"Error writing body: %s"
,
e
)
}
go
c
.
log
(
internalErr
.
Status
())
c
.
StopRun
()
}
func
(
c
*
ApiController
)
SendStatus
(
s
int
)
{
c
.
Ctx
.
ResponseWriter
.
WriteHeader
(
s
)
go
c
.
log
(
s
)
c
.
StopRun
()
c
.
Ctx
.
ResponseWriter
.
WriteHeader
(
s
)
go
c
.
log
(
s
)
c
.
StopRun
()
}
func
(
c
*
ApiController
)
setUser
()
{
tk
:=
c
.
Ctx
.
Input
.
Header
(
"Authorization"
)
if
tk
==
""
{
return
}
p
:=
c
.
C
.
JWTService
.
ParseHeader
(
tk
)
if
p
==
nil
{
return
}
var
err
error
c
.
user
,
err
=
c
.
C
.
UserService
.
UserById
(
p
.
UserId
)
if
err
!=
nil
{
logs
.
Error
(
"Could not find user: %s"
,
err
)
}
tk
:=
c
.
Ctx
.
Input
.
Header
(
"Authorization"
)
if
tk
==
""
{
return
}
p
:=
c
.
C
.
JWTService
.
ParseHeader
(
tk
)
if
p
==
nil
{
return
}
var
err
error
c
.
user
,
err
=
c
.
C
.
UserService
.
UserById
(
p
.
UserId
)
if
err
!=
nil
{
logs
.
Error
(
"Could not find user: %s"
,
err
)
}
}
func
(
c
*
ApiController
)
auditLog
(
l
models
.
Log
)
{
l
.
IP
=
c
.
requestIP
()
l
.
UserAgent
=
c
.
requestUserAgent
()
if
l
.
Request
==
""
{
l
.
Request
=
string
(
c
.
Ctx
.
Input
.
RequestBody
)
}
if
l
.
UserID
!=
0
&&
c
.
user
!=
nil
&&
l
.
UserID
!=
c
.
user
.
ID
{
l
.
AdminID
=
c
.
user
.
ID
}
if
l
.
UserID
==
0
&&
c
.
user
!=
nil
{
l
.
UserID
=
c
.
user
.
ID
}
c
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
l
.
IP
=
c
.
requestIP
()
l
.
UserAgent
=
c
.
requestUserAgent
()
if
l
.
Request
==
""
{
l
.
Request
=
string
(
c
.
Ctx
.
Input
.
RequestBody
)
}
if
l
.
UserID
!=
0
&&
c
.
user
!=
nil
&&
l
.
UserID
!=
c
.
user
.
ID
{
l
.
AdminID
=
c
.
user
.
ID
}
if
l
.
UserID
==
0
&&
c
.
user
!=
nil
{
l
.
UserID
=
c
.
user
.
ID
}
c
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
}
func
(
c
*
ApiController
)
paginator
(
size
int
)
*
paginator
.
Paginator
{
page
:=
map
[
string
]
int
{
"size"
:
size
,
"after"
:
1
}
err
:=
c
.
Ctx
.
Input
.
Bind
(
&
page
,
"page"
)
c
.
logOnError
(
err
)
return
paginator
.
NewPaginator
(
page
,
c
.
readString
(
"sort"
),
c
.
readString
(
"filter"
),
c
.
Ctx
.
Input
.
URI
())
page
:=
map
[
string
]
int
{
"size"
:
size
,
"after"
:
1
}
err
:=
c
.
Ctx
.
Input
.
Bind
(
&
page
,
"page"
)
c
.
logOnError
(
err
)
return
paginator
.
NewPaginator
(
page
,
c
.
readString
(
"sort"
),
c
.
readString
(
"filter"
),
c
.
Ctx
.
Input
.
URI
())
}
func
(
c
*
ApiController
)
AssertCustomer
(
id
string
)
{
if
id
!=
c
.
user
.
CustomerID
{
c
.
handleError
(
internal
.
ErrForbidden
)
}
if
id
!=
c
.
user
.
CustomerID
{
c
.
handleError
(
internal
.
ErrForbidden
)
}
}
src/backend/controllers/AuditLogController.go
View file @
edc8524d
package
controllers
import
(
"backend/kernel"
"backend/kernel"
)
type
AuditLogController
struct
{
ApiController
ApiController
}
// @router / [get]
func
(
c
*
AuditLogController
)
GetAuditLogs
()
{
p
,
err
:=
c
.
C
.
AuditLogService
.
PaginateAuditLogs
(
c
.
paginator
(
kernel
.
ListLimit
))
c
.
handleError
(
err
)
p
,
err
:=
c
.
C
.
AuditLogService
.
PaginateAuditLogs
(
c
.
paginator
(
kernel
.
ListLimit
))
c
.
handleError
(
err
)
c
.
jsonMany
(
p
)
c
.
jsonMany
(
p
)
}
src/backend/controllers/AuditLogController_test.go
View file @
edc8524d
package
controllers_test
import
(
"net/http"
"reflect"
"testing"
"backend/kernel"
"backend/models"
"backend/tests"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
"net/http"
"reflect"
"testing"
"backend/kernel"
"backend/models"
"backend/tests"
"github.com/brianvoe/gofakeit/v6"
"github.com/stretchr/testify/assert"
)
func
TestAuditLogController_GetAuditLogs
(
t
*
testing
.
T
)
{
l
:=
models
.
Log
{}
gofakeit
.
Struct
(
&
l
)
tests
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
gofakeit
.
Struct
(
&
l
)
tests
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
_
,
tk
:=
tests
.
AdminWithToken
(
t
)
w
,
_
:=
tests
.
ApiRequest
(
&
tests
.
Request
{
T
:
t
,
Method
:
http
.
MethodGet
,
URI
:
"/audit-logs"
,
AuthToken
:
tk
,
Status
:
http
.
StatusOK
})
auditLogs
,
payload
:=
tests
.
ParseModels
(
t
,
reflect
.
TypeOf
(
new
(
models
.
AuditLog
)),
w
.
Body
)
assert
.
NotEmpty
(
t
,
auditLogs
)
totalAuditLogs
,
err
:=
tests
.
C
.
AuditLogRepository
.
Count
()
tests
.
FailOnErr
(
t
,
err
)
count
:=
totalAuditLogs
if
totalAuditLogs
>
kernel
.
ListLimit
{
count
=
kernel
.
ListLimit
}
assert
.
Len
(
t
,
auditLogs
,
count
)
assert
.
NotEmpty
(
t
,
auditLogs
[
0
]
.
(
*
models
.
AuditLog
)
.
ID
)
assert
.
NotEmpty
(
t
,
auditLogs
[
1
]
.
(
*
models
.
AuditLog
)
.
Log
.
Action
)
m
:=
*
payload
.
Meta
assert
.
Equal
(
t
,
totalAuditLogs
,
int
(
m
[
"page"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
float64
)))
assert
.
Equal
(
t
,
kernel
.
ListLimit
,
int
(
m
[
"page"
]
.
(
map
[
string
]
interface
{})[
"size"
]
.
(
float64
)))
// test admin access only
_
,
tk
=
tests
.
UserWithToken
(
true
)
w
,
_
=
tests
.
ApiRequest
(
&
tests
.
Request
{
T
:
t
,
Method
:
http
.
MethodGet
,
URI
:
"/audit-logs"
,
AuthToken
:
tk
,
Status
:
http
.
StatusForbidden
})
l
:=
models
.
Log
{}
gofakeit
.
Struct
(
&
l
)
tests
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
gofakeit
.
Struct
(
&
l
)
tests
.
C
.
AuditLogService
.
AddAuditLog
(
l
)
_
,
tk
:=
tests
.
AdminWithToken
(
t
)
w
,
_
:=
tests
.
ApiRequest
(
&
tests
.
Request
{
T
:
t
,
Method
:
http
.
MethodGet
,
URI
:
"/audit-logs"
,
AuthToken
:
tk
,
Status
:
http
.
StatusOK
})
auditLogs
,
payload
:=
tests
.
ParseModels
(
t
,
reflect
.
TypeOf
(
new
(
models
.
AuditLog
)),
w
.
Body
)
assert
.
NotEmpty
(
t
,
auditLogs
)
totalAuditLogs
,
err
:=
tests
.
C
.
AuditLogRepository
.
Count
()
tests
.
FailOnErr
(
t
,
err
)
count
:=
totalAuditLogs
if
totalAuditLogs
>
kernel
.
ListLimit
{
count
=
kernel
.
ListLimit
}
assert
.
Len
(
t
,
auditLogs
,
count
)
assert
.
NotEmpty
(
t
,
auditLogs
[
0
]
.
(
*
models
.
AuditLog
)
.
ID
)
assert
.
NotEmpty
(
t
,
auditLogs
[
1
]
.
(
*
models
.
AuditLog
)
.
Log
.
Action
)
m
:=
*
payload
.
Meta
assert
.
Equal
(
t
,
totalAuditLogs
,
int
(
m
[
"page"
]
.
(
map
[
string
]
interface
{})[
"total"
]
.
(
float64
)))
assert
.
Equal
(
t
,
kernel
.
ListLimit
,
int
(
m
[
"page"
]
.
(
map
[
string
]
interface
{})[
"size"
]
.
(
float64
)))
// test admin access only
_
,
tk
=
tests
.
UserWithToken
(
true
)
w
,
_
=
tests
.
ApiRequest
(
&
tests
.
Request
{
T
:
t
,
Method
:
http
.
MethodGet
,
URI
:
"/audit-logs"
,
AuthToken
:
tk
,
Status
:
http
.
StatusForbidden
})
}
src/backend/controllers/AuthController.go
View file @
edc8524d
package
controllers
import
(
"fmt"
"net/http"
"fmt"
"net/http"
"backend/internal"
"backend/kernel"