@@ -3,6 +3,7 @@ package provider
33import (
44 "context"
55 "fmt"
6+ "strings"
67
78 "github.com/hashicorp/terraform-plugin-log/tflog"
89 "github.com/hashicorp/terraform-plugin-sdk/v2/diag"
@@ -47,21 +48,103 @@ func dataSourceOpenAIProjectUser() *schema.Resource {
4748 }
4849}
4950
50- // dataSourceOpenAIProjectUserRead handles the read operation for the OpenAI project user data source .
51- // It retrieves information about a specific user in a project from the OpenAI API .
52- func dataSourceOpenAIProjectUserRead (ctx context.Context , d * schema. ResourceData , m interface {}) diag. Diagnostics {
53- c , err := GetOpenAIClientWithAdminKey (m )
51+ // dataSourceFindProjectUser finds a user in a project by ID with automatic pagination .
52+ // This is used by the data source to ensure proper user lookups across all pages .
53+ func dataSourceFindProjectUser (ctx context.Context , c interface {}, projectID , userID string ) ( * client. ProjectUser , bool , error ) {
54+ clientInstance , err := GetOpenAIClientWithAdminKey (c )
5455 if err != nil {
55- return diag .FromErr (err )
56+ return nil , false , err
57+ }
58+
59+ const batchSize = 100
60+ tflog .Debug (ctx , fmt .Sprintf ("Finding user %s in project %s with pagination" , userID , projectID ))
61+
62+ var after string
63+ hasMore := true
64+ pageCount := 0
65+
66+ for hasMore {
67+ pageCount ++
68+ tflog .Debug (ctx , fmt .Sprintf ("Fetching page %d for project %s (after: %s)" , pageCount , projectID , after ))
69+
70+ userList , err := clientInstance .ListProjectUsers (projectID , after , batchSize )
71+ if err != nil {
72+ return nil , false , fmt .Errorf ("error fetching project users (page %d): %w" , pageCount , err )
73+ }
74+
75+ // Look for the user in this page
76+ for _ , user := range userList .Data {
77+ if user .ID == userID {
78+ tflog .Debug (ctx , fmt .Sprintf ("Found user %s in project %s on page %d" , userID , projectID , pageCount ))
79+ return & user , true , nil
80+ }
81+ }
82+
83+ // Check if there are more pages
84+ hasMore = userList .HasMore
85+ if hasMore && userList .LastID != "" {
86+ after = userList .LastID
87+ }
5688 }
5789
90+ tflog .Debug (ctx , fmt .Sprintf ("User %s not found in project %s after checking %d pages" , userID , projectID , pageCount ))
91+ return nil , false , nil
92+ }
93+
94+ // dataSourceFindProjectUserByEmail finds a user in a project by email with automatic pagination.
95+ // This is used by the data source to ensure proper user lookups across all pages.
96+ func dataSourceFindProjectUserByEmail (ctx context.Context , c interface {}, projectID , email string ) (* client.ProjectUser , bool , error ) {
97+ clientInstance , err := GetOpenAIClientWithAdminKey (c )
98+ if err != nil {
99+ return nil , false , err
100+ }
101+
102+ const batchSize = 100
103+ tflog .Debug (ctx , fmt .Sprintf ("Finding user by email %s in project %s with pagination" , email , projectID ))
104+
105+ var after string
106+ hasMore := true
107+ pageCount := 0
108+
109+ for hasMore {
110+ pageCount ++
111+ tflog .Debug (ctx , fmt .Sprintf ("Fetching page %d for project %s (after: %s)" , pageCount , projectID , after ))
112+
113+ userList , err := clientInstance .ListProjectUsers (projectID , after , batchSize )
114+ if err != nil {
115+ return nil , false , fmt .Errorf ("error fetching project users (page %d): %w" , pageCount , err )
116+ }
117+
118+ // Look for the user with matching email in this page (case insensitive)
119+ for _ , user := range userList .Data {
120+ if strings .EqualFold (user .Email , email ) {
121+ tflog .Debug (ctx , fmt .Sprintf ("Found user with email %s in project %s on page %d" , email , projectID , pageCount ))
122+ return & user , true , nil
123+ }
124+ }
125+
126+ // Check if there are more pages
127+ hasMore = userList .HasMore
128+ if hasMore && userList .LastID != "" {
129+ after = userList .LastID
130+ }
131+ }
132+
133+ tflog .Debug (ctx , fmt .Sprintf ("User with email %s not found in project %s after checking %d pages" , email , projectID , pageCount ))
134+ return nil , false , nil
135+ }
136+
137+ // dataSourceOpenAIProjectUserRead handles the read operation for the OpenAI project user data source.
138+ // It retrieves information about a specific user in a project from the OpenAI API.
139+ func dataSourceOpenAIProjectUserRead (ctx context.Context , d * schema.ResourceData , m interface {}) diag.Diagnostics {
58140 projectID := d .Get ("project_id" ).(string )
59141 if projectID == "" {
60142 return diag .FromErr (fmt .Errorf ("project_id is required" ))
61143 }
62144
63145 var projectUser * client.ProjectUser
64146 var exists bool
147+ var err error
65148
66149 // Check if we're looking up by user_id or email
67150 if userID , ok := d .GetOk ("user_id" ); ok {
@@ -74,7 +157,7 @@ func dataSourceOpenAIProjectUserRead(ctx context.Context, d *schema.ResourceData
74157 tflog .Debug (ctx , fmt .Sprintf ("Checking if user %s exists in project %s" , userID , projectID ))
75158
76159 // Check if the user exists in the project using the provider's API key
77- projectUser , exists , err = c . FindProjectUser ( projectID , userID )
160+ projectUser , exists , err = dataSourceFindProjectUser ( ctx , m , projectID , userID )
78161 if err != nil {
79162 tflog .Error (ctx , fmt .Sprintf ("Error checking if user exists: %v" , err ))
80163 return diag .Errorf ("Error checking if user exists in project: %s" , err )
@@ -96,7 +179,7 @@ func dataSourceOpenAIProjectUserRead(ctx context.Context, d *schema.ResourceData
96179 tflog .Debug (ctx , fmt .Sprintf ("Checking if user with email %s exists in project %s" , email , projectID ))
97180
98181 // Check if the user exists in the project by email using the provider's API key
99- projectUser , exists , err = c . FindProjectUserByEmail ( projectID , email )
182+ projectUser , exists , err = dataSourceFindProjectUserByEmail ( ctx , m , projectID , email )
100183 if err != nil {
101184 tflog .Error (ctx , fmt .Sprintf ("Error checking if user exists by email: %v" , err ))
102185 return diag .Errorf ("Error checking if user exists in project by email: %s" , err )
0 commit comments