github.com/greenpau/go-authcrunch@v1.1.4/pkg/authn/api_add_user_api_key.go (about) 1 // Copyright 2024 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 "context" 19 "fmt" 20 "net/http" 21 "regexp" 22 "strings" 23 24 "github.com/greenpau/go-authcrunch/pkg/authn/enums/operator" 25 "github.com/greenpau/go-authcrunch/pkg/ids" 26 "github.com/greenpau/go-authcrunch/pkg/requests" 27 "github.com/greenpau/go-authcrunch/pkg/tagging" 28 "github.com/greenpau/go-authcrunch/pkg/user" 29 ) 30 31 var apiKeyTitleRegexPattern = regexp.MustCompile(`^[\w\@\.\s\(\)]+$`) 32 var apiKeyRegexPattern1 = regexp.MustCompile(`^[A-Za-z0-9]{64,72}$`) 33 34 // AddUserAPIKey adds API key to user identity. 35 func (p *Portal) AddUserAPIKey( 36 ctx context.Context, 37 w http.ResponseWriter, 38 r *http.Request, 39 rr *requests.Request, 40 parsedUser *user.User, 41 resp map[string]interface{}, 42 usr *user.User, 43 backend ids.IdentityStore, 44 bodyData map[string]interface{}) error { 45 46 var keyTitle, keyDescription, keyPayload string 47 var keyLabels []string = []string{} 48 var keyTags []tagging.Tag = []tagging.Tag{} 49 50 // Extract data. 51 if v, exists := bodyData["content"]; exists { 52 switch exp := v.(type) { 53 case string: 54 keyPayload = strings.TrimSpace(exp) 55 default: 56 resp["message"] = "Profile API did find key content in the request payload, but it is malformed" 57 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 58 } 59 } else { 60 resp["message"] = "Profile API did not find key content in the request payload" 61 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 62 } 63 if v, exists := bodyData["title"]; exists { 64 keyTitle = v.(string) 65 } else { 66 resp["message"] = "Profile API did not find title in the request payload" 67 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 68 } 69 if v, exists := bodyData["description"]; exists { 70 keyDescription = v.(string) 71 } else { 72 resp["message"] = "Profile API did not find description in the request payload" 73 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 74 } 75 if extractedTokenTags, err := tagging.ExtractTags(bodyData); err == nil { 76 for _, extractedTokenTag := range extractedTokenTags { 77 keyTags = append(keyTags, *extractedTokenTag) 78 } 79 } else { 80 resp["message"] = "Profile API find malformed tags in the request payload" 81 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 82 } 83 if extractedTokenLabels, err := tagging.ExtractLabels(bodyData); err == nil { 84 keyLabels = extractedTokenLabels 85 } else { 86 resp["message"] = "Profile API find malformed tags in the request payload" 87 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 88 } 89 90 // Validate data. 91 if !apiKeyTitleRegexPattern.MatchString(keyTitle) { 92 resp["message"] = "Profile API found non-compliant API key title value" 93 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 94 } 95 if !tokenDescriptionRegexPattern.MatchString(keyDescription) && (keyDescription != "") { 96 resp["message"] = "Profile API found non-compliant API key description value" 97 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 98 } 99 if !apiKeyRegexPattern1.MatchString(keyPayload) { 100 resp["message"] = "Profile API found non-compliant API key value" 101 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 102 } 103 104 rr.Key.Usage = "api" 105 rr.Key.Comment = keyTitle 106 rr.Key.Description = keyDescription 107 rr.Key.Payload = keyPayload 108 rr.Key.Labels = keyLabels 109 rr.Key.Tags = keyTags 110 111 if err := backend.Request(operator.AddAPIKey, rr); err != nil { 112 var errMsg string = fmt.Sprintf("the Profile API failed to add API key to identity store: %v", err) 113 resp["message"] = errMsg 114 return handleAPIProfileResponse(w, rr, http.StatusBadRequest, resp) 115 } 116 117 resp["entry"] = "Created" 118 return handleAPIProfileResponse(w, rr, http.StatusOK, resp) 119 }