Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 40 additions & 25 deletions agent/utils/files/fileinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,31 +92,33 @@ var binaryPreviewExtensions = map[string]struct{}{
}

type FileInfo struct {
Fs afero.Fs `json:"-"`
Path string `json:"path"`
Name string `json:"name"`
User string `json:"user"`
Group string `json:"group"`
Uid string `json:"uid"`
Gid string `json:"gid"`
Extension string `json:"extension"`
Content string `json:"content"`
Size int64 `json:"size"`
IsDir bool `json:"isDir"`
IsSymlink bool `json:"isSymlink"`
IsHidden bool `json:"isHidden"`
LinkPath string `json:"linkPath"`
Type string `json:"type"`
Mode string `json:"mode"`
MimeType string `json:"mimeType"`
UpdateTime time.Time `json:"updateTime"`
ModTime time.Time `json:"modTime"`
FileMode os.FileMode `json:"-"`
Items []*FileInfo `json:"items"`
ItemTotal int `json:"itemTotal"`
FavoriteID uint `json:"favoriteID"`
ShareCode string `json:"shareCode"`
IsDetail bool `json:"isDetail"`
Fs afero.Fs `json:"-"`
Path string `json:"path"`
Name string `json:"name"`
User string `json:"user"`
Group string `json:"group"`
Uid string `json:"uid"`
Gid string `json:"gid"`
Extension string `json:"extension"`
Content string `json:"content"`
Size int64 `json:"size"`
IsDir bool `json:"isDir"`
IsSymlink bool `json:"isSymlink"`
IsHidden bool `json:"isHidden"`
LinkPath string `json:"linkPath"`
Type string `json:"type"`
Mode string `json:"mode"`
MimeType string `json:"mimeType"`
UpdateTime time.Time `json:"updateTime"`
ModTime time.Time `json:"modTime"`
FileMode os.FileMode `json:"-"`
Items []*FileInfo `json:"items"`
ItemTotal int `json:"itemTotal"`
FavoriteID uint `json:"favoriteID"`
ShareCode string `json:"shareCode"`
IsDetail bool `json:"isDetail"`
IsAppendOnly bool `json:"isAppendOnly"`
IsImmutable bool `json:"isImmutable"`
}

type FileOption struct {
Expand Down Expand Up @@ -173,6 +175,7 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
if favorite.ID > 0 {
file.FavoriteID = favorite.ID
}
file.IsAppendOnly, file.IsImmutable = getFileAttributes(op.Path)

if file.IsSymlink {
linkPath := GetSymlink(op.Path)
Expand Down Expand Up @@ -204,6 +207,18 @@ func NewFileInfo(op FileOption) (*FileInfo, error) {
return file, nil
}

func getFileAttributes(filePath string) (bool, bool) {
output, err := exec.Command("lsattr", "-d", "--", filePath).Output()
if err != nil {
return false, false
}
fields := strings.Fields(string(output))
if len(fields) == 0 {
return false, false
}
return strings.Contains(fields[0], "a"), strings.Contains(fields[0], "i")
}

func handleExpansion(file *FileInfo, op FileOption) error {
if file.IsDir {
return file.listChildren(op)
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/api/interface/file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export namespace File {
favoriteID: number;
shareCode: string;
remark?: string;
isAppendOnly: boolean;
isImmutable: boolean;
}

export interface ReqFile extends ReqPage {
Expand Down Expand Up @@ -117,6 +119,7 @@ export namespace File {
linkPath?: boolean;
sub?: boolean;
name?: string;
isAppendOnly?: boolean;
}

export interface FileDelete {
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5050,6 +5050,8 @@ const message = {
},
tamper: {
tamper: 'Website Tamper Protection',
tamperCreateHint:
'The current directory may be affected by tamper protection or file attributes, causing creation to fail.',
ignoreTemplate: 'Exclusion Template',
protectTemplate: 'Protection Template',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/es-es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5092,6 +5092,8 @@ const message = {
},
tamper: {
tamper: 'Anti-manipulación web',
tamperCreateHint:
'El directorio actual puede verse afectado por la protección antimanipulación o los atributos de archivo, lo que provoca un error de creación.',
ignoreTemplate: 'Plantilla de Exclusión',
protectTemplate: 'Plantilla de Protección',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/fa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5013,6 +5013,8 @@ const message = {
},
tamper: {
tamper: 'محافظت در برابر دستکاری وب‌سایت',
tamperCreateHint:
'دایرکتوری فعلی ممکن است تحت تأثیر محافظت در برابر دستکاری یا ویژگی‌های فایل باشد و ایجاد با خطا مواجه شود.',
ignoreTemplate: 'الگوی حذف',
protectTemplate: 'الگوی محافظت',
ignoreTemplateHelper:
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5065,6 +5065,7 @@ const message = {
},
tamper: {
tamper: 'ウェブサイトの改ざん防止',
tamperCreateHint: '現在のディレクトリは改ざん防止またはファイル属性の影響を受け、作成に失敗する可能性があります。',
ignoreTemplate: '除外テンプレート',
protectTemplate: '保護テンプレート',
ignoreTemplateHelper:
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4969,6 +4969,7 @@ const message = {
},
tamper: {
tamper: '웹사이트 변조 방지',
tamperCreateHint: '현재 디렉터리는 변조 방지 또는 파일 속성의 영향을 받아 생성에 실패할 수 있습니다.',
ignoreTemplate: '제외 템플릿',
protectTemplate: '보호 템플릿',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/ms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5128,6 +5128,8 @@ const message = {
},
tamper: {
tamper: 'Perlindungan laman web',
tamperCreateHint:
'Direktori semasa mungkin dipengaruhi oleh perlindungan gangguan atau atribut fail, menyebabkan penciptaan gagal.',
ignoreTemplate: 'Templat Pengecualian',
protectTemplate: 'Templat Perlindungan',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/pt-br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5274,6 +5274,8 @@ const message = {
},
tamper: {
tamper: 'Proteção contra adulteração do site',
tamperCreateHint:
'O diretório atual pode ser afetado pela proteção contra alterações ou por atributos de arquivo, causando falha na criação.',
ignoreTemplate: 'Modelo de Exclusão',
protectTemplate: 'Modelo de Proteção',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5121,6 +5121,8 @@ const message = {
},
tamper: {
tamper: 'Защита от подделки сайта',
tamperCreateHint:
'Текущий каталог может быть затронут защитой от изменений или атрибутами файла, что приведет к ошибке создания.',
ignoreTemplate: 'Шаблон Исключения',
protectTemplate: 'Шаблон Защиты',
ignoreTemplateHelper:
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lang/modules/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5117,6 +5117,8 @@ const message = {
},
tamper: {
tamper: 'Web Sitesi Değiştirme Koruması',
tamperCreateHint:
'Geçerli dizin kurcalama korumasından veya dosya özniteliklerinden etkilenerek oluşturma işleminin başarısız olmasına neden olabilir.',
ignoreTemplate: 'Hariç Tutma Şablonu',
protectTemplate: 'Koruma Şablonu',
ignoreTemplateHelper:
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh-Hant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4710,6 +4710,7 @@ const message = {
},
tamper: {
tamper: '網站防篡改',
tamperCreateHint: '目前目錄可能受防篡改或檔案屬性限制影響,導致建立失敗。',
ignoreTemplate: '排除範本',
protectTemplate: '保護範本',
ignoreTemplateHelper:
Expand Down
1 change: 1 addition & 0 deletions frontend/src/lang/modules/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4159,6 +4159,7 @@ const message = {
},
tamper: {
tamper: '网站防篡改',
tamperCreateHint: '当前目录可能受防篡改或文件属性限制影响,导致创建失败。',
ignoreTemplate: '排除模版',
protectTemplate: '保护模版',
ignoreTemplateHelper:
Expand Down
19 changes: 18 additions & 1 deletion frontend/src/views/host/file-management/create/index.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
<template>
<DrawerPro v-model="open" :header="$t('commons.button.create')" @close="handleClose" size="normal">
<el-alert
v-if="addForm.isAppendOnly"
type="warning"
:title="$t('xpack.tamper.tamperCreateHint')"
:closable="false"
/>
<el-form
ref="fileForm"
class="mt-2"
label-position="top"
:model="addForm"
label-width="100px"
Expand Down Expand Up @@ -66,7 +73,16 @@ const propData = ref<CreateProps>({
file: {},
});

let addForm = reactive({ path: '', name: '', isDir: false, mode: 0o755, isLink: false, isSymlink: true, linkPath: '' });
let addForm = reactive({
path: '',
name: '',
isDir: false,
mode: 0o755,
isLink: false,
isSymlink: true,
linkPath: '',
isAppendOnly: false,
});
let open = ref(false);
const em = defineEmits(['close']);
const handleClose = () => {
Expand Down Expand Up @@ -137,6 +153,7 @@ const acceptParams = (create: File.FileCreate) => {
addForm.path = create.path;
addForm.name = '';
addForm.isLink = false;
addForm.isAppendOnly = Boolean(create.isAppendOnly);

init();
};
Expand Down
9 changes: 6 additions & 3 deletions frontend/src/views/host/file-management/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ let pathWidth = ref(0);
const history: string[] = [];
let pointer = -1;

const fileCreate = reactive({ path: '/', isDir: false, mode: 0o755 });
const fileCreate = reactive({ path: '/', isDir: false, mode: 0o755, isAppendOnly: false });
const fileCompress = reactive({ files: [''], name: '', dst: '', operate: 'compress' });
const fileDeCompress = reactive({ path: '', name: '', dst: '', type: '' });
const fileEdit = reactive<{
Expand All @@ -863,9 +863,9 @@ const fileEdit = reactive<{
}>({ content: '', path: '', name: '', language: 'plaintext', extension: '' });
const filePreview = reactive({ path: '', name: '', extension: '', fileType: '', imageFiles: [], currentNode: '' });
const codeReq = reactive({ path: '', expand: false, page: 1, pageSize: 100, isDetail: false });
const fileUpload = reactive({ path: '' });
const fileUpload = reactive({ path: '', isAppendOnly: false });
const fileRename = reactive({ path: '', oldName: '', newName: '' });
const fileWget = reactive({ path: '' });
const fileWget = reactive({ path: '', isAppendOnly: false });
const fileMove = reactive({ oldPaths: [''], allNames: [''], type: '', path: '', name: '', count: 0, isDir: false });
const fileConvert = reactive<{
outputPath: string;
Expand Down Expand Up @@ -1106,6 +1106,9 @@ const handleSearchResult = (res: ResultData<File.File>) => {
if (res.data.path) {
req.path = res.data.path;
}
fileCreate.isAppendOnly = res.data.isAppendOnly;
fileUpload.isAppendOnly = res.data.isAppendOnly;
fileWget.isAppendOnly = res.data.isAppendOnly;
scheduleRemarkLoad();
};

Expand Down
10 changes: 10 additions & 0 deletions frontend/src/views/host/file-management/upload/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
:confirmBeforeClose="true"
>
<template #content>
<el-alert
v-if="isAppendOnly"
class="mb-4"
type="warning"
:title="$t('xpack.tamper.tamperCreateHint')"
:closable="false"
/>
<div class="upload-button flex flex-wrap justify-between items-center gap-4 pb-4 md:flex-nowrap">
<div class="flex flex-wrap gap-4">
<el-button type="primary" @click="upload('file')">
Expand Down Expand Up @@ -119,6 +126,7 @@ import ExistFileDialog from '@/components/exist-file/index.vue';

interface UploadFileProps {
path: string;
isAppendOnly?: boolean;
}

const uploadRef = ref<UploadInstance>();
Expand All @@ -136,6 +144,7 @@ const uploadOverallPercent = computed(() => {
return Math.min(100, Math.round(raw));
});
const open = ref(false);
const isAppendOnly = ref(false);
const path = ref();
let uploadHelper = ref('');
const dialogExistFileRef = ref();
Expand Down Expand Up @@ -463,6 +472,7 @@ const getFilenameFromPath = (path: string) => {

const acceptParams = (props: UploadFileProps) => {
path.value = props.path;
isAppendOnly.value = Boolean(props.isAppendOnly);
open.value = true;
uploadPercent.value = 0;
uploadTotalCount.value = 0;
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/views/host/file-management/wget/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,13 @@
<span class="input-help">{{ $t('file.ignoreCertificateHelper') }}</span>
</el-form-item>
</el-form>
<el-alert
v-if="isAppendOnly"
class="mt-4"
type="warning"
:title="$t('xpack.tamper.tamperCreateHint')"
:closable="false"
/>
<template #footer>
<span class="dialog-footer">
<el-button @click="handleClose()" :disabled="loading">{{ $t('commons.button.cancel') }}</el-button>
Expand All @@ -57,10 +64,12 @@ import { MsgSuccess } from '@/utils/message';

interface WgetProps {
path: string;
isAppendOnly?: boolean;
}

const fileForm = ref<FormInstance>();
const loading = ref(false);
const isAppendOnly = ref(false);
let open = ref(false);
let submitData = ref(false);
const fileRef = ref();
Expand Down Expand Up @@ -140,6 +149,7 @@ const getFileName = (url: string) => {

const acceptParams = (props: WgetProps) => {
addForm.path = props.path;
isAppendOnly.value = Boolean(props.isAppendOnly);
open.value = true;
submitData.value = false;
addForm.ignoreCertificate = false;
Expand Down
Loading