Skip to content

Conversation

VojtaKai
Copy link
Contributor

@VojtaKai VojtaKai commented Jul 29, 2025

Regular users can no longer use "apify" in their usernames. Admins still can.

@VojtaKai VojtaKai changed the title chore(console, api): soft and hard username and actor regexes [] chore(console, api): soft and hard username and actor regexes Jul 29, 2025
@github-actions github-actions bot added the t-c&c Team covering store and finance matters. label Jul 29, 2025
@github-actions github-actions bot added the tested Temporary label used only programatically for some analytics. label Jul 29, 2025
export function isForbiddenUsername(username: string): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP);
export function isForbiddenUsername(username: string, options: { isAdmin?: boolean, isApifier?: boolean } = { isAdmin: false, isApifier: false }): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP)
Copy link
Member

Choose a reason for hiding this comment

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

Why do we need isApifier ? IMO isAdmin check is sufficient, as 90% Apifiers are admins anyway - simpler => better

Copy link
Contributor Author

@VojtaKai VojtaKai Jul 30, 2025

Choose a reason for hiding this comment

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

Apifier is a user with @apify email. The only reason is convenience when creating an apify test user, I assume. Is that correct @mhamas ?

Copy link
Member

Choose a reason for hiding this comment

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

IMHO it would make sense to remove this and rename "Apify test user" to something else (Internal test user?) to keep the same behaviour for test user as for users. It will simplify adding tests for this.

Copy link
Contributor Author

@VojtaKai VojtaKai Jul 30, 2025

Choose a reason for hiding this comment

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

The option isApifier will be removed and apify test users will be renamed to internal users.

Copy link
Member

Choose a reason for hiding this comment

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

Cool. The fewer special cases the better

@VojtaKai VojtaKai changed the title chore(console, api): soft and hard username and actor regexes chore(console, api): soft and hard regexes for username and actor name / title Jul 30, 2025
export function isForbiddenUsername(username: string): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP);
export function isForbiddenUsername(username: string, options: { isAdmin?: boolean, isApifier?: boolean } = { isAdmin: false, isApifier: false }): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP)
Copy link
Member

Choose a reason for hiding this comment

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

IMHO it would make sense to remove this and rename "Apify test user" to something else (Internal test user?) to keep the same behaviour for test user as for users. It will simplify adding tests for this.

MAX_LENGTH: DNS_SAFE_NAME_MAX_LENGTH, // DNS-safe string length
REGEX: DNS_SAFE_NAME_REGEX,
REGEX: /^(?!.*apify)([a-z0-9]|[a-z0-9][a-z0-9-]*[a-z0-9])$/i,
ADMIN_REGEX: DNS_SAFE_NAME_REGEX,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mtrunkat If I add the min and max length in the DNS_SAFE_NAME_REGEX, it might potentially throw weird errors in forms because in some cases, it is only necessary to match the expression but not the length.

Example: https://github.com/apify/apify-core/blob/develop/src/packages/schemas/src/key_value_stores.ts#L9-L15

Should I add the length there?

Copy link
Member

@jancurn jancurn Jul 30, 2025

Choose a reason for hiding this comment

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

The advantage of separating DNS_SAFE_NAME_MAX_LENGTH and DNS_SAFE_NAME_REGEX is that you get better error messages: Xxx is too long vs. Xxx doesn't match regular expression

So I'd be careful with updating these constants that are used across our code base

Copy link
Member

Choose a reason for hiding this comment

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

BTW ther are 1,700 Actors that contain "apify" in their name - will these keep working ?

Copy link
Contributor Author

@VojtaKai VojtaKai Jul 30, 2025

Choose a reason for hiding this comment

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

Very valid question. I need to investigate what actions are going to be affected by this but from my changes alone, I already know that updateActor (API PUT endpoint) will stop working IMMEDIATELY unless they change the actor name.

The other PR: https://github.com/apify/apify-core/pull/22269/files#diff-4b79096b13a59997f18f26ea5c1fedd7f620bfdd1f5c1268e08d3dfa11362cd2R265

Copy link
Contributor Author

@VojtaKai VojtaKai Jul 30, 2025

Choose a reason for hiding this comment

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

We may give them a pass if the actor names already contains "apify" (they would still need to pass the less strict regex). If it is a new one, they will need to comply with the new regex.

Copy link
Member

Choose a reason for hiding this comment

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

Looking at the other PR, I don't have a very good feeling about this change, it can cause more problems than benefits...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The updateActor will not throw an error if the actor already had "apify" in its name -> https://github.com/apify/apify-core/pull/22269/files#diff-4b79096b13a59997f18f26ea5c1fedd7f620bfdd1f5c1268e08d3dfa11362cd2R263

Prod DB insights:
Actors with apify in the name: 1716

  • out of it managed by Apify: 15
  • managed by Apify and public: 4
  • managed by community: 1701
  • managed by community and public: 41

Copy link
Contributor Author

@VojtaKai VojtaKai Jul 31, 2025

Choose a reason for hiding this comment

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

Original REGEX kept. New REGEX - RESTRICTED_REGEX - only applied in places where we want to make the change.

No current Actor which already has the substring "Apify" in their name or title will be affected --> https://github.com/apify/apify-core/pull/22269/files#diff-4b79096b13a59997f18f26ea5c1fedd7f620bfdd1f5c1268e08d3dfa11362cd2R263-R265
Only new actors will be affected and have to comply with the "no apify substring in actor name or title" requirement.

Copy link
Member

@mtrunkat mtrunkat Jul 31, 2025

Choose a reason for hiding this comment

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

Hmm looking at the numbers, this is a problematic change; we can't enforce this for existing Actors because we disable users from updating them. But if they changed the technical names, the integrations break. So there is no good option for developers to solve this.

Let's discuss this in person? It will be faster.

Copy link
Member

Choose a reason for hiding this comment

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

That's a great point. Honestly I'm not convinced about the whole reasoning behind this change. It makes sense to prohibit use of "apify" in username to avoid confusion, but why in Actor names? We allow "amazon", "google", etc. no problem but ban "apify". But there are legitimate cases for third-party Actors having "apify" in the name, e.g. "apify-airbyte-integration" or "apify-store-scraper".

Altogether, let's just abandon this idea.

export function isForbiddenUsername(username: string): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP);
export function isForbiddenUsername(username: string, options: { isAdmin?: boolean, isApifier?: boolean } = { isAdmin: false, isApifier: false }): boolean {
return !!username.match(APIFY_ID_REGEX) || !!username.match(FORBIDDEN_REGEXP)
Copy link
Contributor Author

@VojtaKai VojtaKai Jul 30, 2025

Choose a reason for hiding this comment

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

The option isApifier will be removed and apify test users will be renamed to internal users.

expect(utils.isForbiddenUsername('karel.novak')).toBe(false);

// Regular user vs Admin
expect(utils.isForbiddenUsername('aPifY')).toBe(true);
Copy link
Member

Choose a reason for hiding this comment

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

Pls let's test cases where Apify is in the middle of the string

@VojtaKai VojtaKai requested review from jancurn and mtrunkat July 31, 2025 07:28
Copy link
Member

@jancurn jancurn left a comment

Choose a reason for hiding this comment

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

As discussed in #525 (comment), let's abandon prohibiting "apify" in actor names, it solves a problem that doesn't even exist and opens a lot more actual problems.

@VojtaKai VojtaKai requested a review from jancurn July 31, 2025 13:15
Copy link
Member

@jancurn jancurn left a comment

Choose a reason for hiding this comment

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

Great, thanks

Copy link
Member

@gippy gippy left a comment

Choose a reason for hiding this comment

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

As mentioned on slack. I do not believe that this change should be done here and should instead be done directly in console backend. This is open source package + it is used on the web. There is no reason why people should know that we allow apify for admins and it would be much cleaner if we just had a condition for apify directly in the update username method. Which is the only place it is used except for the web.

As for the web, If we keep this as it is, and you merge it, you also need to update the logic there, because on the web it's used to check in routing if the path is a valid username, to redirect users to correct user profile pages.
Here: https://github.com/apify/apify-web/blob/e410bac5e1f2943b37b5d51c43cba2d5ecf2c5bc/src/server/lib/helpers.ts#L93
So this path: https://apify.com/apify would no longer work

And to fix it on the web you would have to call it with { isAdmin: true } which is weird.

So I think either you should move this logic (checking apify) to backend, or rename the argument to be isApifyAllowed instead of isAdmin so that it's clearer when used on the web.

@VojtaKai
Copy link
Contributor Author

VojtaKai commented Aug 1, 2025

Thank you for the insights. The option will be removed and the condition will be moved to backend.

@VojtaKai VojtaKai changed the title chore(console, api): soft and hard regexes for username and actor name / title chore(console, api): soft and hard regexes for usernames Aug 11, 2025
@VojtaKai VojtaKai merged commit 91af634 into master Aug 11, 2025
10 checks passed
@VojtaKai VojtaKai deleted the chore/prohibit-keyword-apify-in-usernames-actors-for-non-admins branch August 11, 2025 11:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
t-c&c Team covering store and finance matters. tested Temporary label used only programatically for some analytics.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants