mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[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
This commit is contained in:
@ -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}`;
|
||||
}
|
||||
};
|
||||
|
@ -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 "";
|
||||
}
|
||||
|
Reference in New Issue
Block a user