Skip to content

Commit e39a8d5

Browse files
authored
Merge pull request #69 from mutablelogic/v4
Scope updates
2 parents b365d21 + f013315 commit e39a8d5

File tree

9 files changed

+168
-25
lines changed

9 files changed

+168
-25
lines changed

pkg/handler/auth/endpoints.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,30 @@ var (
4141
func (service *auth) AddEndpoints(ctx context.Context, r server.Router) {
4242
// Path: /
4343
// Methods: GET
44-
// Scopes: read // TODO: Add scopes
44+
// Scopes: read
4545
// Description: Get current set of tokens and groups
4646
r.AddHandlerFuncRe(ctx, reRoot, service.ListTokens, http.MethodGet).(router.Route).
4747
SetScope(service.ScopeRead()...)
4848

4949
// Path: /
5050
// Methods: POST
51-
// Scopes: write // TODO: Add scopes
51+
// Scopes: write
5252
// Description: Create a new token
5353
r.AddHandlerFuncRe(ctx, reRoot, service.CreateToken, http.MethodPost).(router.Route).
54-
SetScope(service.ScopeRead()...).
5554
SetScope(service.ScopeWrite()...)
5655

5756
// Path: /<token-name>
5857
// Methods: GET
59-
// Scopes: read // TODO: Add scopes
58+
// Scopes: read
6059
// Description: Get a token
6160
r.AddHandlerFuncRe(ctx, reToken, service.GetToken, http.MethodGet).(router.Route).
6261
SetScope(service.ScopeRead()...)
6362

6463
// Path: /<token-name>
6564
// Methods: DELETE, PATCH
66-
// Scopes: write // TODO: Add scopes
65+
// Scopes: write
6766
// Description: Delete or update a token
6867
r.AddHandlerFuncRe(ctx, reToken, service.UpdateToken, http.MethodDelete, http.MethodPatch).(router.Route).
69-
SetScope(service.ScopeRead()...).
7068
SetScope(service.ScopeWrite()...)
7169

7270
}

pkg/handler/auth/middleware.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -50,20 +50,22 @@ func (middleware *auth) Wrap(ctx context.Context, next http.HandlerFunc) http.Ha
5050
authorized := true
5151
if token.IsZero() {
5252
authorized = false
53+
httpresponse.Error(w, http.StatusUnauthorized, "invalid or missing token")
5354
} else if !token.IsValid() {
5455
authorized = false
56+
httpresponse.Error(w, http.StatusUnauthorized, "invalid or missing token")
5557
} else if token.IsScope(ScopeRoot) {
5658
// Allow - token is a super-user token
5759
} else if allowedScopes := router.Scope(r.Context()); len(allowedScopes) == 0 {
5860
// Allow - no scopes have been defined on this endpoint
5961
} else if !token.IsScope(allowedScopes...) {
6062
// Deny - token does not have the required scopes
6163
authorized = false
64+
httpresponse.Error(w, http.StatusUnauthorized, "required scope: ", strings.Join(allowedScopes, ","))
6265
}
6366

6467
// Return unauthorized if token is not found or not valid
6568
if !authorized {
66-
httpresponse.Error(w, http.StatusUnauthorized)
6769
return
6870
}
6971

pkg/handler/auth/token.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ import (
1515
// TYPES
1616

1717
type Token struct {
18-
Name string `json:"name,omitempty"` // Name of the token
19-
Value string `json:"token,omitempty"` // Token value
20-
Expire time.Time `json:"expire_time,omitempty"` // Time of expiration for the token
21-
Time time.Time `json:"access_time"` // Time of last access
22-
Scope []string `json:"scopes,omitempty"` // Authentication scopes
18+
Name string `json:"name,omitempty"` // Name of the token
19+
Value string `json:"token,omitempty"` // Token value
20+
Expire time.Time `json:"expire_time,omitempty" writer:",width:29"` // Time of expiration for the token
21+
Time time.Time `json:"access_time,omitempty" writer:",width:29"` // Time of last access
22+
Scope []string `json:"scopes,omitempty" writer:",wrap"` // Authentication scopes
2323
}
2424

2525
type TokenCreate struct {

pkg/handler/nginx/endpoints.go

+19-13
Original file line numberDiff line numberDiff line change
@@ -50,42 +50,48 @@ var (
5050
// PUBLIC METHODS - ENDPOINTS
5151

5252
// Add endpoints to the router
53-
func (service *nginx) AddEndpoints(ctx context.Context, router server.Router) {
53+
func (service *nginx) AddEndpoints(ctx context.Context, r server.Router) {
5454
// Path: /
5555
// Methods: GET
56-
// Scopes: read // TODO: Add scopes
56+
// Scopes: read
5757
// Description: Get nginx status (version, uptime, available and enabled configurations)
58-
router.AddHandlerFuncRe(ctx, reRoot, service.GetHealth, http.MethodGet)
58+
r.AddHandlerFuncRe(ctx, reRoot, service.GetHealth, http.MethodGet).(router.Route).
59+
SetScope(service.ScopeRead()...)
5960

6061
// Path: /(test|reload|reopen)
6162
// Methods: PUT
62-
// Scopes: write // TODO: Add scopes
63+
// Scopes: write
6364
// Description: Test, reload and reopen nginx configuration
64-
router.AddHandlerFuncRe(ctx, reAction, service.PutAction, http.MethodPut)
65+
r.AddHandlerFuncRe(ctx, reAction, service.PutAction, http.MethodPut).(router.Route).
66+
SetScope(service.ScopeWrite()...)
6567

6668
// Path: /config
6769
// Methods: GET
68-
// Scopes: read // TODO: Add scopes
70+
// Scopes: read
6971
// Description: Read the current set of configurations
70-
router.AddHandlerFuncRe(ctx, reListConfig, service.ListConfig, http.MethodGet)
72+
r.AddHandlerFuncRe(ctx, reListConfig, service.ListConfig, http.MethodGet).(router.Route).
73+
SetScope(service.ScopeRead()...)
7174

7275
// Path: /config
7376
// Methods: POST
74-
// Scopes: read // TODO: Add scopes
77+
// Scopes: write
7578
// Description: Create a new configuration
76-
router.AddHandlerFuncRe(ctx, reListConfig, service.CreateConfig, http.MethodPost)
79+
r.AddHandlerFuncRe(ctx, reListConfig, service.CreateConfig, http.MethodPost).(router.Route).
80+
SetScope(service.ScopeWrite()...)
7781

7882
// Path: /config/{id}
7983
// Methods: GET
80-
// Scopes: read // TODO: Add scopes
84+
// Scopes: read
8185
// Description: Read a configuration
82-
router.AddHandlerFuncRe(ctx, reConfig, service.ReadConfig, http.MethodGet)
86+
r.AddHandlerFuncRe(ctx, reConfig, service.ReadConfig, http.MethodGet).(router.Route).
87+
SetScope(service.ScopeRead()...)
8388

8489
// Path: /config/{id}
8590
// Methods: DELETE, POST, PATCH
86-
// Scopes: write // TODO: Add scopes
91+
// Scopes: write
8792
// Description: Modify a configuration
88-
router.AddHandlerFuncRe(ctx, reConfig, service.WriteConfig, http.MethodDelete, http.MethodPatch)
93+
r.AddHandlerFuncRe(ctx, reConfig, service.WriteConfig, http.MethodDelete, http.MethodPatch).(router.Route).
94+
SetScope(service.ScopeWrite()...)
8995
}
9096

9197
///////////////////////////////////////////////////////////////////////////////

pkg/handler/nginx/scope.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package nginx
2+
3+
import (
4+
// Packages
5+
"github.com/mutablelogic/go-server/pkg/version"
6+
)
7+
8+
////////////////////////////////////////////////////////////////////////////////
9+
// GLOBALS
10+
11+
var (
12+
// Prefix
13+
scopePrefix = version.GitSource + "/scope/"
14+
)
15+
16+
////////////////////////////////////////////////////////////////////////////////
17+
// PUBLIC METHODS
18+
19+
func (nginx *nginx) ScopeRead() []string {
20+
// Return read (list, get) scopes
21+
return []string{
22+
scopePrefix + nginx.Label() + "/read",
23+
scopePrefix + defaultName + "/read",
24+
}
25+
}
26+
27+
func (nginx *nginx) ScopeWrite() []string {
28+
// Return write (create, delete, update) scopes
29+
return []string{
30+
scopePrefix + nginx.Label() + "/write",
31+
scopePrefix + defaultName + "/write",
32+
}
33+
}

pkg/handler/router/endpoints.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package router
2+
3+
import (
4+
"context"
5+
"net/http"
6+
"regexp"
7+
8+
// Packages
9+
server "github.com/mutablelogic/go-server"
10+
httpresponse "github.com/mutablelogic/go-server/pkg/httpresponse"
11+
)
12+
13+
///////////////////////////////////////////////////////////////////////////////
14+
// GLOBALS
15+
16+
const (
17+
jsonIndent = 2
18+
)
19+
20+
var (
21+
reRoot = regexp.MustCompile(`^/?$`)
22+
)
23+
24+
///////////////////////////////////////////////////////////////////////////////
25+
// PUBLIC METHODS - ENDPOINTS
26+
27+
// Add endpoints to the router
28+
func (service *router) AddEndpoints(ctx context.Context, r server.Router) {
29+
// Path: /
30+
// Methods: GET
31+
// Scopes: read
32+
// Description: Get router services
33+
r.AddHandlerFuncRe(ctx, reRoot, service.GetScopes, http.MethodGet).(Route).
34+
SetScope(service.ScopeRead()...)
35+
}
36+
37+
///////////////////////////////////////////////////////////////////////////////
38+
// PUBLIC METHODS
39+
40+
// Get registered scopes
41+
func (service *router) GetScopes(w http.ResponseWriter, r *http.Request) {
42+
httpresponse.JSON(w, service.Scopes(), http.StatusOK, jsonIndent)
43+
}

pkg/handler/router/interface.go

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ type Router interface {
1515
// http status code, which will be 200 on success, 404 or 405 and
1616
// path parameters extracted from the path.
1717
Match(host, method, path string) (*matchedRoute, int)
18+
19+
// Return all known scopes
20+
Scopes() []string
1821
}
1922

2023
type Route interface {

pkg/handler/router/router.go

+25
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,31 @@ func (router *router) Match(host, method, path string) (*matchedRoute, int) {
184184
return nil, http.StatusMethodNotAllowed
185185
}
186186

187+
func (router *router) Scopes() []string {
188+
scopes := make(map[string]bool)
189+
for _, r := range router.host {
190+
for _, h := range r.prefix {
191+
for _, r := range h.handlers {
192+
for _, s := range r.scopes {
193+
scopes[s] = true
194+
}
195+
}
196+
}
197+
}
198+
199+
// Gather all scopes
200+
result := make([]string, 0, len(scopes))
201+
for scope := range scopes {
202+
result = append(result, scope)
203+
}
204+
205+
// Sort alphabetically
206+
sort.Strings(result)
207+
208+
// Return the result
209+
return result
210+
}
211+
187212
///////////////////////////////////////////////////////////////////////////////
188213
// PRIVATE METHODS
189214

pkg/handler/router/scope.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package router
2+
3+
import (
4+
// Packages
5+
"github.com/mutablelogic/go-server/pkg/version"
6+
)
7+
8+
////////////////////////////////////////////////////////////////////////////////
9+
// GLOBALS
10+
11+
var (
12+
// Prefix
13+
scopePrefix = version.GitSource + "/scope/"
14+
)
15+
16+
////////////////////////////////////////////////////////////////////////////////
17+
// PUBLIC METHODS
18+
19+
func (router *router) ScopeRead() []string {
20+
// Return read (list, get) scopes
21+
return []string{
22+
scopePrefix + router.Label() + "/read",
23+
scopePrefix + defaultName + "/read",
24+
}
25+
}
26+
27+
func (router *router) ScopeWrite() []string {
28+
// Return write (create, delete, update) scopes
29+
return []string{
30+
scopePrefix + router.Label() + "/write",
31+
scopePrefix + defaultName + "/write",
32+
}
33+
}

0 commit comments

Comments
 (0)