@@ -1048,6 +1048,178 @@ func (c *baseClient) GetUsers(
10481048 return & GetUsersResult {userRecords , notFound }, nil
10491049}
10501050
1051+ // QueryUserInfoResponse is the response from the QueryUsers function.
1052+ type QueryUserInfoResponse struct {
1053+ Users []* UserRecord
1054+ Count int64
1055+ }
1056+
1057+ type queryUsersResponse struct {
1058+ Users []* userQueryResponse `json:"userInfo"`
1059+ Count int64 `json:"recordsCount,string,omitempty"`
1060+ }
1061+
1062+ // Expression represents a query condition used to filter results.
1063+ //
1064+ // Specify only one of Email, PhoneNumber, or UID. If you specify more than one,
1065+ // only the first (in order of Email, PhoneNumber, then UID) is applied.
1066+ type Expression struct {
1067+ // Email is a case-insensitive string that the account's email must match.
1068+ Email string `json:"email,omitempty"`
1069+ // PhoneNumber is a string that the account's phone number must match.
1070+ PhoneNumber string `json:"phoneNumber,omitempty"`
1071+ // UID is a string that the account's local ID must match.
1072+ UID string `json:"userId,omitempty"`
1073+ }
1074+
1075+ // QueryUsersRequest is the request structure for the QueryUsers function.
1076+ type QueryUsersRequest struct {
1077+ // ReturnUserInfo specifies whether to return user accounts that match the query.
1078+ // If set to false, only the count of matching accounts is returned.
1079+ // Defaults to true.
1080+ ReturnUserInfo * bool `json:"returnUserInfo,omitempty"`
1081+ // Limit is the maximum number of accounts to return with an upper limit of 500.
1082+ // Defaults to 500. This field is valid only when ReturnUserInfo is true.
1083+ Limit int64 `json:"limit,string,omitempty"`
1084+ // Offset is the number of accounts to skip from the beginning of matching records.
1085+ // This field is valid only when ReturnUserInfo is true.
1086+ Offset int64 `json:"offset,string,omitempty"`
1087+ // SortBy is the field to use for sorting user accounts.
1088+ SortBy SortBy `json:"-"`
1089+ // Order is the sort order for the query results.
1090+ Order Order `json:"-"`
1091+ // TenantID is the ID of the tenant to which the results are scoped.
1092+ TenantID string `json:"tenantId,omitempty"`
1093+ // Expression is a list of query conditions used to filter the results.
1094+ Expression []* Expression `json:"expression,omitempty"`
1095+ }
1096+
1097+ // build builds the query request (for internal use only).
1098+ func (q * QueryUsersRequest ) build () interface {} {
1099+ var sortBy string
1100+ if q .SortBy != sortByUnspecified {
1101+ sortBys := map [SortBy ]string {
1102+ UID : "USER_ID" ,
1103+ Name : "NAME" ,
1104+ CreatedAt : "CREATED_AT" ,
1105+ LastLoginAt : "LAST_LOGIN_AT" ,
1106+ UserEmail : "USER_EMAIL" ,
1107+ }
1108+ sortBy = sortBys [q .SortBy ]
1109+ }
1110+
1111+ var order string
1112+ if q .Order != orderUnspecified {
1113+ orders := map [Order ]string {
1114+ Asc : "ASC" ,
1115+ Desc : "DESC" ,
1116+ }
1117+ order = orders [q .Order ]
1118+ }
1119+
1120+ type queryUsersRequestInternal QueryUsersRequest
1121+ internal := (* queryUsersRequestInternal )(q )
1122+ if internal .ReturnUserInfo == nil {
1123+ t := true
1124+ internal .ReturnUserInfo = & t
1125+ }
1126+
1127+ return & struct {
1128+ SortBy string `json:"sortBy,omitempty"`
1129+ Order string `json:"order,omitempty"`
1130+ * queryUsersRequestInternal
1131+ }{
1132+ SortBy : sortBy ,
1133+ Order : order ,
1134+ queryUsersRequestInternal : internal ,
1135+ }
1136+ }
1137+
1138+ func (q * QueryUsersRequest ) validate () error {
1139+ if q .Limit != 0 && (q .Limit < 1 || q .Limit > 500 ) {
1140+ return fmt .Errorf ("limit must be between 1 and 500" )
1141+ }
1142+ if q .Offset < 0 {
1143+ return fmt .Errorf ("offset must be non-negative" )
1144+ }
1145+ for _ , exp := range q .Expression {
1146+ if exp .Email != "" {
1147+ if err := validateEmail (exp .Email ); err != nil {
1148+ return err
1149+ }
1150+ }
1151+ if exp .PhoneNumber != "" {
1152+ if err := validatePhone (exp .PhoneNumber ); err != nil {
1153+ return err
1154+ }
1155+ }
1156+ if exp .UID != "" {
1157+ if err := validateUID (exp .UID ); err != nil {
1158+ return err
1159+ }
1160+ }
1161+ }
1162+ return nil
1163+ }
1164+
1165+ // SortBy defines the fields available for sorting user accounts.
1166+ type SortBy int
1167+
1168+ const (
1169+ sortByUnspecified SortBy = iota
1170+ // UID sorts results by user ID.
1171+ UID
1172+ // Name sorts results by name.
1173+ Name
1174+ // CreatedAt sorts results by creation time.
1175+ CreatedAt
1176+ // LastLoginAt sorts results by the last login time.
1177+ LastLoginAt
1178+ // UserEmail sorts results by user email.
1179+ UserEmail
1180+ )
1181+
1182+ // Order defines the sort order for query results.
1183+ type Order int
1184+
1185+ const (
1186+ orderUnspecified Order = iota
1187+ // Asc sorts results in ascending order.
1188+ Asc
1189+ // Desc sorts results in descending order.
1190+ Desc
1191+ )
1192+
1193+ // QueryUsers queries for user accounts based on the provided query configuration.
1194+ func (c * baseClient ) QueryUsers (ctx context.Context , query * QueryUsersRequest ) (* QueryUserInfoResponse , error ) {
1195+ if query == nil {
1196+ return nil , fmt .Errorf ("query request must not be nil" )
1197+ }
1198+ if err := query .validate (); err != nil {
1199+ return nil , err
1200+ }
1201+
1202+ var parsed queryUsersResponse
1203+ _ , err := c .post (ctx , "/accounts:query" , query .build (), & parsed )
1204+ if err != nil {
1205+ return nil , err
1206+ }
1207+
1208+ var userRecords []* UserRecord
1209+ for _ , user := range parsed .Users {
1210+ userRecord , err := user .makeUserRecord ()
1211+ if err != nil {
1212+ return nil , fmt .Errorf ("error while parsing response: %w" , err )
1213+ }
1214+ userRecords = append (userRecords , userRecord )
1215+ }
1216+
1217+ return & QueryUserInfoResponse {
1218+ Users : userRecords ,
1219+ Count : parsed .Count ,
1220+ }, nil
1221+ }
1222+
10511223type userQueryResponse struct {
10521224 UID string `json:"localId,omitempty"`
10531225 DisplayName string `json:"displayName,omitempty"`
0 commit comments