diff options
| author | 2025-03-17 15:06:17 +0100 | |
|---|---|---|
| committer | 2025-03-17 14:06:17 +0000 | |
| commit | d5847e2d2b68a1eb41d43be170cd4ddff9003cff (patch) | |
| tree | 7352e79110b081eb72d483358f5c07c8d34c29ff /web/source/settings/lib/util | |
| parent | [feature/frontend] Add visibility icon for posts (#3908) (diff) | |
| download | gotosocial-d5847e2d2b68a1eb41d43be170cd4ddff9003cff.tar.xz | |
[feature] Application creation + management via API + settings panel (#3906)
* [feature] Application creation + management via API + settings panel
* fix docs links
* add errnorows test
* use known application as shorter
* add comment about side effects
Diffstat (limited to 'web/source/settings/lib/util')
| -rw-r--r-- | web/source/settings/lib/util/formvalidators.ts | 71 | ||||
| -rw-r--r-- | web/source/settings/lib/util/index.ts | 2 |
2 files changed, 71 insertions, 2 deletions
diff --git a/web/source/settings/lib/util/formvalidators.ts b/web/source/settings/lib/util/formvalidators.ts index 358db616c..4e0e4a6a8 100644 --- a/web/source/settings/lib/util/formvalidators.ts +++ b/web/source/settings/lib/util/formvalidators.ts @@ -18,6 +18,8 @@ */ import isValidDomain from "is-valid-domain"; +import { useCallback } from "react"; +import { ValidScopes, ValidTopLevelScopes } from "../types/scopes"; /** * Validate the "domain" field of a form. @@ -29,6 +31,11 @@ export function formDomainValidator(domain: string): string { return ""; } + // Allow localhost for testing. + if (domain === "localhost") { + return ""; + } + if (domain[domain.length-1] === ".") { return "invalid domain"; } @@ -63,5 +70,67 @@ export function urlValidator(urlStr: string): string { return `invalid protocol, must be http or https`; } - return formDomainValidator(url.host); + return formDomainValidator(url.hostname); +} + +export function useScopesValidator(): (_scopes: string[]) => string { + return useCallback((scopes) => { + return scopes. + map((scope) => validateScope(scope)). + flatMap((msg) => msg || []). + join(", "); + }, []); +} + +export function useScopeValidator(): (_scope: string) => string { + return useCallback((scope) => validateScope(scope), []); +} + +const validateScope = (scope: string) => { + if (!ValidScopes.includes(scope)) { + return scope + " is not a recognized scope"; + } + return ""; +}; + +export function useScopesPermittedBy(): (_hasScopes: string[], _wantScopes: string[]) => string { + return useCallback((hasScopes, wantsScopes) => { + return wantsScopes. + map((wanted) => scopePermittedByScopes(hasScopes, wanted)). + flatMap((msg) => msg || []). + join(", "); + }, []); } + +const scopePermittedByScopes = (hasScopes: string[], wanted: string) => { + if (hasScopes.some((hasScope) => scopePermittedByScope(hasScope, wanted) === "")) { + return ""; + } + return `scopes [${hasScopes}] do not permit ${wanted}`; +}; + +const scopePermittedByScope = (has: string, wanted: string) => { + if (has === wanted) { + // Exact match on either a + // top-level or granular scope. + return ""; + } + + // Ensure we have a + // known top-level scope. + switch (true) { + case (ValidTopLevelScopes.includes(has)): + // Check if top-level includes wanted, + // eg., have "admin", want "admin:read". + if (wanted.startsWith(has + ":")) { + return ""; + } else { + return `scope ${has} does not permit ${wanted}`; + } + + default: + // Unknown top-level scope, + // can't permit anything. + return `unrecognized scope ${has}`; + } +}; diff --git a/web/source/settings/lib/util/index.ts b/web/source/settings/lib/util/index.ts index 4c8a90626..8bcf5ab5d 100644 --- a/web/source/settings/lib/util/index.ts +++ b/web/source/settings/lib/util/index.ts @@ -30,7 +30,7 @@ export function UseOurInstanceAccount(account: AdminAccount): boolean { // Pull our own URL out of storage so we can // tell if account is our instance account. const ourDomain = useMemo(() => { - const instanceUrlStr = store.getState().oauth.instanceUrl; + const instanceUrlStr = store.getState().login.instanceUrl; if (!instanceUrlStr) { return ""; } |
