github.com/greenpau/go-authcrunch@v1.0.50/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 "github.com/google/go-cmp/cmp" 19 "github.com/greenpau/go-authcrunch/internal/tests" 20 "github.com/greenpau/go-authcrunch/internal/testutils" 21 "github.com/greenpau/go-authcrunch/pkg/acl" 22 "github.com/greenpau/go-authcrunch/pkg/authn/cookie" 23 "github.com/greenpau/go-authcrunch/pkg/authn/transformer" 24 "github.com/greenpau/go-authcrunch/pkg/authn/ui" 25 "github.com/greenpau/go-authcrunch/pkg/authz/options" 26 "github.com/greenpau/go-authcrunch/pkg/errors" 27 "github.com/greenpau/go-authcrunch/pkg/ids" 28 logutil "github.com/greenpau/go-authcrunch/pkg/util/log" 29 "go.uber.org/zap" 30 "testing" 31 ) 32 33 func TestNewPortal(t *testing.T) { 34 db, err := testutils.CreateTestDatabase("TestNewPortal") 35 if err != nil { 36 t.Fatalf("failed to create temp dir: %v", err) 37 } 38 dbPath := db.GetPath() 39 t.Logf("%v", dbPath) 40 41 var testcases = []struct { 42 name string 43 disabled bool 44 want string 45 shouldErr bool 46 err error 47 48 loggerFunc func() *zap.Logger 49 configFunc func() *PortalConfig 50 51 // Portal Config fields. 52 uiConfig *ui.Parameters 53 userTransformerConfigs []*transformer.Config 54 cookieConfig *cookie.Config 55 identityStoreConfigs []*ids.IdentityStoreConfig 56 aclConfigs []*acl.RuleConfiguration 57 tokenValidatorOptions *options.TokenValidatorOptions 58 tokenGrantorOptions *options.TokenGrantorOptions 59 cryptoRawConfigs []string 60 }{ 61 { 62 name: "test new portal without logger", 63 loggerFunc: func() *zap.Logger { 64 return nil 65 }, 66 configFunc: func() *PortalConfig { 67 return nil 68 }, 69 shouldErr: true, 70 err: errors.ErrNewPortalLoggerNil, 71 }, 72 { 73 name: "test new portal without config", 74 loggerFunc: func() *zap.Logger { 75 return logutil.NewLogger() 76 }, 77 configFunc: func() *PortalConfig { 78 return nil 79 }, 80 shouldErr: true, 81 err: errors.ErrNewPortalConfigNil, 82 }, 83 { 84 name: "test new portal without name", 85 loggerFunc: func() *zap.Logger { 86 return logutil.NewLogger() 87 }, 88 configFunc: func() *PortalConfig { 89 return &PortalConfig{} 90 }, 91 shouldErr: true, 92 err: errors.ErrNewPortal.WithArgs(errors.ErrPortalConfigNameNotFound), 93 }, 94 { 95 name: "test new portal without backends", 96 loggerFunc: func() *zap.Logger { 97 return logutil.NewLogger() 98 }, 99 configFunc: func() *PortalConfig { 100 return &PortalConfig{ 101 Name: "myportal", 102 } 103 }, 104 shouldErr: true, 105 err: errors.ErrNewPortal.WithArgs(errors.ErrPortalConfigBackendsNotFound), 106 }, 107 { 108 name: "test new portal backed by local database", 109 loggerFunc: func() *zap.Logger { 110 return logutil.NewLogger() 111 }, 112 configFunc: func() *PortalConfig { 113 return &PortalConfig{ 114 Name: "myportal", 115 IdentityStores: []string{ 116 "local_backend", 117 }, 118 } 119 }, 120 identityStoreConfigs: []*ids.IdentityStoreConfig{ 121 { 122 Name: "local_backend", 123 Kind: "local", 124 Params: map[string]interface{}{ 125 "path": dbPath, 126 "realm": "local", 127 }, 128 }, 129 }, 130 want: `{ 131 "config": { 132 "name": "myportal", 133 "ui": { 134 "theme": "basic" 135 }, 136 "token_validator_options": { 137 "validate_bearer_header": true 138 }, 139 "access_list_configs": [ 140 { 141 "action": "` + defaultPortalACLAction + `", 142 "conditions": ["` + defaultPortalACLCondition + `"] 143 } 144 ], 145 "identity_stores": ["local_backend"] 146 } 147 }`, 148 }, 149 } 150 151 for _, tc := range testcases { 152 t.Run(tc.name, func(t *testing.T) { 153 if tc.disabled { 154 return 155 } 156 cfg := tc.configFunc() 157 if cfg != nil { 158 if tc.uiConfig != nil { 159 cfg.UI = tc.uiConfig 160 } 161 if len(tc.userTransformerConfigs) > 0 { 162 cfg.UserTransformerConfigs = tc.userTransformerConfigs 163 } 164 if tc.cookieConfig != nil { 165 cfg.CookieConfig = tc.cookieConfig 166 } 167 if len(tc.aclConfigs) > 0 { 168 cfg.AccessListConfigs = tc.aclConfigs 169 } 170 if tc.tokenValidatorOptions != nil { 171 cfg.TokenValidatorOptions = tc.tokenValidatorOptions 172 } 173 if tc.tokenGrantorOptions != nil { 174 cfg.TokenGrantorOptions = tc.tokenGrantorOptions 175 } 176 for _, s := range tc.cryptoRawConfigs { 177 cfg.AddRawCryptoConfigs(s) 178 } 179 } 180 181 params := PortalParameters{ 182 Config: cfg, 183 Logger: tc.loggerFunc(), 184 } 185 186 for _, storeCfg := range tc.identityStoreConfigs { 187 store, err := ids.NewIdentityStore(storeCfg, logutil.NewLogger()) 188 if err != nil { 189 t.Fatal(err) 190 } 191 if err := store.Configure(); err != nil { 192 t.Fatal(err) 193 } 194 params.IdentityStores = append(params.IdentityStores, store) 195 } 196 197 portal, err := NewPortal(params) 198 if err != nil { 199 if !tc.shouldErr { 200 t.Fatalf("expected success, got: %v", err) 201 } 202 if diff := cmp.Diff(err.Error(), tc.err.Error()); diff != "" { 203 t.Fatalf("unexpected error: %v, want: %v", err, tc.err) 204 } 205 return 206 } 207 if tc.shouldErr { 208 t.Fatalf("unexpected success, want: %v", tc.err) 209 } 210 211 got := make(map[string]interface{}) 212 got["config"] = tests.Unpack(t, portal.config) 213 want := tests.Unpack(t, tc.want) 214 215 if diff := cmp.Diff(want, got); diff != "" { 216 t.Logf("JSON: %s", tests.UnpackJSON(t, got)) 217 t.Errorf("NewPortal() config mismatch (-want +got):\n%s", diff) 218 } 219 }) 220 } 221 }