fix 403 on sso provider signup and other tweaks to UI. Setting to disable SSO
This commit is contained in:
@@ -21,7 +21,6 @@ export function setErrorMessage(data, message) {
|
|||||||
|
|
||||||
export default function ({ app, router }) {
|
export default function ({ app, router }) {
|
||||||
app.config.globalProperties.$axios = axios;
|
app.config.globalProperties.$axios = axios;
|
||||||
|
|
||||||
axios.defaults.withCredentials = true;
|
axios.defaults.withCredentials = true;
|
||||||
|
|
||||||
axios.interceptors.request.use(
|
axios.interceptors.request.use(
|
||||||
@@ -67,7 +66,11 @@ export default function ({ app, router }) {
|
|||||||
// perms
|
// perms
|
||||||
else if (error.response.status === 403) {
|
else if (error.response.status === 403) {
|
||||||
// don't notify user if method is GET
|
// don't notify user if method is GET
|
||||||
if (error.config.method === "get" || error.config.method === "patch")
|
if (
|
||||||
|
error.config.method === "get" ||
|
||||||
|
error.config.method === "patch" ||
|
||||||
|
error.config.url === "accounts/ssoproviders/token/"
|
||||||
|
)
|
||||||
return Promise.reject({ ...error });
|
return Promise.reject({ ...error });
|
||||||
text = error.response.data.detail;
|
text = error.response.data.detail;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,8 +37,8 @@
|
|||||||
<template #body="props">
|
<template #body="props">
|
||||||
<q-tr>
|
<q-tr>
|
||||||
<!-- rows -->
|
<!-- rows -->
|
||||||
<td>{{ props.row.created }}</td>
|
<td>{{ formatDate(props.row.created) }}</td>
|
||||||
<td>{{ props.row.expiry }}</td>
|
<td>{{ formatDate(props.row.expiry) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<q-btn
|
<q-btn
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
import { onMounted, ref } from "vue";
|
import { onMounted, ref } from "vue";
|
||||||
import { useDialogPluginComponent, useQuasar, type QTableColumn } from "quasar";
|
import { useDialogPluginComponent, useQuasar, type QTableColumn } from "quasar";
|
||||||
import { notifySuccess } from "@/utils/notify";
|
import { notifySuccess } from "@/utils/notify";
|
||||||
|
import { formatDate } from "@/utils/format";
|
||||||
import {
|
import {
|
||||||
fetchUserSessions,
|
fetchUserSessions,
|
||||||
deleteAllUserSessions,
|
deleteAllUserSessions,
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import axios from "axios";
|
|||||||
import { getCookie } from "@/ee/sso/utils/cookies";
|
import { getCookie } from "@/ee/sso/utils/cookies";
|
||||||
import { getBaseUrl } from "@/boot/axios";
|
import { getBaseUrl } from "@/boot/axios";
|
||||||
|
|
||||||
import type { SSOProvider } from "@/ee/sso/types/sso";
|
import type { SSOProvider, SSOSettings } from "@/ee/sso/types/sso";
|
||||||
|
|
||||||
const baseUrl = "accounts";
|
const baseUrl = "accounts";
|
||||||
|
|
||||||
@@ -56,10 +56,6 @@ export async function removeSSOProvider(id: number) {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SSOSettings {
|
|
||||||
block_local_user_logon: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchSSOSettings(): Promise<SSOSettings> {
|
export async function fetchSSOSettings(): Promise<SSOSettings> {
|
||||||
const { data } = await axios.get(`${baseUrl}/ssoproviders/settings/`);
|
const { data } = await axios.get(`${baseUrl}/ssoproviders/settings/`);
|
||||||
return data;
|
return data;
|
||||||
|
|||||||
@@ -36,8 +36,8 @@ For details, see: https://license.tacticalrmm.com/ee
|
|||||||
<!-- rows -->
|
<!-- rows -->
|
||||||
<td>{{ props.row.display }}</td>
|
<td>{{ props.row.display }}</td>
|
||||||
<td>{{ props.row.provider }}</td>
|
<td>{{ props.row.provider }}</td>
|
||||||
<td>{{ props.row.last_login }}</td>
|
<td>{{ formatDate(props.row.last_login) }}</td>
|
||||||
<td>{{ props.row.date_joined }}</td>
|
<td>{{ formatDate(props.row.date_joined) }}</td>
|
||||||
<td>
|
<td>
|
||||||
<q-btn
|
<q-btn
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -60,6 +60,7 @@ import { useDialogPluginComponent, useQuasar, type QTableColumn } from "quasar";
|
|||||||
import { disconnectSSOAccount } from "@/ee/sso/api/sso";
|
import { disconnectSSOAccount } from "@/ee/sso/api/sso";
|
||||||
import { notifySuccess } from "@/utils/notify";
|
import { notifySuccess } from "@/utils/notify";
|
||||||
import { useAuthStore } from "@/stores/auth";
|
import { useAuthStore } from "@/stores/auth";
|
||||||
|
import { formatDate } from "@/utils/format";
|
||||||
|
|
||||||
//types
|
//types
|
||||||
import type { SSOAccount, SSOUser } from "../types/sso";
|
import type { SSOAccount, SSOUser } from "../types/sso";
|
||||||
|
|||||||
@@ -33,18 +33,9 @@ For details, see: https://license.tacticalrmm.com/ee
|
|||||||
:loading="loading"
|
:loading="loading"
|
||||||
>
|
>
|
||||||
<template v-slot:top>
|
<template v-slot:top>
|
||||||
<q-space />
|
|
||||||
<q-btn
|
<q-btn
|
||||||
@click="
|
@click="openSSOSettings"
|
||||||
changeSSOSettings({
|
label="SSO Settings"
|
||||||
block_local_user_logon: !ssoSettings.block_local_user_logon,
|
|
||||||
})
|
|
||||||
"
|
|
||||||
:label="
|
|
||||||
ssoSettings.block_local_user_logon
|
|
||||||
? 'Allow Local Logon'
|
|
||||||
: 'Block Local Logon'
|
|
||||||
"
|
|
||||||
no-caps
|
no-caps
|
||||||
color="primary"
|
color="primary"
|
||||||
size="sm"
|
size="sm"
|
||||||
@@ -90,15 +81,18 @@ For details, see: https://license.tacticalrmm.com/ee
|
|||||||
</q-menu>
|
</q-menu>
|
||||||
<!-- name -->
|
<!-- name -->
|
||||||
<q-td>
|
<q-td>
|
||||||
{{ props.row.name }}
|
{{ truncateText(props.row.name, 35) }}
|
||||||
|
<q-tooltip>{{ props.row.name }}</q-tooltip>
|
||||||
</q-td>
|
</q-td>
|
||||||
<!-- server_url -->
|
<!-- server_url -->
|
||||||
<q-td>
|
<q-td>
|
||||||
{{ props.row.server_url }}
|
{{ truncateText(props.row.server_url, 35) }}
|
||||||
|
<q-tooltip>{{ props.row.server_url }}</q-tooltip>
|
||||||
</q-td>
|
</q-td>
|
||||||
<!-- pattern -->
|
<!-- pattern -->
|
||||||
<q-td>
|
<q-td>
|
||||||
{{ props.row.client_id }}
|
{{ truncateText(props.row.client_id, 35) }}
|
||||||
|
<q-tooltip>{{ props.row.client_id }}</q-tooltip>
|
||||||
</q-td>
|
</q-td>
|
||||||
</q-tr>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
@@ -110,20 +104,16 @@ For details, see: https://license.tacticalrmm.com/ee
|
|||||||
// composition imports
|
// composition imports
|
||||||
import { ref, onMounted } from "vue";
|
import { ref, onMounted } from "vue";
|
||||||
import { QTableColumn, useQuasar } from "quasar";
|
import { QTableColumn, useQuasar } from "quasar";
|
||||||
import {
|
import { fetchSSOProviders, removeSSOProvider } from "@/ee/sso/api/sso";
|
||||||
fetchSSOProviders,
|
|
||||||
removeSSOProvider,
|
|
||||||
fetchSSOSettings,
|
|
||||||
updateSSOSettings,
|
|
||||||
type SSOSettings,
|
|
||||||
} from "@/ee/sso/api/sso";
|
|
||||||
import { notifySuccess } from "@/utils/notify";
|
import { notifySuccess } from "@/utils/notify";
|
||||||
|
import { truncateText } from "@/utils/format";
|
||||||
|
|
||||||
// ui imports
|
// ui imports
|
||||||
import SSOProvidersForm from "@/ee/sso/components/SSOProvidersForm.vue";
|
import SSOProvidersForm from "@/ee/sso/components/SSOProvidersForm.vue";
|
||||||
|
|
||||||
// types
|
// types
|
||||||
import { type SSOProvider } from "@/ee/sso/types/sso";
|
import { type SSOProvider } from "@/ee/sso/types/sso";
|
||||||
|
import SSOSettings from "@/ee/sso/components/SSOSettings.vue";
|
||||||
|
|
||||||
// setup quasar
|
// setup quasar
|
||||||
const $q = useQuasar();
|
const $q = useQuasar();
|
||||||
@@ -131,7 +121,7 @@ const $q = useQuasar();
|
|||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
|
|
||||||
const providers = ref([] as SSOProvider[]);
|
const providers = ref([] as SSOProvider[]);
|
||||||
const ssoSettings = ref({} as SSOSettings);
|
|
||||||
const columns: QTableColumn[] = [
|
const columns: QTableColumn[] = [
|
||||||
{
|
{
|
||||||
name: "name",
|
name: "name",
|
||||||
@@ -166,28 +156,6 @@ async function getSSOProviders() {
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getSSOSettings() {
|
|
||||||
loading.value = true;
|
|
||||||
try {
|
|
||||||
ssoSettings.value = await fetchSSOSettings();
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function changeSSOSettings(data: SSOSettings) {
|
|
||||||
loading.value = true;
|
|
||||||
try {
|
|
||||||
ssoSettings.value = await updateSSOSettings(data);
|
|
||||||
await getSSOSettings();
|
|
||||||
notifySuccess("Settings updated successfully");
|
|
||||||
} catch (e) {
|
|
||||||
console.error(e);
|
|
||||||
}
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function addSSOProvider() {
|
function addSSOProvider() {
|
||||||
$q.dialog({
|
$q.dialog({
|
||||||
component: SSOProvidersForm,
|
component: SSOProvidersForm,
|
||||||
@@ -221,8 +189,13 @@ function deleteSSOProvider(provider: SSOProvider) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openSSOSettings() {
|
||||||
|
$q.dialog({
|
||||||
|
component: SSOSettings,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
await getSSOProviders();
|
await getSSOProviders();
|
||||||
await getSSOSettings();
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
104
src/ee/sso/components/SSOSettings.vue
Normal file
104
src/ee/sso/components/SSOSettings.vue
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<!--
|
||||||
|
Copyright (c) 2023-present Amidaware Inc.
|
||||||
|
This file is subject to the EE License Agreement.
|
||||||
|
For details, see: https://license.tacticalrmm.com/ee
|
||||||
|
-->
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<q-dialog ref="dialogRef" @hide="onDialogHide">
|
||||||
|
<q-card class="q-dialog-plugin" style="width: 50">
|
||||||
|
<q-bar>
|
||||||
|
SSO Settings
|
||||||
|
<q-space />
|
||||||
|
<q-btn dense flat icon="close" v-close-popup>
|
||||||
|
<q-tooltip class="bg-white text-primary">Close</q-tooltip>
|
||||||
|
</q-btn>
|
||||||
|
</q-bar>
|
||||||
|
|
||||||
|
<!-- disable sso-->
|
||||||
|
<q-card-section>
|
||||||
|
<q-checkbox
|
||||||
|
dense
|
||||||
|
label="Enable SSO"
|
||||||
|
v-model="ssoSettings.sso_enabled"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<!-- block local user logon -->
|
||||||
|
<q-card-section>
|
||||||
|
<q-checkbox
|
||||||
|
dense
|
||||||
|
label="Block Local Logon"
|
||||||
|
v-model="ssoSettings.block_local_user_logon"
|
||||||
|
:disable="!ssoSettings.sso_enabled"
|
||||||
|
/>
|
||||||
|
</q-card-section>
|
||||||
|
|
||||||
|
<q-card-actions align="right">
|
||||||
|
<q-btn flat label="Cancel" v-close-popup />
|
||||||
|
<q-btn
|
||||||
|
flat
|
||||||
|
label="Submit"
|
||||||
|
color="primary"
|
||||||
|
:loading="loading"
|
||||||
|
@click="submit"
|
||||||
|
/>
|
||||||
|
</q-card-actions>
|
||||||
|
</q-card>
|
||||||
|
</q-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
// composition imports
|
||||||
|
import { ref, watch, onMounted } from "vue";
|
||||||
|
import { useDialogPluginComponent } from "quasar";
|
||||||
|
import { notifySuccess } from "@/utils/notify";
|
||||||
|
import { fetchSSOSettings, updateSSOSettings } from "@/ee/sso/api/sso";
|
||||||
|
|
||||||
|
// types
|
||||||
|
import { SSOSettings } from "../types/sso";
|
||||||
|
|
||||||
|
// define emits
|
||||||
|
defineEmits([...useDialogPluginComponent.emits]);
|
||||||
|
|
||||||
|
const { dialogRef, onDialogHide, onDialogOK } = useDialogPluginComponent();
|
||||||
|
|
||||||
|
const ssoSettings = ref({} as SSOSettings);
|
||||||
|
const loading = ref(false);
|
||||||
|
|
||||||
|
// watcher to disable block local login if sso is disabled
|
||||||
|
watch(
|
||||||
|
() => ssoSettings.value.sso_enabled,
|
||||||
|
(newValue) => {
|
||||||
|
if (newValue) {
|
||||||
|
ssoSettings.value.block_local_user_logon = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
async function getSSOSettings() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
ssoSettings.value = await fetchSSOSettings();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function submit() {
|
||||||
|
loading.value = true;
|
||||||
|
try {
|
||||||
|
ssoSettings.value = await updateSSOSettings(ssoSettings.value);
|
||||||
|
await getSSOSettings();
|
||||||
|
notifySuccess("Settings updated successfully");
|
||||||
|
onDialogOK();
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
loading.value = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
await getSSOSettings();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -26,3 +26,8 @@ export interface SSOAccount {
|
|||||||
export interface SSOUser extends User {
|
export interface SSOUser extends User {
|
||||||
social_accounts: SSOAccount[];
|
social_accounts: SSOAccount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface SSOSettings {
|
||||||
|
sso_enabled: boolean;
|
||||||
|
block_local_user_logon: boolean;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user