Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core)!: enhanced user search params #2639

Merged
merged 8 commits into from
Dec 14, 2022
Merged

feat(core)!: enhanced user search params #2639

merged 8 commits into from
Dec 14, 2022

Conversation

gao-sun
Copy link
Member

@gao-sun gao-sun commented Dec 12, 2022

Summary

implement #2167

This PR enhanced GET /users API with more search options.

馃挜 Breaking change 馃挜

If you want to perform the original fuzzy search, you need to manually add % around the keyword. E.g.:

Original: GET /users?search=foo
Now: GET /users?search=%foo%

Perform a search request

A search request consists of the following parameter keys:

  • Search keywords: search, search.*
  • Search mode for fields: mode, mode.* (default value 'like', available ['exact', 'like', 'similar_to', 'posix'])
  • Joint mode: joint or jointMode (default value 'or', available ['or', 'and'])
  • Is case-sensitive: isCaseSensitive (default value false)
  • Hide admin users: hideAdminUser (default value false)

Pagination stays the same way. Let's go through them via some examples. All search params will be formatted as a constructor of URLSearchParams.

Basic fuzzy search

If you want to perform a fuzzy search over all available fields, just provide a value for key search. It will use the like operator under the hood:

new URLSearchParams([
  ['search', '%foo%']
])

This search will iterate over all available fields in a user search, i.e. id, primaryEmail, primaryPhone, username, name.

Specify fields

What if you want to limit the search in name only? To search someone that includes foo in their name, just use the . symbol to specify the field:

new URLSearchParams([
  ['search.name', '%foo%']
])

Remember nested fields are not supported, e.g. search.name.first will result an error.

You can also specify multiple fields at the same time:

new URLSearchParams([
  ['search.name', '%foo%'],
  ['search.primaryEmail', '%@gmail.com']
])

Means to search users that have foo in name OR their email ends with @gmail.com.

Changing the joint mode

If you want the API only returns the result that satisfies ALL the conditions, set the joint mode to and:

new URLSearchParams([
  ['search.name', '%foo%'],
  ['search.primaryEmail', '%@gmail.com'],
  ['joint', 'and']
])

Means to search users that have foo in name AND their email ends with @gmail.com.

Exact match and case sensitivity

Say you want to search whose name is exact "Alice". You can set mode.name to use exact match.

new URLSearchParams([
  ['search.name', 'Alice'],
  ['mode.name', 'exact']
])

You may find it has the same effect when using the like mode (default) v.s. specifying exact. One difference is exact mode uses = for comparing while like uses like or ilike. Theoretically = should have a better performance.

Plus, in exact mode, you can pass multiple values for matching, and they will be connected with or:

new URLSearchParams([
  ['search.name', 'Alice'],
  ['search.name', 'Bob'],
  ['mode.name', 'exact']
])

It will match the users with name "Alice" OR "Bob".

By default search is case-insensitive. To be more precise, set the search as case-sensitive:

new URLSearchParams([
  ['search.name', 'Alice'],
  ['search.name', 'Bob'],
  ['mode.name', 'exact'],
  ['isCaseSensitive', 'true']
])

Note isCaseSensitive is a global config. Thus EVERY field will follow it.

Regular expression (RegEx)

PostgreSQL supports two types of regular expressions, similar to and posix. Set mode to similar_to or posix to search by regular expressions:

new URLSearchParams([
  ['search', '^T.?m Scot+$'],
  ['mode', 'posix']
])

Note
Mode similar_to only works in case-sensitive searches.

Match mode override

By default, all keywords will inherit the match mode from the general search:

new URLSearchParams([
  ['search', '^T.?m Scot+$'],
  ['mode', 'posix'],
  ['search.primaryEmail', 'tom%'], // Posix mode
  ['joint', 'and']
])

To override for specific field:

new URLSearchParams([
  ['search', '^T.?m Scot+$'],
  ['mode', 'posix'],
  ['search.primaryEmail', 'tom%'], // Like mode
  ['mode.primaryEmail', 'like'],
  ['search.phone', '0{3,}'], // Posix mode
  ['joint', 'and']
])

Hide admin user

For convenience, you can apply hideAdminUser to quickly filter out all admins from the result:

new URLSearchParams([
  ['search', '%foo%'],
  ['hideAdminUser', 'true']
])

Testing

  • added integration tests
  • local Admin Console user management works as expected

@github-actions
Copy link

github-actions bot commented Dec 12, 2022

COMPARE TO master

Total Size Diff 鈿狅笍 馃搱 +20.22 KB

Diff by File
Name Diff
packages/console/src/pages/Users/index.tsx 馃搱 +2 Bytes
packages/core/nodemon.json 馃搱 +29 Bytes
packages/core/package.json 馃搱 +85 Bytes
packages/core/src/env-set/parameters.ts 馃搱 +67 Bytes
packages/core/src/lib/passcode.ts 馃搱 +39 Bytes
packages/core/src/lib/sign-in-experience/sign-in.ts 馃搱 +63 Bytes
packages/core/src/middleware/koa-auth.ts 馃搱 +65 Bytes
packages/core/src/middleware/koa-pagination.ts 馃搱 +68 Bytes
packages/core/src/queries/user.test.ts 馃搱 +4.54 KB
packages/core/src/queries/user.ts 馃搱 +8 Bytes
packages/core/src/routes/admin-user.test.ts 馃搱 +54 Bytes
packages/core/src/routes/admin-user.ts 馃搱 +36 Bytes
packages/core/src/routes/connector.ts 馃搱 +43 Bytes
packages/core/src/routes/interaction/utils/sign-in-experience-validation.ts 馃搱 +90 Bytes
packages/core/src/routes/sign-in-experience.ts 馃搱 +69 Bytes
packages/core/src/utils/search.test.ts 馃搱 +6.63 KB
packages/core/src/utils/search.ts 馃搱 +7.63 KB
packages/core/src/utils/test-utils.ts 馃搱 +377 Bytes
packages/core/src/utils/zod.ts 馃搱 +56 Bytes
packages/integration-tests/src/api/admin-user.ts 馃搱 +25 Bytes
packages/integration-tests/src/helpers.ts 馃搱 +942 Bytes
packages/integration-tests/src/tests/api/admin-user.search.test.ts 馃搱 +7.91 KB
packages/phrases/src/locales/de/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/en/errors.ts 馃搱 +70 Bytes
packages/phrases/src/locales/fr/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/ko/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/pt-br/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/pt-pt/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/tr-tr/errors.ts 馃搱 +86 Bytes
packages/phrases/src/locales/zh-cn/errors.ts 馃搱 +86 Bytes
packages/schemas/src/types/index.ts 馃搱 +29 Bytes
packages/schemas/src/types/search.ts 馃搱 +835 Bytes

@uffizzi-cloud
Copy link

uffizzi-cloud bot commented Dec 12, 2022

This branch has been deployed using Uffizzi.

Preview URL:
https://pr-2639-deployment-8890-logto.app.uffizzi.com

View deployment details here:
https://https://app.uffizzi.com/projects/4064/deployments

This is an automated comment. To turn off commenting, visit uffizzi.com.

@gao-sun gao-sun linked an issue Dec 12, 2022 that may be closed by this pull request
@gao-sun gao-sun changed the base branch from master to gao-test-native-esm-2 December 13, 2022 06:50
Base automatically changed from gao-test-native-esm-2 to master December 13, 2022 06:58
@gao-sun gao-sun changed the title feat(core): enhanced user search params feat(core)!: enhanced user search params Dec 13, 2022
@gao-sun gao-sun requested review from a team, wangsijie and simeng-li and removed request for a team December 13, 2022 10:08
@gao-sun gao-sun marked this pull request as ready for review December 13, 2022 10:08
packages/core/src/env-set/parameters.ts Outdated Show resolved Hide resolved
packages/core/src/routes/admin-user.ts Outdated Show resolved Hide resolved
packages/core/src/utils/search.ts Show resolved Hide resolved
packages/core/src/utils/search.ts Outdated Show resolved Hide resolved
packages/core/src/utils/search.ts Outdated Show resolved Hide resolved
packages/core/src/utils/search.ts Outdated Show resolved Hide resolved
packages/core/src/utils/search.ts Show resolved Hide resolved
Copy link
Contributor

@wangsijie wangsijie left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we support array values? Like /api/users?search=id:1,2,3

@gao-sun
Copy link
Member Author

gao-sun commented Dec 14, 2022

Can we support array values? Like /api/users?search=id:1,2,3

yes, integration tests covered this. added to description

Copy link
Contributor

@simeng-li simeng-li left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@gao-sun gao-sun enabled auto-merge (squash) December 14, 2022 08:34
@gao-sun gao-sun merged commit 7bf52aa into master Dec 14, 2022
@gao-sun gao-sun deleted the gao-search-api branch December 14, 2022 08:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

Successfully merging this pull request may close these issues.

feature request: search user by IDs/usernames/phones/emails
4 participants