processAndCreateKeys is the lowest-level reusable function for adding keys.
( groupID uint, keys []string, progressCallback func(processed int), )
| 88 | |
| 89 | // processAndCreateKeys is the lowest-level reusable function for adding keys. |
| 90 | func (s *KeyService) processAndCreateKeys( |
| 91 | groupID uint, |
| 92 | keys []string, |
| 93 | progressCallback func(processed int), |
| 94 | ) (addedCount int, ignoredCount int, err error) { |
| 95 | // 1. Get existing key hashes in the group for deduplication |
| 96 | var existingHashes []string |
| 97 | if err := s.DB.Model(&models.APIKey{}).Where("group_id = ?", groupID).Pluck("key_hash", &existingHashes).Error; err != nil { |
| 98 | return 0, 0, err |
| 99 | } |
| 100 | existingHashMap := make(map[string]bool) |
| 101 | for _, h := range existingHashes { |
| 102 | existingHashMap[h] = true |
| 103 | } |
| 104 | |
| 105 | // 2. Prepare new keys for creation |
| 106 | var newKeysToCreate []models.APIKey |
| 107 | uniqueNewKeys := make(map[string]bool) |
| 108 | |
| 109 | for _, keyVal := range keys { |
| 110 | trimmedKey := strings.TrimSpace(keyVal) |
| 111 | if trimmedKey == "" || uniqueNewKeys[trimmedKey] || !s.isValidKeyFormat(trimmedKey) { |
| 112 | continue |
| 113 | } |
| 114 | |
| 115 | // Generate hash for deduplication check |
| 116 | keyHash := s.EncryptionSvc.Hash(trimmedKey) |
| 117 | if existingHashMap[keyHash] { |
| 118 | continue |
| 119 | } |
| 120 | |
| 121 | encryptedKey, err := s.EncryptionSvc.Encrypt(trimmedKey) |
| 122 | if err != nil { |
| 123 | logrus.WithError(err).WithField("key", trimmedKey).Error("Failed to encrypt key, skipping") |
| 124 | continue |
| 125 | } |
| 126 | |
| 127 | uniqueNewKeys[trimmedKey] = true |
| 128 | newKeysToCreate = append(newKeysToCreate, models.APIKey{ |
| 129 | GroupID: groupID, |
| 130 | KeyValue: encryptedKey, |
| 131 | KeyHash: keyHash, |
| 132 | Status: models.KeyStatusActive, |
| 133 | }) |
| 134 | } |
| 135 | |
| 136 | if len(newKeysToCreate) == 0 { |
| 137 | return 0, len(keys), nil |
| 138 | } |
| 139 | |
| 140 | // 3. Use KeyProvider to add keys in chunks |
| 141 | for i := 0; i < len(newKeysToCreate); i += chunkSize { |
| 142 | end := i + chunkSize |
| 143 | if end > len(newKeysToCreate) { |
| 144 | end = len(newKeysToCreate) |
| 145 | } |
| 146 | chunk := newKeysToCreate[i:end] |
| 147 | if err := s.KeyProvider.AddKeys(groupID, chunk); err != nil { |
no test coverage detected