Skip to content

Commit

Permalink
update middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
agungdwiprasetyo committed Dec 6, 2022
1 parent 74b7f7f commit cca6ebf
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 38 deletions.
15 changes: 15 additions & 0 deletions candishared/filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,18 @@ func (f *Filter) CalculateOffset() int {
f.Offset = (f.Page - 1) * f.Limit
return f.Offset
}

// GetPage method
func (f *Filter) GetPage() int {
return f.Page
}

// IncrPage method
func (f *Filter) IncrPage() {
f.Page++
}

// GetLimit method
func (f *Filter) GetLimit() int {
return f.Limit
}
14 changes: 12 additions & 2 deletions codebase/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package app

import (
"context"
"errors"
"fmt"
"log"
"os"
Expand All @@ -28,8 +29,8 @@ func New(service factory.ServiceFactory) *App {
// Run start app
func (a *App) Run() {

if len(a.service.GetApplications()) == 0 {
panic("No server/worker running")
if err := a.checkRequired(); err != nil {
panic(err)
}

errServe := make(chan error)
Expand Down Expand Up @@ -83,3 +84,12 @@ func (a *App) shutdown(forceShutdown chan os.Signal) {
log.Println("\x1b[31;1mContext timeout\x1b[0m")
}
}

func (a *App) checkRequired() (err error) {

if len(a.service.GetApplications()) == 0 {
return errors.New("No server/worker running")
}

return
}
2 changes: 1 addition & 1 deletion codebase/app/task_queue_worker/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type configurationUsecase struct {

func initConfiguration(opt *option) *configurationUsecase {
defaultConfigs := []Configuration{
{Key: configurationRetentionAgeKey, Name: "Retention Age", Value: "10m", IsActive: false},
{Key: configurationRetentionAgeKey, Name: "Retention Age", Value: "0 0 * * *", IsActive: false},
{Key: configurationClientSubscriberAgeKey, Name: "Client Subscriber Age", Value: "10m", IsActive: false},
{Key: configurationMaxClientSubscriberKey, Name: "Max Client Subscriber", Value: "5", IsActive: false},
{Key: configurationTraceDetailURL, Name: "Trace Detail URL", Value: "http://localhost:16686/trace", IsActive: true},
Expand Down
9 changes: 6 additions & 3 deletions codebase/interfaces/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ type HTTPMiddleware interface {

// HTTPPermissionACL method.
// This middleware required TokenValidator (HTTPBearerAuth middleware must executed before) for extract userID
// from token (from `Subject` field in token claim payload)
// default from `Subject` field in token claim payload
// or you can custom extract user id with `SetUserIDExtractor` option when construct middleware in configs
HTTPPermissionACL(permissionCode string) func(http.Handler) http.Handler
}

Expand All @@ -38,7 +39,8 @@ type GRPCMiddleware interface {

// GRPCPermissionACL method.
// This middleware required TokenValidator (GRPCBearerAuth middleware must executed before) for extract userID
// from token (from `Subject` field in token claim payload)
// default from `Subject` field in token claim payload
// or you can custom extract user id with `SetUserIDExtractor` option when construct middleware in configs
GRPCPermissionACL(permissionCode string) types.MiddlewareFunc
}

Expand All @@ -48,7 +50,8 @@ type GraphQLMiddleware interface {

// GraphQLPermissionACL method.
// This middleware required TokenValidator (GraphQLAuth middleware with BEARER must executed before) for extract userID
// from token (from `Subject` field in token claim payload)
// default from `Subject` field in token claim payload
// or you can custom extract user id with `SetUserIDExtractor` option when construct middleware in configs
GraphQLPermissionACL(ctx context.Context, directive *gqltypes.Directive, input interface{}) (context.Context, error)
}

Expand Down
11 changes: 10 additions & 1 deletion middleware/acl_permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,16 @@ func (m *Middleware) checkACLPermissionFromContext(ctx context.Context, permissi
}()

tokenClaim = candishared.ParseTokenClaimFromContext(ctx)
role, err := m.ACLPermissionChecker.CheckPermission(ctx, tokenClaim.Subject, permissionCode)

if m.aclPermissionChecker == nil {
return tokenClaim, errors.New("Missing acl permission checker")
}

userID := tokenClaim.Subject
if m.extractUserIDFunc != nil {
userID = m.extractUserIDFunc(tokenClaim)
}
role, err := m.aclPermissionChecker.CheckPermission(ctx, userID, permissionCode)
if err != nil {
return tokenClaim, err
}
Expand Down
28 changes: 12 additions & 16 deletions middleware/basic.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,26 +22,22 @@ const (

// Basic function basic auth
func (m *Middleware) Basic(ctx context.Context, key string) error {
isValid := func() bool {
data, err := base64.StdEncoding.DecodeString(key)
if err != nil {
return false
}

decoded := strings.Split(string(data), ":")
if len(decoded) < 2 {
return false
}
username, password := decoded[0], decoded[1]
if m.basicAuthValidator == nil {
return errors.New("Missing basic auth implementor")
}

if err := m.BasicAuthValidator.ValidateBasic(username, password); err != nil {
return false
}
data, err := base64.StdEncoding.DecodeString(key)
if err != nil {
return errors.New("Unauthorized")
}

return true
decoded := strings.Split(string(data), ":")
if len(decoded) < 2 {
return errors.New("Unauthorized")
}
username, password := decoded[0], decoded[1]

if !isValid() {
if err := m.basicAuthValidator.ValidateBasic(username, password); err != nil {
return errors.New("Unauthorized")
}

Expand Down
6 changes: 3 additions & 3 deletions middleware/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestBasicAuth(t *testing.T) {

env.SetEnv(env.Env{BasicAuthUsername: basicUsername, BasicAuthPassword: basicPass})
midd := &Middleware{
BasicAuthValidator: defaultMiddleware{},
basicAuthValidator: defaultMiddleware{},
}

t.Run("Test With Valid Auth", func(t *testing.T) {
Expand Down Expand Up @@ -66,7 +66,7 @@ func TestBasicAuth(t *testing.T) {
func TestMiddleware_HTTPBasicAuth(t *testing.T) {
env.SetEnv(env.Env{BasicAuthUsername: basicUsername, BasicAuthPassword: basicPass})
mw := &Middleware{
BasicAuthValidator: defaultMiddleware{},
basicAuthValidator: defaultMiddleware{},
}

tests := []struct {
Expand Down Expand Up @@ -110,7 +110,7 @@ func TestMiddleware_HTTPBasicAuth(t *testing.T) {
func TestMiddleware_GRPCBasicAuth(t *testing.T) {
env.SetEnv(env.Env{BasicAuthUsername: basicUsername, BasicAuthPassword: basicPass})
mw := &Middleware{
BasicAuthValidator: defaultMiddleware{},
basicAuthValidator: defaultMiddleware{},
}

t.Run("Testcase #1: Positive", func(t *testing.T) {
Expand Down
6 changes: 5 additions & 1 deletion middleware/bearer.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,11 @@ const (

// Bearer token validator
func (m *Middleware) Bearer(ctx context.Context, tokenString string) (*candishared.TokenClaim, error) {
tokenClaim, err := m.TokenValidator.ValidateToken(ctx, tokenString)
if m.tokenValidator == nil {
return nil, errors.New("Missing token validator")
}

tokenClaim, err := m.tokenValidator.ValidateToken(ctx, tokenString)
if err != nil {
return nil, err
}
Expand Down
35 changes: 25 additions & 10 deletions middleware/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,21 @@ import (

// Middleware impl
type Middleware struct {
TokenValidator interfaces.TokenValidator
ACLPermissionChecker interfaces.ACLPermissionChecker
BasicAuthValidator interfaces.BasicAuthValidator
tokenValidator interfaces.TokenValidator
aclPermissionChecker interfaces.ACLPermissionChecker
basicAuthValidator interfaces.BasicAuthValidator

extractUserIDFunc func(tokenClaim *candishared.TokenClaim) (userID string)
}

// NewMiddleware create new middleware instance
// NewMiddleware create new middleware instance (DEPRECATED, use NewMiddlewareWithOption)
func NewMiddleware(tokenValidator interfaces.TokenValidator, aclPermissionChecker interfaces.ACLPermissionChecker) *Middleware {
mw := &Middleware{
TokenValidator: tokenValidator, ACLPermissionChecker: aclPermissionChecker,
BasicAuthValidator: &defaultMiddleware{},
tokenValidator: tokenValidator, aclPermissionChecker: aclPermissionChecker,
basicAuthValidator: &defaultMiddleware{},
extractUserIDFunc: func(tokenClaim *candishared.TokenClaim) (userID string) {
return tokenClaim.Subject
},
}

return mw
Expand All @@ -31,7 +36,10 @@ func NewMiddleware(tokenValidator interfaces.TokenValidator, aclPermissionChecke
func NewMiddlewareWithOption(opts ...OptionFunc) *Middleware {
defaultMw := &defaultMiddleware{}
mw := &Middleware{
TokenValidator: defaultMw, ACLPermissionChecker: defaultMw, BasicAuthValidator: defaultMw,
tokenValidator: defaultMw, aclPermissionChecker: defaultMw, basicAuthValidator: defaultMw,
extractUserIDFunc: func(tokenClaim *candishared.TokenClaim) (userID string) {
return tokenClaim.Subject
},
}
for _, opt := range opts {
opt(mw)
Expand All @@ -56,21 +64,28 @@ type OptionFunc func(*Middleware)
// SetTokenValidator option func
func SetTokenValidator(tokenValidator interfaces.TokenValidator) OptionFunc {
return func(mw *Middleware) {
mw.TokenValidator = tokenValidator
mw.tokenValidator = tokenValidator
}
}

// SetACLPermissionChecker option func
func SetACLPermissionChecker(aclPermissionChecker interfaces.ACLPermissionChecker) OptionFunc {
return func(mw *Middleware) {
mw.ACLPermissionChecker = aclPermissionChecker
mw.aclPermissionChecker = aclPermissionChecker
}
}

// SetBasicAuthValidator option func
func SetBasicAuthValidator(basicAuth interfaces.BasicAuthValidator) OptionFunc {
return func(mw *Middleware) {
mw.BasicAuthValidator = basicAuth
mw.basicAuthValidator = basicAuth
}
}

// SetUserIDExtractor option func, custom extract user id from token claim for acl permission checker
func SetUserIDExtractor(extractor func(tokenClaim *candishared.TokenClaim) (userID string)) OptionFunc {
return func(mw *Middleware) {
mw.extractUserIDFunc = extractor
}
}

Expand Down
2 changes: 1 addition & 1 deletion middleware/multiple.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func (m *Middleware) checkMultipleAuth(ctx context.Context, authType, token stri
case Basic:
err = m.Basic(ctx, token)
default:
return nil, errors.New("Invalid authorization type")
return nil, errors.New("Invalid authorization type, must BEARER or BASIC")
}

return claimData, err
Expand Down

0 comments on commit cca6ebf

Please sign in to comment.