mirror of
https://github.com/unraid/api.git
synced 2025-12-31 13:39:52 -06:00
feat: move ssoenabled to a boolean flag rather than ids
This commit is contained in:
@@ -18,5 +18,5 @@ echo $wcExtractor->getScriptTagHtml();
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<unraid-i18n-host>
|
<unraid-i18n-host>
|
||||||
<unraid-sso-button subids="<?= $serverState->ssoSubIds ?>"></unraid-sso-button>
|
<unraid-sso-button ssoenabled="<?= $serverState->ssoEnabled ?>"></unraid-sso-button>
|
||||||
</unraid-i18n-host>
|
</unraid-i18n-host>
|
||||||
@@ -8,6 +8,7 @@
|
|||||||
* The above copyright notice and this permission notice shall be included in
|
* The above copyright notice and this permission notice shall be included in
|
||||||
* all copies or substantial portions of the Software.
|
* all copies or substantial portions of the Software.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @todo refactor globals – currently if you try to use $GLOBALS the class will break.
|
* @todo refactor globals – currently if you try to use $GLOBALS the class will break.
|
||||||
*/
|
*/
|
||||||
@@ -56,7 +57,7 @@ class ServerState
|
|||||||
/**
|
/**
|
||||||
* SSO Sub IDs from the my servers config file.
|
* SSO Sub IDs from the my servers config file.
|
||||||
*/
|
*/
|
||||||
public $ssoSubIds = '';
|
public $ssoEnabled = false;
|
||||||
private $osVersion;
|
private $osVersion;
|
||||||
private $osVersionBranch;
|
private $osVersionBranch;
|
||||||
private $rebootDetails;
|
private $rebootDetails;
|
||||||
@@ -71,7 +72,7 @@ class ServerState
|
|||||||
public $myServersMemoryCfg = [];
|
public $myServersMemoryCfg = [];
|
||||||
public $host = 'unknown';
|
public $host = 'unknown';
|
||||||
public $combinedKnownOrigins = [];
|
public $combinedKnownOrigins = [];
|
||||||
|
|
||||||
public $nginxCfg = [];
|
public $nginxCfg = [];
|
||||||
public $flashbackupStatus = [];
|
public $flashbackupStatus = [];
|
||||||
public $registered = false;
|
public $registered = false;
|
||||||
@@ -90,7 +91,7 @@ class ServerState
|
|||||||
* @see - getWebguiGlobal() for usage
|
* @see - getWebguiGlobal() for usage
|
||||||
* */
|
* */
|
||||||
global $webguiGlobals;
|
global $webguiGlobals;
|
||||||
$this->webguiGlobals =& $webguiGlobals;
|
$this->webguiGlobals = &$webguiGlobals;
|
||||||
// echo "<pre>" . json_encode($this->webguiGlobals, JSON_PRETTY_PRINT) . "</pre>";
|
// echo "<pre>" . json_encode($this->webguiGlobals, JSON_PRETTY_PRINT) . "</pre>";
|
||||||
|
|
||||||
$this->var = (array)parse_ini_file('state/var.ini');
|
$this->var = (array)parse_ini_file('state/var.ini');
|
||||||
@@ -123,7 +124,8 @@ class ServerState
|
|||||||
/**
|
/**
|
||||||
* Retrieve the value of a webgui global setting.
|
* Retrieve the value of a webgui global setting.
|
||||||
*/
|
*/
|
||||||
public function getWebguiGlobal(string $key, string $subkey = null) {
|
public function getWebguiGlobal(string $key, string $subkey = null)
|
||||||
|
{
|
||||||
if (!$subkey) {
|
if (!$subkey) {
|
||||||
return _var($this->webguiGlobals, $key, '');
|
return _var($this->webguiGlobals, $key, '');
|
||||||
}
|
}
|
||||||
@@ -131,7 +133,8 @@ class ServerState
|
|||||||
return _var($keyArray, $subkey, '');
|
return _var($keyArray, $subkey, '');
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setConnectValues() {
|
private function setConnectValues()
|
||||||
|
{
|
||||||
if (file_exists('/var/lib/pkgtools/packages/dynamix.unraid.net')) {
|
if (file_exists('/var/lib/pkgtools/packages/dynamix.unraid.net')) {
|
||||||
$this->connectPluginInstalled = 'dynamix.unraid.net.plg';
|
$this->connectPluginInstalled = 'dynamix.unraid.net.plg';
|
||||||
}
|
}
|
||||||
@@ -158,13 +161,15 @@ class ServerState
|
|||||||
$this->getFlashBackupStatus();
|
$this->getFlashBackupStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getFlashBackupStatus() {
|
private function getFlashBackupStatus()
|
||||||
|
{
|
||||||
$flashbackupCfg = '/var/local/emhttp/flashbackup.ini';
|
$flashbackupCfg = '/var/local/emhttp/flashbackup.ini';
|
||||||
$this->flashbackupStatus = (file_exists($flashbackupCfg)) ? @parse_ini_file($flashbackupCfg) : [];
|
$this->flashbackupStatus = (file_exists($flashbackupCfg)) ? @parse_ini_file($flashbackupCfg) : [];
|
||||||
$this->flashBackupActivated = empty($this->flashbackupStatus['activated']) ? '' : 'true';
|
$this->flashBackupActivated = empty($this->flashbackupStatus['activated']) ? '' : 'true';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getMyServersCfgValues() {
|
private function getMyServersCfgValues()
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* @todo can we read this from somewhere other than the flash? Connect page uses this path and /boot/config/plugins/dynamix.my.servers/myservers.cfg…
|
* @todo can we read this from somewhere other than the flash? Connect page uses this path and /boot/config/plugins/dynamix.my.servers/myservers.cfg…
|
||||||
* - $myservers_memory_cfg_path ='/var/local/emhttp/myservers.cfg';
|
* - $myservers_memory_cfg_path ='/var/local/emhttp/myservers.cfg';
|
||||||
@@ -197,10 +202,11 @@ class ServerState
|
|||||||
$this->registered = !empty($this->myServersFlashCfg['remote']['apikey']) && $this->connectPluginInstalled;
|
$this->registered = !empty($this->myServersFlashCfg['remote']['apikey']) && $this->connectPluginInstalled;
|
||||||
$this->registeredTime = $this->myServersFlashCfg['remote']['regWizTime'] ?? '';
|
$this->registeredTime = $this->myServersFlashCfg['remote']['regWizTime'] ?? '';
|
||||||
$this->username = $this->myServersFlashCfg['remote']['username'] ?? '';
|
$this->username = $this->myServersFlashCfg['remote']['username'] ?? '';
|
||||||
$this->ssoSubIds = $this->myServersFlashCfg['remote']['ssoSubIds'] ?? '';
|
$this->ssoEnabled = $this->myServersFlashCfg['remote']['ssoSubIds'] !== '';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getConnectKnownOrigins() {
|
private function getConnectKnownOrigins()
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Allowed origins warning displayed when the current webGUI URL is NOT included in the known lists of allowed origins.
|
* Allowed origins warning displayed when the current webGUI URL is NOT included in the known lists of allowed origins.
|
||||||
* Include localhost in the test, but only display HTTP(S) URLs that do not include localhost.
|
* Include localhost in the test, but only display HTTP(S) URLs that do not include localhost.
|
||||||
@@ -208,7 +214,7 @@ class ServerState
|
|||||||
$this->host = $_SERVER['HTTP_HOST'] ?? "unknown";
|
$this->host = $_SERVER['HTTP_HOST'] ?? "unknown";
|
||||||
$memoryCfgPath = '/var/local/emhttp/myservers.cfg';
|
$memoryCfgPath = '/var/local/emhttp/myservers.cfg';
|
||||||
$this->myServersMemoryCfg = (file_exists($memoryCfgPath)) ? @parse_ini_file($memoryCfgPath) : [];
|
$this->myServersMemoryCfg = (file_exists($memoryCfgPath)) ? @parse_ini_file($memoryCfgPath) : [];
|
||||||
$this->myServersMiniGraphConnected = (($this->myServersMemoryCfg['minigraph']??'') === 'CONNECTED');
|
$this->myServersMiniGraphConnected = (($this->myServersMemoryCfg['minigraph'] ?? '') === 'CONNECTED');
|
||||||
|
|
||||||
$allowedOrigins = $this->myServersMemoryCfg['allowedOrigins'] ?? "";
|
$allowedOrigins = $this->myServersMemoryCfg['allowedOrigins'] ?? "";
|
||||||
$extraOrigins = $this->myServersFlashCfg['api']['extraOrigins'] ?? "";
|
$extraOrigins = $this->myServersFlashCfg['api']['extraOrigins'] ?? "";
|
||||||
@@ -224,8 +230,8 @@ class ServerState
|
|||||||
$this->combinedKnownOrigins = explode(",", $combinedOrigins);
|
$this->combinedKnownOrigins = explode(",", $combinedOrigins);
|
||||||
|
|
||||||
if ($this->combinedKnownOrigins) {
|
if ($this->combinedKnownOrigins) {
|
||||||
foreach($this->combinedKnownOrigins as $key => $origin) {
|
foreach ($this->combinedKnownOrigins as $key => $origin) {
|
||||||
if ( (strpos($origin, "http") === false) || (strpos($origin, "localhost") !== false) ) {
|
if ((strpos($origin, "http") === false) || (strpos($origin, "localhost") !== false)) {
|
||||||
// clean up $this->combinedKnownOrigins, only display warning if origins still remain to display
|
// clean up $this->combinedKnownOrigins, only display warning if origins still remain to display
|
||||||
unset($this->combinedKnownOrigins[$key]);
|
unset($this->combinedKnownOrigins[$key]);
|
||||||
}
|
}
|
||||||
@@ -238,7 +244,8 @@ class ServerState
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function detectActivationCode() {
|
private function detectActivationCode()
|
||||||
|
{
|
||||||
// Fresh server and we're not loading with a callback param to install
|
// Fresh server and we're not loading with a callback param to install
|
||||||
if ($this->state !== 'ENOKEYFILE' || !empty($_GET['c'])) {
|
if ($this->state !== 'ENOKEYFILE' || !empty($_GET['c'])) {
|
||||||
return;
|
return;
|
||||||
@@ -312,6 +319,7 @@ class ServerState
|
|||||||
"registered" => $this->registered,
|
"registered" => $this->registered,
|
||||||
"registeredTime" => $this->registeredTime,
|
"registeredTime" => $this->registeredTime,
|
||||||
"site" => _var($_SERVER, 'REQUEST_SCHEME') . "://" . _var($_SERVER, 'HTTP_HOST'),
|
"site" => _var($_SERVER, 'REQUEST_SCHEME') . "://" . _var($_SERVER, 'HTTP_HOST'),
|
||||||
|
"ssoEnabled" => $this->ssoEnabled,
|
||||||
"state" => $this->state,
|
"state" => $this->state,
|
||||||
"theme" => [
|
"theme" => [
|
||||||
"banner" => !empty($this->getWebguiGlobal('display', 'banner')),
|
"banner" => !empty($this->getWebguiGlobal('display', 'banner')),
|
||||||
@@ -326,7 +334,6 @@ class ServerState
|
|||||||
"uptime" => 1000 * (time() - round(strtok(exec("cat /proc/uptime"), ' '))),
|
"uptime" => 1000 * (time() - round(strtok(exec("cat /proc/uptime"), ' '))),
|
||||||
"username" => $this->username,
|
"username" => $this->username,
|
||||||
"wanFQDN" => @$this->nginxCfg['NGINX_WANFQDN'] ?? '',
|
"wanFQDN" => @$this->nginxCfg['NGINX_WANFQDN'] ?? '',
|
||||||
"ssoSubIds" => $this->ssoSubIds
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if ($this->combinedKnownOrigins) {
|
if ($this->combinedKnownOrigins) {
|
||||||
@@ -357,7 +364,8 @@ class ServerState
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getServerStateJson() {
|
public function getServerStateJson()
|
||||||
|
{
|
||||||
return json_encode($this->getServerState());
|
return json_encode($this->getServerState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -366,7 +374,8 @@ class ServerState
|
|||||||
*
|
*
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function getServerStateJsonForHtmlAttr() {
|
public function getServerStateJsonForHtmlAttr()
|
||||||
|
{
|
||||||
$json = json_encode($this->getServerState());
|
$json = json_encode($this->getServerState());
|
||||||
return htmlspecialchars($json, ENT_QUOTES, 'UTF-8');
|
return htmlspecialchars($json, ENT_QUOTES, 'UTF-8');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ export const serverState: Server = {
|
|||||||
regExp,
|
regExp,
|
||||||
regGuid,
|
regGuid,
|
||||||
site: 'http://localhost:4321',
|
site: 'http://localhost:4321',
|
||||||
ssoSubIds: '1234567890,0987654321,297294e2-b31c-4bcc-a441-88aee0ad609f',
|
ssoEnabled: true,
|
||||||
state,
|
state,
|
||||||
theme: {
|
theme: {
|
||||||
banner: false,
|
banner: false,
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import Button from '~/components/Brand/Button.vue';
|
|||||||
import { ACCOUNT } from '~/helpers/urls';
|
import { ACCOUNT } from '~/helpers/urls';
|
||||||
|
|
||||||
export interface Props {
|
export interface Props {
|
||||||
subids?: string;
|
ssoenabled?: boolean;
|
||||||
}
|
}
|
||||||
const props = defineProps<Props>();
|
const props = defineProps<Props>();
|
||||||
|
|
||||||
@@ -34,25 +34,39 @@ const generateStateToken = (): string => {
|
|||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
const search = new URLSearchParams(window.location.search);
|
try {
|
||||||
const token = search.get('token') ?? '';
|
const search = new URLSearchParams(window.location.search);
|
||||||
const state = search.get('state') ?? '';
|
const code = search.get('code') ?? '';
|
||||||
const sessionState = getStateToken();
|
const state = search.get('state') ?? '';
|
||||||
if (token && state === sessionState) {
|
const sessionState = getStateToken();
|
||||||
enterCallbackTokenIntoField(token);
|
|
||||||
// Clear the token from the URL
|
if (code && state === sessionState) {
|
||||||
window.history.replaceState({}, document.title, window.location.pathname);
|
const token = await fetch(new URL('token', ACCOUNT), {
|
||||||
window.location.search = '';
|
method: 'POST',
|
||||||
|
body: new URLSearchParams({
|
||||||
|
code,
|
||||||
|
clientId: 'CONNECT_SERVER_SSO',
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
if (token.ok) {
|
||||||
|
const tokenBody = await token.json();
|
||||||
|
enterCallbackTokenIntoField(tokenBody.access_token);
|
||||||
|
if (window.location.search) {
|
||||||
|
window.history.replaceState({}, document.title, window.location.pathname);
|
||||||
|
window.location.search = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error fetching token', err);
|
||||||
|
} finally {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const externalSSOUrl = computed<string>(() => {
|
const externalSSOUrl = computed<string>(() => {
|
||||||
if (props.subids === undefined) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
const url = new URL('sso', ACCOUNT);
|
const url = new URL('sso', ACCOUNT);
|
||||||
url.searchParams.append('uids', props.subids);
|
|
||||||
const callbackUrlLogin = new URL('login', window.location.origin);
|
const callbackUrlLogin = new URL('login', window.location.origin);
|
||||||
const state = generateStateToken();
|
const state = generateStateToken();
|
||||||
callbackUrlLogin.searchParams.append('state', state);
|
callbackUrlLogin.searchParams.append('state', state);
|
||||||
@@ -63,7 +77,7 @@ const externalSSOUrl = computed<string>(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<template v-if="props.subids">
|
<template v-if="props.ssoenabled === true">
|
||||||
<Button target="_blank" :href="externalSSOUrl">Sign In With Unraid.net Account</Button>
|
<Button target="_blank" :href="externalSSOUrl">Sign In With Unraid.net Account</Button>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -156,7 +156,7 @@ onMounted(() => {
|
|||||||
<div class="bg-background">
|
<div class="bg-background">
|
||||||
<hr class="border-black dark:border-white" />
|
<hr class="border-black dark:border-white" />
|
||||||
<h2 class="text-xl font-semibold font-mono">SSO Button Component</h2>
|
<h2 class="text-xl font-semibold font-mono">SSO Button Component</h2>
|
||||||
<SsoButtonCe :subids="serverState.ssoSubIds" />
|
<SsoButtonCe :ssoEnabled="serverState.ssoEnabled" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</client-only>
|
</client-only>
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ onBeforeMount(() => {
|
|||||||
<h3 class="text-lg font-semibold font-mono">
|
<h3 class="text-lg font-semibold font-mono">
|
||||||
SSOSignInButtonCe
|
SSOSignInButtonCe
|
||||||
</h3>
|
</h3>
|
||||||
<unraid-sso-button :subids="serverState.ssoSubIds" />
|
<unraid-sso-button :ssoEnabled="serverState.ssoEnabled" />
|
||||||
</unraid-i18n-host>
|
</unraid-i18n-host>
|
||||||
</client-only>
|
</client-only>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ export const useServerStore = defineStore("server", () => {
|
|||||||
return today.isAfter(parsedUpdateExpirationDate, "day");
|
return today.isAfter(parsedUpdateExpirationDate, "day");
|
||||||
});
|
});
|
||||||
const site = ref<string>("");
|
const site = ref<string>("");
|
||||||
const ssoSubIds = ref<string>("");
|
const ssoEnabled = ref<boolean>(false);
|
||||||
const state = ref<ServerState>();
|
const state = ref<ServerState>();
|
||||||
const theme = ref<Theme>();
|
const theme = ref<Theme>();
|
||||||
watch(theme, (newVal) => {
|
watch(theme, (newVal) => {
|
||||||
@@ -1209,8 +1209,8 @@ export const useServerStore = defineStore("server", () => {
|
|||||||
if (typeof data?.regTo !== "undefined") {
|
if (typeof data?.regTo !== "undefined") {
|
||||||
regTo.value = data.regTo;
|
regTo.value = data.regTo;
|
||||||
}
|
}
|
||||||
if (typeof data?.ssoSubIds !== "undefined") {
|
if (typeof data?.ssoEnabled !== "undefined") {
|
||||||
ssoSubIds.value = data.ssoSubIds;
|
ssoEnabled.value = Boolean(data.ssoEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data.activationCodeData !== "undefined") {
|
if (typeof data.activationCodeData !== "undefined") {
|
||||||
@@ -1478,7 +1478,7 @@ export const useServerStore = defineStore("server", () => {
|
|||||||
parsedRegExp,
|
parsedRegExp,
|
||||||
regUpdatesExpired,
|
regUpdatesExpired,
|
||||||
site,
|
site,
|
||||||
ssoSubIds,
|
ssoEnabled,
|
||||||
state,
|
state,
|
||||||
theme,
|
theme,
|
||||||
updateOsIgnoredReleases,
|
updateOsIgnoredReleases,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import type { Config, PartialCloudFragment } from '~/composables/gql/graphql';
|
import type { Config, PartialCloudFragment } from '~/composables/gql/graphql';
|
||||||
|
import type { ActivationCodeData } from '~/store/activationCode';
|
||||||
import type { Theme } from '~/store/theme';
|
import type { Theme } from '~/store/theme';
|
||||||
import type { UserProfileLink } from '~/types/userProfile';
|
import type { UserProfileLink } from '~/types/userProfile';
|
||||||
import type { ActivationCodeData } from '~/store/activationCode';
|
|
||||||
|
|
||||||
export type ServerState = 'BASIC'
|
export type ServerState = 'BASIC'
|
||||||
| 'PLUS'
|
| 'PLUS'
|
||||||
@@ -108,6 +109,7 @@ export interface Server {
|
|||||||
regExp?: number;
|
regExp?: number;
|
||||||
regUpdatesExpired?: boolean;
|
regUpdatesExpired?: boolean;
|
||||||
site?: string;
|
site?: string;
|
||||||
|
ssoEnabled?: boolean;
|
||||||
state?: ServerState;
|
state?: ServerState;
|
||||||
theme?: Theme | undefined;
|
theme?: Theme | undefined;
|
||||||
updateOsIgnoredReleases?: string[];
|
updateOsIgnoredReleases?: string[];
|
||||||
@@ -117,7 +119,6 @@ export interface Server {
|
|||||||
username?: string;
|
username?: string;
|
||||||
wanFQDN?: string;
|
wanFQDN?: string;
|
||||||
wanIp?: string;
|
wanIp?: string;
|
||||||
ssoSubIds?: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ServerAccountCallbackSendPayload {
|
export interface ServerAccountCallbackSendPayload {
|
||||||
@@ -196,4 +197,4 @@ export interface ServerStateData {
|
|||||||
message: string;
|
message: string;
|
||||||
error?: ServerStateDataError | boolean;
|
error?: ServerStateDataError | boolean;
|
||||||
withKey?: boolean; // @todo potentially remove
|
withKey?: boolean; // @todo potentially remove
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user