|
| 1 | +# App Users Pagination Examples |
| 2 | + |
| 3 | +This document demonstrates how to use the new pagination features for the `GetAppUsers` method. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +The OneLogin Go SDK now supports pagination for retrieving app users, allowing you to handle applications with more than 100 users. The implementation maintains backward compatibility: |
| 8 | + |
| 9 | +1. `GetAppUsers(appID int)` - **Original method** (fully backward compatible) |
| 10 | +2. `GetAppUsersWithPagination(appID int, queryParams *AppUserQuery)` - **New method** with pagination parameters |
| 11 | +3. `GetAppUsersWithPaginationAndContext(ctx context.Context, appID int, queryParams *AppUserQuery)` - **New method** with context support |
| 12 | + |
| 13 | +## Basic Usage |
| 14 | + |
| 15 | +### 1. Backward Compatible (Original Method - No Changes Required) |
| 16 | + |
| 17 | +```go |
| 18 | +// This works exactly as before - returns up to 100 users |
| 19 | +// NO CODE CHANGES NEEDED for existing applications |
| 20 | +users, err := sdk.GetAppUsers(123) |
| 21 | +if err != nil { |
| 22 | + log.Fatalf("Failed to get app users: %v", err) |
| 23 | +} |
| 24 | + |
| 25 | +// users is still interface{} - same as before |
| 26 | +fmt.Printf("Retrieved users: %+v\n", users) |
| 27 | +``` |
| 28 | + |
| 29 | +### 2. With Pagination Parameters (New Method) |
| 30 | + |
| 31 | +```go |
| 32 | +// Create query with pagination parameters |
| 33 | +query := &models.AppUserQuery{ |
| 34 | + Limit: "50", // Get 50 users per page |
| 35 | + Page: "2", // Get page 2 |
| 36 | +} |
| 37 | + |
| 38 | +result, err := sdk.GetAppUsersWithPagination(123, query) |
| 39 | +if err != nil { |
| 40 | + log.Fatalf("Failed to get app users: %v", err) |
| 41 | +} |
| 42 | + |
| 43 | +// Access the users data |
| 44 | +users := result.Data |
| 45 | + |
| 46 | +// Access pagination metadata |
| 47 | +fmt.Printf("Current page: %d\n", result.Pagination.CurrentPage) |
| 48 | +fmt.Printf("Total pages: %d\n", result.Pagination.TotalPages) |
| 49 | +fmt.Printf("Total count: %d\n", result.Pagination.TotalCount) |
| 50 | +fmt.Printf("Next page cursor: %s\n", result.Pagination.AfterCursor) |
| 51 | +``` |
| 52 | + |
| 53 | +### 3. With Context Support (New Method) |
| 54 | + |
| 55 | +```go |
| 56 | +ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) |
| 57 | +defer cancel() |
| 58 | + |
| 59 | +query := &models.AppUserQuery{ |
| 60 | + Limit: "50", |
| 61 | + Page: "1", |
| 62 | +} |
| 63 | + |
| 64 | +result, err := sdk.GetAppUsersWithPaginationAndContext(ctx, 123, query) |
| 65 | +if err != nil { |
| 66 | + log.Fatalf("Failed to get app users: %v", err) |
| 67 | +} |
| 68 | + |
| 69 | +// Same result structure as above |
| 70 | +users := result.Data |
| 71 | +pagination := result.Pagination |
| 72 | +``` |
| 73 | + |
| 74 | +## Advanced Usage |
| 75 | + |
| 76 | +### Cursor-Based Pagination |
| 77 | + |
| 78 | +For better performance with large datasets, use cursor-based pagination: |
| 79 | + |
| 80 | +```go |
| 81 | +query := &models.AppUserQuery{ |
| 82 | + Limit: "50", |
| 83 | + Cursor: "your_cursor_here", |
| 84 | +} |
| 85 | + |
| 86 | +result, err := sdk.GetAppUsersWithPagination(123, query) |
| 87 | +``` |
| 88 | + |
| 89 | +### Iterating Through All Pages |
| 90 | + |
| 91 | +```go |
| 92 | +var allUsers []interface{} |
| 93 | +cursor := "" |
| 94 | +ctx := context.Background() |
| 95 | + |
| 96 | +for { |
| 97 | + query := &models.AppUserQuery{ |
| 98 | + Limit: "50", |
| 99 | + Cursor: cursor, |
| 100 | + } |
| 101 | + |
| 102 | + result, err := sdk.GetAppUsersWithPaginationAndContext(ctx, 123, query) |
| 103 | + if err != nil { |
| 104 | + log.Fatalf("Failed to get page: %v", err) |
| 105 | + } |
| 106 | + |
| 107 | + // Add users from this page |
| 108 | + if users, ok := result.Data.([]interface{}); ok { |
| 109 | + allUsers = append(allUsers, users...) |
| 110 | + } |
| 111 | + |
| 112 | + // Check if there's a next page |
| 113 | + if result.Pagination.AfterCursor == "" { |
| 114 | + break // No more pages |
| 115 | + } |
| 116 | + |
| 117 | + cursor = result.Pagination.AfterCursor |
| 118 | +} |
| 119 | + |
| 120 | +fmt.Printf("Retrieved %d total users\n", len(allUsers)) |
| 121 | +``` |
| 122 | + |
| 123 | +## AppUserQuery Parameters |
| 124 | + |
| 125 | +The `AppUserQuery` struct supports the following parameters: |
| 126 | + |
| 127 | +- `Limit` (string): Number of results per page (e.g., "50", "100") |
| 128 | +- `Page` (string): Page number to retrieve (e.g., "1", "2", "3") |
| 129 | +- `Cursor` (string): Cursor for cursor-based pagination |
| 130 | + |
| 131 | +## PagedResponse Structure |
| 132 | + |
| 133 | +The new pagination methods return a `*PagedResponse` with: |
| 134 | + |
| 135 | +```go |
| 136 | +type PagedResponse struct { |
| 137 | + Data interface{} `json:"data"` // The actual user data |
| 138 | + Pagination PaginationInfo `json:"pagination"` // Pagination metadata |
| 139 | +} |
| 140 | + |
| 141 | +type PaginationInfo struct { |
| 142 | + Cursor string `json:"cursor,omitempty"` |
| 143 | + AfterCursor string `json:"after_cursor,omitempty"` |
| 144 | + BeforeCursor string `json:"before_cursor,omitempty"` |
| 145 | + TotalPages int `json:"total_pages,omitempty"` |
| 146 | + CurrentPage int `json:"current_page,omitempty"` |
| 147 | + TotalCount int `json:"total_count,omitempty"` |
| 148 | +} |
| 149 | +``` |
| 150 | + |
| 151 | +## Error Handling |
| 152 | + |
| 153 | +The methods include improved error handling with context: |
| 154 | + |
| 155 | +```go |
| 156 | +query := &models.AppUserQuery{ |
| 157 | + Limit: "invalid_value", |
| 158 | +} |
| 159 | + |
| 160 | +result, err := sdk.GetAppUsersWithPagination(123, query) |
| 161 | +if err != nil { |
| 162 | + // Handle validation error with context |
| 163 | + fmt.Printf("Parameter validation failed: %v\n", err) |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +## Migration Guide |
| 168 | + |
| 169 | +### ✅ **No Breaking Changes - Existing Code Works Unchanged** |
| 170 | + |
| 171 | +**Existing code (no changes needed):** |
| 172 | +```go |
| 173 | +users, err := sdk.GetAppUsers(appID) |
| 174 | +// This continues to work exactly as before |
| 175 | +``` |
| 176 | + |
| 177 | +**To add pagination (new functionality):** |
| 178 | +```go |
| 179 | +// Option 1: Add pagination support |
| 180 | +query := &models.AppUserQuery{Limit: "50", Page: "1"} |
| 181 | +result, err := sdk.GetAppUsersWithPagination(appID, query) |
| 182 | +users := result.Data |
| 183 | + |
| 184 | +// Option 2: Add context support |
| 185 | +ctx := context.Background() |
| 186 | +result, err := sdk.GetAppUsersWithPaginationAndContext(ctx, appID, query) |
| 187 | +users := result.Data |
| 188 | +``` |
| 189 | + |
| 190 | +## Backward Compatibility Guarantee |
| 191 | + |
| 192 | +- ✅ **Original `GetAppUsers(appID int)` method unchanged** |
| 193 | +- ✅ **Same return type: `(interface{}, error)`** |
| 194 | +- ✅ **Same behavior: returns up to 100 users** |
| 195 | +- ✅ **Existing code requires no modifications** |
| 196 | +- ✅ **New functionality available through new methods** |
| 197 | + |
| 198 | +This approach ensures existing applications continue to work while providing new pagination capabilities through additional methods. |
0 commit comments