Skip to content

Commit

Permalink
transfer ownership of a form
Browse files Browse the repository at this point in the history
Signed-off-by: hamza221 <hamzamahjoubi221@gmail.com>
  • Loading branch information
hamza221 committed Nov 26, 2022
1 parent 674d340 commit 8cfd77a
Show file tree
Hide file tree
Showing 6 changed files with 169 additions and 3 deletions.
8 changes: 8 additions & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,14 @@
'apiVersion' => 'v2'
]
],
[
'name' => 'api#ownerTransfer',
'url' => '/api/{apiVersion}/form/transfer',
'verb' => 'POST',
'requirements' => [
'apiVersion' => 'v2'
]
],

// Questions
[
Expand Down
45 changes: 45 additions & 0 deletions lib/Controller/ApiController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1136,4 +1136,49 @@ public function exportSubmissionsToCloud(string $hash, string $path) {

return new DataResponse($fileName);
}
/**
* @NoAdminRequired
*
* Transfer ownership of a form to another user
*
* @param int $formId id of the form to update
* @param string $uid id of the new owner
* @return DataResponse
* @throws OCSBadRequestException
* @throws OCSForbiddenException
*/
public function ownerTransfer(int $formId, string $uid): DataResponse {
$this->logger->debug('Updating owner: formId: {formId}, userId: {uid}', [
'formId' => $formId,
'uid' => $uid
]);

try {
$form = $this->formMapper->findById($formId);
} catch (IMapperException $e) {
$this->logger->debug('Could not find form');
throw new OCSBadRequestException('Could not find form');
}

if ($form->getOwnerId() !== $this->currentUser->getUID()) {
$this->logger->debug('This form is not owned by the current user');
throw new OCSForbiddenException();
}

// update form owner
$form->setOwnerId($uid);

// Update changed Columns in Db.
$this->formMapper->update($form);

//delete this form from shares for the new owner
try {
$share = $this->shareMapper->findPublicShareByFormIdAndUid($formId, $uid);
$this->shareMapper->deleteById($share->getId());
} catch (IMapperException $e) {
$this->logger->debug('No shares found');
}

return new DataResponse($form->getOwnerId());
}
}
21 changes: 21 additions & 0 deletions lib/Db/ShareMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,28 @@ public function findPublicShareByHash(string $hash): Share {

return $this->findEntity($qb);
}
/**
* Find Share by formId and user id
* @param int $formId
* @param string $uid
* @return Share
* @throws MultipleObjectsReturnedException if more than one result
* @throws DoesNotExistException if not found
*/
public function findPublicShareByFormIdAndUid(int $formId, string $uid): Share {
$qb = $this->db->getQueryBuilder();

$qb->select('*')
->from($this->getTableName())
->where(
$qb->expr()->eq('form_id', $qb->createNamedParameter($formId, IQueryBuilder::PARAM_INT))
)
->andWhere(
$qb->expr()->eq('share_with', $qb->createNamedParameter($uid, IQueryBuilder::PARAM_STR))
);

return $this->findEntity($qb);
}
/**
* Delete a share
* @param int $id of the share.
Expand Down
73 changes: 71 additions & 2 deletions src/Forms.vue
Original file line number Diff line number Diff line change
Expand Up @@ -96,17 +96,37 @@
:form="selectedForm"
:opened.sync="sidebarOpened"
:active.sync="sidebarActive"
name="sidebar" />
name="sidebar"
@transfer:ownership="openModal" />
</template>
<NcModal v-if="modal"
size="normal"
title="Transfer Ownership"
name="NcModal"
:outTransition="true"
@close="closeModal">
<div class="modal__content">
{{ t('forms', 'Are you sure you want to tranfer Ownership of this Form to ') }} {{ tranferData.displayName }}?
<div class="modal_buttons">
<NcButton type="primary" @click="onOwnershipTransfer">
Yes
</NcButton>
<NcButton type="error" @click="closeModal">
No
</NcButton>
</div>
</div>
</NcModal>
</NcContent>
</template>

<script>
import { emit } from '@nextcloud/event-bus'
import { generateOcsUrl } from '@nextcloud/router'
import { loadState } from '@nextcloud/initial-state'
import { showError } from '@nextcloud/dialogs'
import { showError, showSuccess } from '@nextcloud/dialogs'
import axios from '@nextcloud/axios'
import Router from 'vue-router'
import NcAppContent from '@nextcloud/vue/dist/Components/NcAppContent.js'
import NcAppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation.js'
Expand All @@ -117,6 +137,7 @@ import NcContent from '@nextcloud/vue/dist/Components/NcContent.js'
import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
import isMobile from '@nextcloud/vue/dist/Mixins/isMobile.js'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import IconPlus from 'vue-material-design-icons/Plus.vue'
Expand All @@ -141,17 +162,20 @@ export default {
NcContent,
NcEmptyContent,
NcLoadingIcon,
NcModal,
},
mixins: [isMobile, PermissionTypes],
data() {
return {
loading: true,
modal: false,
sidebarOpened: false,
sidebarActive: 'forms-sharing',
forms: [],
sharedForms: [],
tranferData: { formId: null, userId: null, displayName: null },
canCreateForms: loadState(appName, 'appConfig').canCreateForms,
}
Expand Down Expand Up @@ -221,6 +245,40 @@ export default {
},
methods: {
closeModal() {
this.modal = false
showError(t('forms', 'Ownership transfer was Cancelled'))
},
openModal(share, id) {
this.modal = true
this.tranferData.formId = id
this.tranferData.userId = share?.shareWith
this.tranferData.displayName = share?.displayName
},
async onOwnershipTransfer() {
this.modal = false
if (this.tranferData.formId && this.tranferData.userId) {
try {
await axios.post(generateOcsUrl('apps/forms/api/v2/form/transfer'), {
formId: this.tranferData.formId,
uid: this.tranferData.userId,
})
showSuccess(`${t('forms', 'This form is now owned by')} ${this.tranferData.displayName}`)
Router.push('/')
location.reload()
} catch (error) {
logger.error('Error while transfering form ownership', { error })
showError(t('forms', 'An error occurred while transfering ownership'))
}
} else {
logger.error('Null parameters while transfering form ownership', { transferData: this.tranferData })
showError(t('forms', 'An error occurred while transfering ownership'))
}
},
/**
* Closes the App-Navigation on mobile-devices
*/
Expand Down Expand Up @@ -348,3 +406,14 @@ export default {
},
}
</script>
<style scoped>
.modal__content {
margin: 50px;
text-align: center;
}
.modal_buttons{
display: flex;
margin-top:30px;
justify-content: space-around;
}
</style>
19 changes: 19 additions & 0 deletions src/components/SidebarTabs/SettingsSidebarTab.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,15 @@

<template>
<div class="sidebar-tabs__content">
<div>
<NcCheckboxRadioSwitch :checked="isChangingOwnership"
type="switch"
@update:checked="onChangeOwner">
{{ t('forms', 'Change form owner') }}
</NcCheckboxRadioSwitch>
<SharingSearchDiv v-show="isChangingOwnership"
@add-share="tranferOwnership" />
</div>
<NcCheckboxRadioSwitch :checked="form.isAnonymous"
type="switch"
@update:checked="onAnonChange">
Expand Down Expand Up @@ -63,11 +72,13 @@ import moment from '@nextcloud/moment'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcDatetimePicker from '@nextcloud/vue/dist/Components/NcDatetimePicker.js'
import ShareTypes from '../../mixins/ShareTypes.js'
import SharingSearchDiv from './SharingSearchDiv.vue'
export default {
components: {
NcCheckboxRadioSwitch,
NcDatetimePicker,
SharingSearchDiv,
},
mixins: [ShareTypes],
Expand All @@ -81,10 +92,12 @@ export default {
data() {
return {
isLoading: false,
formatter: {
stringify: this.stringifyDate,
parse: this.parseTimestampToDate,
},
isChangingOwnership: false,
}
},
Expand Down Expand Up @@ -196,6 +209,12 @@ export default {
notBeforeNow(datetime) {
return datetime < moment().toDate()
},
tranferOwnership(share) {
this.$emit('transfer:ownership', share)
},
onChangeOwner() {
this.isChangingOwnership = !this.isChangingOwnership
},
},
}
</script>
Expand Down
6 changes: 5 additions & 1 deletion src/views/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
<IconSettings :size="20" />
</template>
<SettingsSidebarTab :form="form"
@update:formProp="onPropertyChange" />
@update:formProp="onPropertyChange"
@transfer:ownership="onOwnershipTransfer" />
</NcAppSidebarTab>
</NcAppSidebar>
</template>
Expand Down Expand Up @@ -97,6 +98,9 @@ export default {
onUpdateActive(active) {
this.$emit('update:active', active)
},
onOwnershipTransfer(share) {
this.$emit('transfer:ownership', share, this.form.id)
},
/**
* Save Form-Properties
Expand Down

0 comments on commit 8cfd77a

Please sign in to comment.