CreateAPIKey creates a new API key with the specified parameters and stores it in the database. The key is hashed using bcrypt before storage for security. The plain text key is returned ONLY during creation and should be displayed to the user immediately as it cannot be retrieved later. Parameters
(ctx context.Context, name, ownerID string, scopes []string, expiresAt time.Time)
| 63 | // - *model.APIKey: The created API key object with the PLAIN TEXT key (store this immediately, it won't be retrievable later). |
| 64 | // - error: An error if the API key creation fails during generation or database insertion. |
| 65 | func (s *Datasource) CreateAPIKey(ctx context.Context, name, ownerID string, scopes []string, expiresAt time.Time) (*model.APIKey, error) { |
| 66 | // Generate the API key with plain text |
| 67 | apiKey, err := model.NewAPIKey(name, ownerID, scopes, expiresAt) |
| 68 | if err != nil { |
| 69 | return nil, err |
| 70 | } |
| 71 | |
| 72 | // Store the plain text key to return to the user |
| 73 | plainTextKey := apiKey.Key |
| 74 | |
| 75 | // Extract prefix for efficient lookup |
| 76 | keyPrefix := getKeyPrefix(plainTextKey) |
| 77 | |
| 78 | // Hash the key using bcrypt before storing in database |
| 79 | hashedKey, err := hashAPIKey(plainTextKey) |
| 80 | if err != nil { |
| 81 | return nil, fmt.Errorf("failed to hash API key: %w", err) |
| 82 | } |
| 83 | apiKey.Key = hashedKey |
| 84 | |
| 85 | query := ` |
| 86 | INSERT INTO ledgerforge.api_keys (api_key_id, key, key_prefix, name, owner_id, scopes, expires_at, created_at, last_used_at, is_revoked) |
| 87 | VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) |
| 88 | ` |
| 89 | |
| 90 | _, err = s.Conn.ExecContext(ctx, query, |
| 91 | apiKey.APIKeyID, |
| 92 | apiKey.Key, // This is now the bcrypt hashed key |
| 93 | keyPrefix, |
| 94 | apiKey.Name, |
| 95 | apiKey.OwnerID, |
| 96 | pq.StringArray(apiKey.Scopes), |
| 97 | apiKey.ExpiresAt, |
| 98 | apiKey.CreatedAt, |
| 99 | apiKey.LastUsedAt, |
| 100 | apiKey.IsRevoked, |
| 101 | ) |
| 102 | if err != nil { |
| 103 | return nil, err |
| 104 | } |
| 105 | |
| 106 | // Return the API key with the PLAIN TEXT key for the user |
| 107 | // This is the ONLY time they'll see this key |
| 108 | apiKey.Key = plainTextKey |
| 109 | return apiKey, nil |
| 110 | } |
| 111 | |
| 112 | // GetAPIKey retrieves an API key from the database using its key string. |
| 113 | // The provided key's prefix is used for efficient lookup, then bcrypt verifies the full key. |