github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/portal_test.go (about)

     1  // Copyright 2022 Paul Greenberg greenpau@outlook.com
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package authn
    16  
    17  import (
    18  	"testing"
    19  
    20  	"github.com/google/go-cmp/cmp"
    21  	"github.com/greenpau/go-authcrunch/internal/tests"
    22  	"github.com/greenpau/go-authcrunch/internal/testutils"
    23  	"github.com/greenpau/go-authcrunch/pkg/acl"
    24  	"github.com/greenpau/go-authcrunch/pkg/authn/cookie"
    25  	"github.com/greenpau/go-authcrunch/pkg/authn/transformer"
    26  	"github.com/greenpau/go-authcrunch/pkg/authn/ui"
    27  	"github.com/greenpau/go-authcrunch/pkg/authz/options"
    28  	"github.com/greenpau/go-authcrunch/pkg/errors"
    29  	"github.com/greenpau/go-authcrunch/pkg/ids"
    30  	logutil "github.com/greenpau/go-authcrunch/pkg/util/log"
    31  	"go.uber.org/zap"
    32  )
    33  
    34  func TestNewPortal(t *testing.T) {
    35  	db, err := testutils.CreateTestDatabase("TestNewPortal")
    36  	if err != nil {
    37  		t.Fatalf("failed to create temp dir: %v", err)
    38  	}
    39  	dbPath := db.GetPath()
    40  	t.Logf("%v", dbPath)
    41  
    42  	var testcases = []struct {
    43  		name      string
    44  		disabled  bool
    45  		want      string
    46  		shouldErr bool
    47  		err       error
    48  
    49  		loggerFunc func() *zap.Logger
    50  		configFunc func() *PortalConfig
    51  
    52  		// Portal Config fields.
    53  		uiConfig               *ui.Parameters
    54  		userTransformerConfigs []*transformer.Config
    55  		cookieConfig           *cookie.Config
    56  		identityStoreConfigs   []*ids.IdentityStoreConfig
    57  		aclConfigs             []*acl.RuleConfiguration
    58  		tokenValidatorOptions  *options.TokenValidatorOptions
    59  		tokenGrantorOptions    *options.TokenGrantorOptions
    60  		cryptoRawConfigs       []string
    61  	}{
    62  		{
    63  			name: "test new portal without logger",
    64  			loggerFunc: func() *zap.Logger {
    65  				return nil
    66  			},
    67  			configFunc: func() *PortalConfig {
    68  				return nil
    69  			},
    70  			shouldErr: true,
    71  			err:       errors.ErrNewPortalLoggerNil,
    72  		},
    73  		{
    74  			name: "test new portal without config",
    75  			loggerFunc: func() *zap.Logger {
    76  				return logutil.NewLogger()
    77  			},
    78  			configFunc: func() *PortalConfig {
    79  				return nil
    80  			},
    81  			shouldErr: true,
    82  			err:       errors.ErrNewPortalConfigNil,
    83  		},
    84  		{
    85  			name: "test new portal without name",
    86  			loggerFunc: func() *zap.Logger {
    87  				return logutil.NewLogger()
    88  			},
    89  			configFunc: func() *PortalConfig {
    90  				return &PortalConfig{}
    91  			},
    92  			shouldErr: true,
    93  			err:       errors.ErrNewPortal.WithArgs(errors.ErrPortalConfigNameNotFound),
    94  		},
    95  		{
    96  			name: "test new portal without backends",
    97  			loggerFunc: func() *zap.Logger {
    98  				return logutil.NewLogger()
    99  			},
   100  			configFunc: func() *PortalConfig {
   101  				return &PortalConfig{
   102  					Name: "myportal",
   103  				}
   104  			},
   105  			shouldErr: true,
   106  			err:       errors.ErrNewPortal.WithArgs(errors.ErrPortalConfigBackendsNotFound),
   107  		},
   108  		{
   109  			name: "test new portal backed by local database",
   110  			loggerFunc: func() *zap.Logger {
   111  				return logutil.NewLogger()
   112  			},
   113  			configFunc: func() *PortalConfig {
   114  				return &PortalConfig{
   115  					Name: "myportal",
   116  					IdentityStores: []string{
   117  						"local_backend",
   118  					},
   119  				}
   120  			},
   121  			identityStoreConfigs: []*ids.IdentityStoreConfig{
   122  				{
   123  					Name: "local_backend",
   124  					Kind: "local",
   125  					Params: map[string]interface{}{
   126  						"path":  dbPath,
   127  						"realm": "local",
   128  					},
   129  				},
   130  			},
   131  			want: `{
   132                "config": {
   133  			    "name": "myportal",
   134  				"ui": {
   135  				  "theme": "basic"
   136  				},
   137  				"portal_admin_roles": {
   138  					"authp/admin": true
   139  				},
   140  				"portal_user_roles": {
   141  					"authp/user": true
   142  				},
   143  				"portal_guest_roles": {
   144  					"authp/guest": true
   145  				},
   146  				"token_validator_options": {
   147  				  "validate_bearer_header": true
   148  				},
   149  				"access_list_configs": [
   150  					{
   151  						"action": "allow stop",
   152  						"comment": "admin role name match",
   153  						"conditions": ["match role authp/admin"]
   154  					},
   155  					{
   156  						"action": "allow stop",
   157  						"comment": "user role name match",
   158  						"conditions": ["match role authp/user"]
   159  					},
   160  					{
   161  						"action": "allow stop",
   162  						"comment": "guest role name match",
   163  						"conditions": ["match role authp/guest"]
   164  					}
   165  				],
   166  				"identity_stores": ["local_backend"]
   167                }
   168              }`,
   169  		},
   170  	}
   171  
   172  	for _, tc := range testcases {
   173  		t.Run(tc.name, func(t *testing.T) {
   174  			if tc.disabled {
   175  				return
   176  			}
   177  			cfg := tc.configFunc()
   178  			if cfg != nil {
   179  				if tc.uiConfig != nil {
   180  					cfg.UI = tc.uiConfig
   181  				}
   182  				if len(tc.userTransformerConfigs) > 0 {
   183  					cfg.UserTransformerConfigs = tc.userTransformerConfigs
   184  				}
   185  				if tc.cookieConfig != nil {
   186  					cfg.CookieConfig = tc.cookieConfig
   187  				}
   188  				if len(tc.aclConfigs) > 0 {
   189  					cfg.AccessListConfigs = tc.aclConfigs
   190  				}
   191  				if tc.tokenValidatorOptions != nil {
   192  					cfg.TokenValidatorOptions = tc.tokenValidatorOptions
   193  				}
   194  				if tc.tokenGrantorOptions != nil {
   195  					cfg.TokenGrantorOptions = tc.tokenGrantorOptions
   196  				}
   197  				for _, s := range tc.cryptoRawConfigs {
   198  					cfg.AddRawCryptoConfigs(s)
   199  				}
   200  			}
   201  
   202  			params := PortalParameters{
   203  				Config: cfg,
   204  				Logger: tc.loggerFunc(),
   205  			}
   206  
   207  			for _, storeCfg := range tc.identityStoreConfigs {
   208  				store, err := ids.NewIdentityStore(storeCfg, logutil.NewLogger())
   209  				if err != nil {
   210  					t.Fatal(err)
   211  				}
   212  				if err := store.Configure(); err != nil {
   213  					t.Fatal(err)
   214  				}
   215  				params.IdentityStores = append(params.IdentityStores, store)
   216  			}
   217  
   218  			portal, err := NewPortal(params)
   219  			if err != nil {
   220  				if !tc.shouldErr {
   221  					t.Fatalf("expected success, got: %v", err)
   222  				}
   223  				if diff := cmp.Diff(err.Error(), tc.err.Error()); diff != "" {
   224  					t.Fatalf("unexpected error: %v, want: %v", err, tc.err)
   225  				}
   226  				return
   227  			}
   228  			if tc.shouldErr {
   229  				t.Fatalf("unexpected success, want: %v", tc.err)
   230  			}
   231  
   232  			got := make(map[string]interface{})
   233  			got["config"] = tests.Unpack(t, portal.config)
   234  			want := tests.Unpack(t, tc.want)
   235  
   236  			if diff := cmp.Diff(want, got); diff != "" {
   237  				t.Logf("JSON: %s", tests.UnpackJSON(t, got))
   238  				t.Errorf("NewPortal() config mismatch (-want +got):\n%s", diff)
   239  			}
   240  		})
   241  	}
   242  }