Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nc fix: add missing signedPath or signedUrl in form attachements #7768

Merged
merged 9 commits into from
Mar 3, 2024
4 changes: 3 additions & 1 deletion packages/nc-gui/components/general/FormBanner.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
<script lang="ts" setup>
import type { AttachmentResType } from 'nocodb-sdk';

interface Props {
bannerImageUrl?: string | null
bannerImageUrl?: AttachmentResType
}
const { bannerImageUrl } = defineProps<Props>()

Expand Down
15 changes: 8 additions & 7 deletions packages/nc-gui/components/smartsheet/Form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
isLinksOrLTAR,
isSelectTypeCol,
isVirtualCol,
type AttachmentResType,
} from 'nocodb-sdk'
import type { Permission } from '#imports'
import {
Expand Down Expand Up @@ -372,8 +373,8 @@ function setFormData() {
systemFieldsIds.value = getSystemColumns(col).map((c) => c.fk_column_id)

formViewData.value = {
banner_image_url: '',
logo_url: '',
banner_image_url: null,
logo_url: null,
...formViewData.value,
submit_another_form: !!(formViewData.value?.submit_another_form ?? 0),
show_blank_form: !!(formViewData.value?.show_blank_form ?? 0),
Expand Down Expand Up @@ -503,11 +504,11 @@ onChangeFile((files) => {
}
})

const handleOnUploadImage = (data: Record<string, any> = {}) => {
const handleOnUploadImage = (data: AttachmentResType = null) => {
if (imageCropperData.value.cropFor === 'banner') {
formViewData.value!.banner_image_url = stringifyProp(data) ?? ''
formViewData.value!.banner_image_url = data
} else {
formViewData.value!.logo_url = stringifyProp(data) ?? ''
formViewData.value!.logo_url = data
}
updateView()
}
Expand Down Expand Up @@ -724,7 +725,7 @@ useEventListener(
@click="
() => {
if (isEditable) {
formViewData!.banner_image_url = ''
formViewData!.banner_image_url = null
updateView()
}
}
Expand Down Expand Up @@ -787,7 +788,7 @@ useEventListener(
@click="
() => {
if (isEditable) {
formViewData!.logo_url = ''
formViewData!.logo_url = null
updateView()
}
}
Expand Down
108 changes: 103 additions & 5 deletions packages/nocodb/src/models/FormView.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
import type { MetaType } from 'nocodb-sdk';
import type { BoolType, FormType } from 'nocodb-sdk';
import type {
MetaType,
BoolType,
FormType,
AttachmentResType,
} from 'nocodb-sdk';
import { PresignedUrl } from '~/models';
import FormViewColumn from '~/models/FormViewColumn';
import View from '~/models/View';
import { extractProps } from '~/helpers/extractProps';
Expand All @@ -9,7 +14,12 @@ import { deserializeJSON, serializeJSON } from '~/utils/serialize';
import { CacheGetType, CacheScope, MetaTable } from '~/utils/globals';
import { prepareForDb, prepareForResponse } from '~/utils/modelUtils';

export default class FormView implements FormType {
type FormViewType = Omit<FormType, 'banner_image_url' | 'logo_url'> & {
banner_image_url?: AttachmentResType | string;
logo_url?: AttachmentResType | string;
};

export default class FormView implements FormViewType {
show: BoolType;
is_default: BoolType;
order: number;
Expand All @@ -20,8 +30,8 @@ export default class FormView implements FormType {
redirect_url?: string;
redirect_after_secs?: string;
email?: string;
banner_image_url?: string;
logo_url?: string;
banner_image_url?: AttachmentResType | string;
logo_url?: AttachmentResType | string;
submit_another_form?: BoolType;
show_blank_form?: BoolType;

Expand All @@ -46,11 +56,21 @@ export default class FormView implements FormType {
view = await ncMeta.metaGet2(null, null, MetaTable.FORM_VIEW, {
fk_view_id: viewId,
});

if (view) {
view.meta = deserializeJSON(view.meta);
await NocoCache.set(`${CacheScope.FORM_VIEW}:${viewId}`, view);
}
}

const convertedAttachment = await this.convertAttachmentType({
banner_image_url: view?.banner_image_url,
logo_url: view?.logo_url,
});

view.banner_image_url = convertedAttachment.banner_image_url || null;
view.logo_url = convertedAttachment.logo_url || null;

return view && new FormView(view);
}

Expand All @@ -74,6 +94,17 @@ export default class FormView implements FormType {
if (insertObj.meta) {
insertObj.meta = serializeJSON(insertObj.meta);
}

if (insertObj?.logo_url) {
insertObj.logo_url = this.serializeAttachmentJSON(insertObj.logo_url);
}

if (insertObj?.banner_image_url) {
insertObj.banner_image_url = this.serializeAttachmentJSON(
insertObj.banner_image_url,
);
}

if (!(view.base_id && view.source_id)) {
const viewRef = await View.get(view.fk_view_id);
insertObj.base_id = viewRef.base_id;
Expand Down Expand Up @@ -103,6 +134,16 @@ export default class FormView implements FormType {
'meta',
]);

if (updateObj?.logo_url) {
updateObj.logo_url = this.serializeAttachmentJSON(updateObj.logo_url);
}

if (updateObj?.banner_image_url) {
updateObj.banner_image_url = this.serializeAttachmentJSON(
updateObj.banner_image_url,
);
}

// update meta
const res = await ncMeta.metaUpdate(
null,
Expand Down Expand Up @@ -131,4 +172,61 @@ export default class FormView implements FormType {
await form.getColumns(ncMeta);
return form;
}

static serializeAttachmentJSON(attachment): string | null {
if (attachment) {
return serializeJSON(
extractProps(deserializeJSON(attachment), [
'url',
'path',
'title',
'mimetype',
'size',
'icon',
]),
);
}
return attachment;
}

protected static async convertAttachmentType(
formAttachments: Record<string, any>,
) {
try {
if (formAttachments) {
const promises = [];

for (const key in formAttachments) {
if (
formAttachments[key] &&
typeof formAttachments[key] === 'string'
) {
formAttachments[key] = deserializeJSON(formAttachments[key]);
}

if (formAttachments[key]?.path) {
promises.push(
PresignedUrl.getSignedUrl({
path: formAttachments[key].path.replace(/^download\//, ''),
}).then((r) => (formAttachments[key].signedPath = r)),
);
} else if (formAttachments[key]?.url) {
if (formAttachments[key].url.includes('.amazonaws.com/')) {
const relativePath = decodeURI(
formAttachments[key].url.split('.amazonaws.com/')[1],
);
promises.push(
PresignedUrl.getSignedUrl({
path: relativePath,
s3: true,
}).then((r) => (formAttachments[key].signedUrl = r)),
);
}
}
}
await Promise.all(promises);
}
} catch {}
return formAttachments;
}
}