mirror of
https://github.com/h44z/wg-portal.git
synced 2025-08-25 06:22:23 +00:00
fix REST API permission checks (#209)
This commit is contained in:
@@ -44,7 +44,8 @@ func (e authEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *authenti
|
||||
// @Router /auth/providers [get]
|
||||
func (e authEndpoint) handleExternalLoginProvidersGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
providers := e.app.Authenticator.GetExternalLoginProviders(c.Request.Context())
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
providers := e.app.Authenticator.GetExternalLoginProviders(ctx)
|
||||
|
||||
c.JSON(http.StatusOK, model.NewLoginProviderInfos(providers))
|
||||
}
|
||||
@@ -69,7 +70,7 @@ func (e authEndpoint) handleSessionInfoGet() gin.HandlerFunc {
|
||||
var email *string
|
||||
|
||||
if currentSession.LoggedIn {
|
||||
uid := string(currentSession.UserIdentifier)
|
||||
uid := currentSession.UserIdentifier
|
||||
f := currentSession.Firstname
|
||||
l := currentSession.Lastname
|
||||
e := currentSession.Email
|
||||
@@ -134,7 +135,8 @@ func (e authEndpoint) handleOauthInitiateGet() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
authCodeUrl, state, nonce, err := e.app.Authenticator.OauthLoginStep1(c.Request.Context(), provider)
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
authCodeUrl, state, nonce, err := e.app.Authenticator.OauthLoginStep1(ctx, provider)
|
||||
if err != nil {
|
||||
if autoRedirect {
|
||||
redirectToReturn()
|
||||
@@ -292,7 +294,8 @@ func (e authEndpoint) handleLoginPost() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
user, err := e.app.Authenticator.PlainLogin(c.Request.Context(), loginData.Username, loginData.Password)
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
user, err := e.app.Authenticator.PlainLogin(ctx, loginData.Username, loginData.Password)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusUnauthorized, model.Error{Code: http.StatusUnauthorized, Message: "login failed"})
|
||||
return
|
||||
|
@@ -19,7 +19,7 @@ func (e interfaceEndpoint) GetName() string {
|
||||
}
|
||||
|
||||
func (e interfaceEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *authenticationHandler) {
|
||||
apiGroup := g.Group("/interface", e.authenticator.LoggedIn())
|
||||
apiGroup := g.Group("/interface", e.authenticator.LoggedIn(ScopeAdmin))
|
||||
|
||||
apiGroup.GET("/prepare", e.handlePrepareGet())
|
||||
apiGroup.GET("/all", e.handleAllGet())
|
||||
@@ -45,7 +45,8 @@ func (e interfaceEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *aut
|
||||
// @Router /interface/prepare [get]
|
||||
func (e interfaceEndpoint) handlePrepareGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
in, err := e.app.PrepareInterface(c.Request.Context())
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
in, err := e.app.PrepareInterface(ctx)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
@@ -68,7 +69,8 @@ func (e interfaceEndpoint) handlePrepareGet() gin.HandlerFunc {
|
||||
// @Router /interface/all [get]
|
||||
func (e interfaceEndpoint) handleAllGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
interfaces, peers, err := e.app.GetAllInterfacesAndPeers(c.Request.Context())
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
interfaces, peers, err := e.app.GetAllInterfacesAndPeers(ctx)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
@@ -92,6 +94,7 @@ func (e interfaceEndpoint) handleAllGet() gin.HandlerFunc {
|
||||
// @Router /interface/get/{id} [get]
|
||||
func (e interfaceEndpoint) handleSingleGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
id := Base64UrlDecode(c.Param("id"))
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, model.Error{
|
||||
@@ -100,7 +103,7 @@ func (e interfaceEndpoint) handleSingleGet() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
iface, peers, err := e.app.GetInterfaceAndPeers(c.Request.Context(), domain.InterfaceIdentifier(id))
|
||||
iface, peers, err := e.app.GetInterfaceAndPeers(ctx, domain.InterfaceIdentifier(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
@@ -124,6 +127,7 @@ func (e interfaceEndpoint) handleSingleGet() gin.HandlerFunc {
|
||||
// @Router /interface/config/{id} [get]
|
||||
func (e interfaceEndpoint) handleConfigGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
id := Base64UrlDecode(c.Param("id"))
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, model.Error{
|
||||
@@ -132,7 +136,7 @@ func (e interfaceEndpoint) handleConfigGet() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
config, err := e.app.GetInterfaceConfig(c.Request.Context(), domain.InterfaceIdentifier(id))
|
||||
config, err := e.app.GetInterfaceConfig(ctx, domain.InterfaceIdentifier(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
|
@@ -21,11 +21,11 @@ func (e peerEndpoint) GetName() string {
|
||||
func (e peerEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *authenticationHandler) {
|
||||
apiGroup := g.Group("/peer", e.authenticator.LoggedIn())
|
||||
|
||||
apiGroup.GET("/iface/:iface/all", e.handleAllGet())
|
||||
apiGroup.GET("/iface/:iface/stats", e.handleStatsGet())
|
||||
apiGroup.GET("/iface/:iface/prepare", e.handlePrepareGet())
|
||||
apiGroup.POST("/iface/:iface/new", e.handleCreatePost())
|
||||
apiGroup.POST("/iface/:iface/multiplenew", e.handleCreateMultiplePost())
|
||||
apiGroup.GET("/iface/:iface/all", e.authenticator.LoggedIn(ScopeAdmin), e.handleAllGet())
|
||||
apiGroup.GET("/iface/:iface/stats", e.authenticator.LoggedIn(ScopeAdmin), e.handleStatsGet())
|
||||
apiGroup.GET("/iface/:iface/prepare", e.authenticator.LoggedIn(ScopeAdmin), e.handlePrepareGet())
|
||||
apiGroup.POST("/iface/:iface/new", e.authenticator.LoggedIn(ScopeAdmin), e.handleCreatePost())
|
||||
apiGroup.POST("/iface/:iface/multiplenew", e.authenticator.LoggedIn(ScopeAdmin), e.handleCreateMultiplePost())
|
||||
apiGroup.GET("/config-qr/:id", e.handleQrCodeGet())
|
||||
apiGroup.POST("/config-mail", e.handleEmailPost())
|
||||
apiGroup.GET("/config/:id", e.handleConfigGet())
|
||||
@@ -298,6 +298,8 @@ func (e peerEndpoint) handleDelete() gin.HandlerFunc {
|
||||
// @Router /peer/config/{id} [get]
|
||||
func (e peerEndpoint) handleConfigGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
|
||||
id := Base64UrlDecode(c.Param("id"))
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, model.Error{
|
||||
@@ -306,7 +308,7 @@ func (e peerEndpoint) handleConfigGet() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
config, err := e.app.GetPeerConfig(c.Request.Context(), domain.PeerIdentifier(id))
|
||||
config, err := e.app.GetPeerConfig(ctx, domain.PeerIdentifier(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
@@ -339,6 +341,7 @@ func (e peerEndpoint) handleConfigGet() gin.HandlerFunc {
|
||||
// @Router /peer/config-qr/{id} [get]
|
||||
func (e peerEndpoint) handleQrCodeGet() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
id := Base64UrlDecode(c.Param("id"))
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, model.Error{
|
||||
@@ -347,7 +350,7 @@ func (e peerEndpoint) handleQrCodeGet() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
config, err := e.app.GetPeerConfigQrCode(c.Request.Context(), domain.PeerIdentifier(id))
|
||||
config, err := e.app.GetPeerConfigQrCode(ctx, domain.PeerIdentifier(id))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{
|
||||
Code: http.StatusInternalServerError, Message: err.Error(),
|
||||
@@ -392,11 +395,13 @@ func (e peerEndpoint) handleEmailPost() gin.HandlerFunc {
|
||||
return
|
||||
}
|
||||
|
||||
ctx := domain.SetUserInfoFromGin(c)
|
||||
|
||||
peerIds := make([]domain.PeerIdentifier, len(req.Identifiers))
|
||||
for i := range req.Identifiers {
|
||||
peerIds[i] = domain.PeerIdentifier(req.Identifiers[i])
|
||||
}
|
||||
err = e.app.SendPeerEmail(c.Request.Context(), req.LinkOnly, peerIds...)
|
||||
err = e.app.SendPeerEmail(ctx, req.LinkOnly, peerIds...)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error{Code: http.StatusInternalServerError, Message: err.Error()})
|
||||
return
|
||||
|
@@ -20,13 +20,13 @@ func (e userEndpoint) GetName() string {
|
||||
func (e userEndpoint) RegisterRoutes(g *gin.RouterGroup, authenticator *authenticationHandler) {
|
||||
apiGroup := g.Group("/user", e.authenticator.LoggedIn())
|
||||
|
||||
apiGroup.GET("/all", e.handleAllGet())
|
||||
apiGroup.GET("/:id", e.handleSingleGet())
|
||||
apiGroup.PUT("/:id", e.handleUpdatePut())
|
||||
apiGroup.DELETE("/:id", e.handleDelete())
|
||||
apiGroup.POST("/new", e.handleCreatePost())
|
||||
apiGroup.GET("/:id/peers", e.handlePeersGet())
|
||||
apiGroup.GET("/:id/stats", e.handleStatsGet())
|
||||
apiGroup.GET("/all", e.authenticator.LoggedIn(ScopeAdmin), e.handleAllGet())
|
||||
apiGroup.GET("/:id", e.authenticator.UserIdMatch("id"), e.handleSingleGet())
|
||||
apiGroup.PUT("/:id", e.authenticator.UserIdMatch("id"), e.handleUpdatePut())
|
||||
apiGroup.DELETE("/:id", e.authenticator.UserIdMatch("id"), e.handleDelete())
|
||||
apiGroup.POST("/new", e.authenticator.LoggedIn(ScopeAdmin), e.handleCreatePost())
|
||||
apiGroup.GET("/:id/peers", e.authenticator.UserIdMatch("id"), e.handlePeersGet())
|
||||
apiGroup.GET("/:id/stats", e.authenticator.UserIdMatch("id"), e.handleStatsGet())
|
||||
}
|
||||
|
||||
// handleAllGet returns a gorm handler function.
|
||||
|
@@ -58,6 +58,31 @@ func (h authenticationHandler) LoggedIn(scopes ...Scope) gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// UserIdMatch checks if the user id in the session matches the user id in the request. If not, the request is aborted.
|
||||
func (h authenticationHandler) UserIdMatch(idParameter string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
session := h.Session.GetData(c)
|
||||
|
||||
if session.IsAdmin {
|
||||
c.Next() // Admins can do everything
|
||||
return
|
||||
}
|
||||
|
||||
sessionUserId := domain.UserIdentifier(session.UserIdentifier)
|
||||
requestUserId := domain.UserIdentifier(Base64UrlDecode(c.Param(idParameter)))
|
||||
|
||||
if sessionUserId != requestUserId {
|
||||
// Abort the request with the appropriate error code
|
||||
c.Abort()
|
||||
c.JSON(http.StatusForbidden, model.Error{Code: http.StatusForbidden, Message: "not enough permissions"})
|
||||
return
|
||||
}
|
||||
|
||||
// Continue down the chain to handler etc
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func UserHasScopes(session SessionData, scopes ...Scope) bool {
|
||||
// No scopes give, so the check should succeed
|
||||
if len(scopes) == 0 {
|
||||
|
Reference in New Issue
Block a user