github.com/greenpau/go-authcrunch@v1.1.4/pkg/ids/local/authenticator_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 local 16 17 import ( 18 "fmt" 19 "github.com/google/uuid" 20 "github.com/greenpau/go-authcrunch/internal/tests" 21 "github.com/greenpau/go-authcrunch/internal/testutils" 22 "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" 23 "github.com/greenpau/go-authcrunch/pkg/errors" 24 "github.com/greenpau/go-authcrunch/pkg/identity" 25 "github.com/greenpau/go-authcrunch/pkg/requests" 26 logutil "github.com/greenpau/go-authcrunch/pkg/util/log" 27 "os" 28 "testing" 29 ) 30 31 func TestAuthenticate(t *testing.T) { 32 db, err := testutils.CreateTestDatabase("TestLocalIdentityStore") 33 if err != nil { 34 t.Fatalf("failed to create temp dir: %v", err) 35 } 36 dbPath := db.GetPath() 37 38 config := &Config{ 39 Name: "local_store", 40 Realm: "local", 41 Path: dbPath, 42 } 43 44 testcases := []struct { 45 name string 46 config *Config 47 op operator.Type 48 req *requests.Request 49 opts map[string]interface{} 50 want map[string]interface{} 51 shouldErr bool 52 err error 53 }{ 54 { 55 name: "authenticate user", 56 config: config, 57 op: operator.Authenticate, 58 req: &requests.Request{ 59 User: requests.User{ 60 Username: tests.TestUser1, 61 Email: tests.TestEmail1, 62 Password: tests.TestPwd1, 63 }, 64 }, 65 want: map[string]interface{}{ 66 "config": map[string]interface{}{ 67 "name": "local_store", 68 "realm": "local", 69 "path": dbPath, 70 "login_icon": map[string]interface{}{ 71 "background_color": string("#324960"), 72 "class_name": string("las la-key la-2x"), 73 "color": string("white"), 74 "text_color": string("#37474f"), 75 }, 76 }, 77 }, 78 }, 79 { 80 name: "authenticate user with invalid password", 81 config: config, 82 op: operator.Authenticate, 83 req: &requests.Request{ 84 User: requests.User{ 85 Username: tests.TestUser1, 86 Email: tests.TestEmail1, 87 }, 88 }, 89 shouldErr: true, 90 err: errors.ErrIdentityStoreLocalAuthFailed.WithArgs("user authentication failed: malformed auth request"), 91 }, 92 { 93 name: "test unknown operator", 94 config: config, 95 op: operator.Unknown, 96 shouldErr: true, 97 err: errors.ErrOperatorNotSupported.WithArgs(operator.Unknown), 98 }, 99 } 100 for _, tc := range testcases { 101 t.Run(tc.name, func(t *testing.T) { 102 msgs := []string{fmt.Sprintf("test name: %s", tc.name)} 103 msgs = append(msgs, fmt.Sprintf("db path: %v", tc.config.Path)) 104 msgs = append(msgs, fmt.Sprintf("config:\n%v", tc.config)) 105 logger := logutil.NewLogger() 106 107 b, err := NewIdentityStore(tc.config, logger) 108 if err != nil { 109 t.Fatalf("initialization error: %v", err) 110 } 111 112 if err := b.Configure(); err != nil { 113 t.Fatalf("configuration error: %v", err) 114 } 115 116 err = b.Request(tc.op, tc.req) 117 if tests.EvalErrWithLog(t, err, "authenticate", tc.shouldErr, tc.err, msgs) { 118 return 119 } 120 121 got := make(map[string]interface{}) 122 got["config"] = b.GetConfig() 123 tests.EvalObjectsWithLog(t, "user", tc.want, got, msgs) 124 }) 125 } 126 } 127 128 func TestNewAuthenticator(t *testing.T) { 129 testcases := []struct { 130 name string 131 config *Config 132 db func() *identity.Database 133 env map[string]string 134 authenticate bool 135 want map[string]interface{} 136 shouldErr bool 137 err error 138 }{ 139 { 140 name: "test new authenticator with user env var", 141 config: &Config{ 142 Name: "local_store", 143 Realm: "local", 144 }, 145 env: map[string]string{ 146 "AUTHP_ADMIN_USER": "myadmin", 147 "AUTHP_ADMIN_SECRET": uuid.New().String(), 148 "AUTHP_ADMIN_EMAIL": "myadmin@localdomain.local", 149 }, 150 db: func() *identity.Database { 151 db, err := testutils.CreateEmptyTestDatabase("TestLocalIdentityStore") 152 if err != nil { 153 t.Fatalf("failed to create temp dir: %v", err) 154 } 155 return db 156 }, 157 authenticate: true, 158 want: map[string]interface{}{ 159 "response": requests.Response{ 160 Code: 200, 161 }, 162 }, 163 }, 164 { 165 name: "test new authenticator without user env var", 166 config: &Config{ 167 Name: "local_store", 168 Realm: "local", 169 }, 170 db: func() *identity.Database { 171 db, err := testutils.CreateEmptyTestDatabase("TestLocalIdentityStore") 172 if err != nil { 173 t.Fatalf("failed to create temp dir: %v", err) 174 } 175 return db 176 }, 177 want: map[string]interface{}{}, 178 }, 179 { 180 name: "test new authenticator with invalid user email", 181 config: &Config{ 182 Name: "local_store", 183 Realm: "local", 184 }, 185 env: map[string]string{ 186 "AUTHP_ADMIN_USER": "myadmin", 187 "AUTHP_ADMIN_SECRET": uuid.New().String(), 188 "AUTHP_ADMIN_EMAIL": "localdomain.local", 189 }, 190 db: func() *identity.Database { 191 db, err := testutils.CreateEmptyTestDatabase("TestLocalIdentityStore") 192 if err != nil { 193 t.Fatalf("failed to create temp dir: %v", err) 194 } 195 return db 196 }, 197 shouldErr: true, 198 err: errors.ErrAddUser.WithArgs("myadmin", "invalid email address"), 199 }, 200 } 201 for _, tc := range testcases { 202 t.Run(tc.name, func(t *testing.T) { 203 msgs := []string{fmt.Sprintf("test name: %s", tc.name)} 204 for k, v := range tc.env { 205 msgs = append(msgs, fmt.Sprintf("env: %s = %s", k, v)) 206 os.Setenv(k, v) 207 defer os.Unsetenv(k) 208 } 209 db := tc.db() 210 tc.config.Path = db.GetPath() 211 msgs = append(msgs, fmt.Sprintf("db path: %v", tc.config.Path)) 212 msgs = append(msgs, fmt.Sprintf("config:\n%v", tc.config)) 213 214 b := NewAuthenticator() 215 b.logger = logutil.NewLogger() 216 err := b.Configure(db.GetPath(), nil) 217 if tests.EvalErrWithLog(t, err, "configure", tc.shouldErr, tc.err, msgs) { 218 return 219 } 220 221 req := &requests.Request{ 222 User: requests.User{ 223 Username: os.Getenv("AUTHP_ADMIN_USER"), 224 Email: os.Getenv("AUTHP_ADMIN_EMAIL"), 225 Password: os.Getenv("AUTHP_ADMIN_SECRET"), 226 }, 227 } 228 229 if tc.authenticate { 230 err = b.AuthenticateUser(req) 231 if tests.EvalErrWithLog(t, err, "authenticate", tc.shouldErr, tc.err, msgs) { 232 return 233 } 234 235 got := make(map[string]interface{}) 236 got["response"] = req.Response 237 tests.EvalObjectsWithLog(t, "user", tc.want, got, msgs) 238 } 239 }) 240 } 241 }