-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #17166 from jmchilton/permissions_overhaul
Much simpler default dataset permissions for typical users.
- Loading branch information
Showing
8 changed files
with
308 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
<script lang="ts" setup> | ||
import { ref, watch } from "vue"; | ||
import FormGeneric from "@/components/Form/FormGeneric.vue"; | ||
import LoadingSpan from "@/components/LoadingSpan.vue"; | ||
interface DatasetPermissionsFormProps { | ||
loading: boolean; | ||
simplePermissions: boolean; | ||
title: string; | ||
checked: boolean; | ||
formConfig: object; | ||
} | ||
const props = defineProps<DatasetPermissionsFormProps>(); | ||
const selectedAdvancedForm = ref(false); | ||
const checkedInForm = ref(props.checked); | ||
const emit = defineEmits<{ | ||
(e: "change", value: boolean): void; | ||
}>(); | ||
async function change(value: boolean) { | ||
emit("change", value); | ||
} | ||
watch(props, () => { | ||
checkedInForm.value = props.checked; | ||
}); | ||
</script> | ||
|
||
<template> | ||
<div> | ||
<LoadingSpan v-if="loading" message="Loading permission information" /> | ||
<div v-else-if="simplePermissions && !selectedAdvancedForm"> | ||
<div class="ui-portlet-section"> | ||
<div class="portlet-header"> | ||
<span class="portlet-title" | ||
><span class="portlet-title-icon fa mr-1 fa-users"></span> | ||
<b itemprop="name" class="portlet-title-text">{{ title }}</b> | ||
</span> | ||
</div> | ||
<div class="portlet-content"> | ||
<div class="mb-3 mt-3"> | ||
<b-form-checkbox v-model="checkedInForm" name="check-button" switch @change="change"> | ||
Make new datasets private | ||
</b-form-checkbox> | ||
</div> | ||
<a href="#" @click="selectedAdvancedForm = true">Show advanced options.</a> | ||
</div> | ||
</div> | ||
</div> | ||
<div v-else> | ||
<FormGeneric v-bind="formConfig" /> | ||
</div> | ||
</div> | ||
</template> |
71 changes: 71 additions & 0 deletions
71
client/src/components/History/HistoryDatasetPermissions.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
<script lang="ts" setup> | ||
import axios from "axios"; | ||
import { computed, ref } from "vue"; | ||
import { initRefs, updateRefs, useCallbacks } from "@/composables/datasetPermissions"; | ||
import { withPrefix } from "@/utils/redirect"; | ||
import DatasetPermissionsForm from "@/components/Dataset/DatasetPermissionsForm.vue"; | ||
interface HistoryDatasetPermissionsProps { | ||
historyId: string; | ||
} | ||
const props = defineProps<HistoryDatasetPermissionsProps>(); | ||
const loading = ref(true); | ||
const { | ||
managePermissionsOptions, | ||
accessPermissionsOptions, | ||
managePermissions, | ||
accessPermissions, | ||
simplePermissions, | ||
checked, | ||
} = initRefs(); | ||
const inputsUrl = computed(() => { | ||
return `/history/permissions?id=${props.historyId}`; | ||
}); | ||
const title = "Change default dataset permissions for history"; | ||
const formConfig = computed(() => { | ||
return { | ||
title: title, | ||
url: inputsUrl.value, | ||
submitTitle: "Save Permissions", | ||
redirect: "/histories/list", | ||
}; | ||
}); | ||
async function change(value: unknown) { | ||
const managePermissionValue: number = managePermissions.value[0] as number; | ||
let access: number[] = [] as number[]; | ||
if (value) { | ||
access = [managePermissionValue]; | ||
} | ||
const formValue = { | ||
DATASET_MANAGE_PERMISSIONS: [managePermissionValue], | ||
DATASET_ACCESS: access, | ||
}; | ||
axios.put(withPrefix(inputsUrl.value), formValue).then(onSuccess).catch(onError); | ||
} | ||
async function init() { | ||
const { data } = await axios.get(withPrefix(inputsUrl.value)); | ||
updateRefs(data.inputs, managePermissionsOptions, accessPermissionsOptions, managePermissions, accessPermissions); | ||
loading.value = false; | ||
} | ||
const { onSuccess, onError } = useCallbacks(init); | ||
</script> | ||
|
||
<template> | ||
<DatasetPermissionsForm | ||
:loading="loading" | ||
:simple-permissions="simplePermissions" | ||
:title="title" | ||
:form-config="formConfig" | ||
:checked="checked" | ||
@change="change" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
<script lang="ts" setup> | ||
import axios from "axios"; | ||
import { computed, ref } from "vue"; | ||
import { initRefs, updateRefs, useCallbacks } from "@/composables/datasetPermissions"; | ||
import { withPrefix } from "@/utils/redirect"; | ||
import DatasetPermissionsForm from "@/components/Dataset/DatasetPermissionsForm.vue"; | ||
interface UserDatasetPermissionsProps { | ||
userId: string; | ||
} | ||
const props = defineProps<UserDatasetPermissionsProps>(); | ||
const loading = ref(true); | ||
const { | ||
managePermissionsOptions, | ||
accessPermissionsOptions, | ||
managePermissions, | ||
accessPermissions, | ||
simplePermissions, | ||
checked, | ||
} = initRefs(); | ||
const inputsUrl = computed(() => { | ||
return `/api/users/${props.userId}/permissions/inputs`; | ||
}); | ||
async function init() { | ||
const { data } = await axios.get(withPrefix(inputsUrl.value)); | ||
updateRefs(data.inputs, managePermissionsOptions, accessPermissionsOptions, managePermissions, accessPermissions); | ||
loading.value = false; | ||
} | ||
const title = "Set Dataset Permissions for New Histories"; | ||
const formConfig = computed(() => { | ||
return { | ||
title: title, | ||
id: "edit-preferences-permissions", | ||
description: | ||
"Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.", | ||
url: inputsUrl.value, | ||
icon: "fa-users", | ||
submitTitle: "Save Permissions", | ||
redirect: "/user", | ||
}; | ||
}); | ||
async function change(value: unknown) { | ||
const managePermissionValue: number = managePermissions.value[0] as number; | ||
let access: number[] = [] as number[]; | ||
if (value) { | ||
access = [managePermissionValue]; | ||
} | ||
const formValue = { | ||
DATASET_MANAGE_PERMISSIONS: [managePermissionValue], | ||
DATASET_ACCESS: access, | ||
}; | ||
axios.put(withPrefix(inputsUrl.value), formValue).then(onSuccess).catch(onError); | ||
} | ||
const { onSuccess, onError } = useCallbacks(init); | ||
</script> | ||
|
||
<template> | ||
<DatasetPermissionsForm | ||
:loading="loading" | ||
:simple-permissions="simplePermissions" | ||
:title="title" | ||
:form-config="formConfig" | ||
:checked="checked" | ||
@change="change" /> | ||
</template> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import { AxiosResponse } from "axios"; | ||
import type { Ref } from "vue"; | ||
import { computed, ref } from "vue"; | ||
|
||
import { useToast } from "@/composables/toast"; | ||
import { errorMessageAsString } from "@/utils/simple-error"; | ||
|
||
interface InputOption { | ||
roleName: string; | ||
roleValue: number; | ||
} | ||
|
||
interface Input { | ||
value: number[]; | ||
options: [string, number][]; | ||
} | ||
|
||
export function initRefs() { | ||
const managePermissionsOptions = ref<InputOption[]>([]); | ||
const accessPermissionsOptions = ref<InputOption[]>([]); | ||
const managePermissions = ref<number[]>([]); | ||
const accessPermissions = ref<number[]>([]); | ||
|
||
const simplePermissions = computed(() => { | ||
// we have one manage permission and read access can be that or not that but nothing else | ||
const hasOneManagePermission = managePermissions.value.length == 1; | ||
const hasAtMostOneAccessPermissions = accessPermissions.value.length < 2; | ||
if (!hasOneManagePermission || !hasAtMostOneAccessPermissions) { | ||
return false; | ||
} | ||
const managePermissionValue = managePermissions.value[0]; | ||
return accessPermissions.value.length == 0 || accessPermissions.value[0] == managePermissionValue; | ||
}); | ||
|
||
const checked = computed(() => { | ||
return accessPermissions.value.length > 0; | ||
}); | ||
|
||
return { | ||
managePermissionsOptions, | ||
accessPermissionsOptions, | ||
managePermissions, | ||
accessPermissions, | ||
simplePermissions, | ||
checked, | ||
}; | ||
} | ||
|
||
export function updateRefs( | ||
inputs: Input[], | ||
managePermissionsOptions: Ref<InputOption[]>, | ||
accessPermissionsOptions: Ref<InputOption[]>, | ||
managePermissions: Ref<number[]>, | ||
accessPermissions: Ref<number[]> | ||
) { | ||
const manageInput: Input = inputs[0] as Input; | ||
const accessInput: Input = inputs[1] as Input; | ||
managePermissionsOptions.value = manageInput.options.map((v: [string, number]) => { | ||
return <InputOption>{ roleName: v[0], roleValue: v[1] }; | ||
}); | ||
accessPermissionsOptions.value = accessInput.options.map((v: [string, number]) => { | ||
return <InputOption>{ roleName: v[0], roleValue: v[1] }; | ||
}); | ||
|
||
managePermissions.value = manageInput.value; | ||
accessPermissions.value = accessInput.value; | ||
} | ||
|
||
export function useCallbacks(init: () => void) { | ||
const toast = useToast(); | ||
|
||
async function onError(e: unknown) { | ||
toast.error(errorMessageAsString(e)); | ||
} | ||
|
||
async function onSuccess(data: AxiosResponse) { | ||
toast.success(data.data.message); | ||
init(); | ||
} | ||
|
||
init(); | ||
|
||
return { onSuccess, onError }; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters