Unverified Commit a4cc8613 authored by Eric_Lee's avatar Eric_Lee Committed by GitHub

Merge pull request #183 from jumpserver/webftp_search

[Update] web sftp support asset
parents ea42c010 fcb52d3a
......@@ -19695,49 +19695,49 @@ $.fn.elfindersearchbutton = function(cmd) {
});
})
.one('open', function() {
opts = (fm.api < 2.1)? null : $('<div class="ui-front ui-widget ui-widget-content elfinder-button-menu elfinder-button-search-menu ui-corner-all"/>')
.append(
$('<div class="buttonset"/>')
.append(
$('<input id="'+id('SearchFromCwd')+'" name="serchfrom" type="radio" checked="checked"/><label for="'+id('SearchFromCwd')+'">'+fm.i18n('btnCwd')+'</label>'),
$('<input id="'+id('SearchFromVol')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromVol')+'">'+fm.i18n('btnVolume')+'</label>'),
$('<input id="'+id('SearchFromAll')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromAll')+'">'+fm.i18n('btnAll')+'</label>')
),
$('<div class="buttonset elfinder-search-type"/>')
.append(
$('<input id="'+id('SearchName')+'" name="serchcol" type="radio" checked="checked" value="SearchName"/><label for="'+id('SearchName')+'">'+fm.i18n('btnFileName')+'</label>')
)
)
.hide()
.appendTo(fm.getUI());
if (opts) {
if (sTypes) {
typeSet = opts.find('.elfinder-search-type');
$.each(cmd.options.searchTypes, function(i, v) {
typeSet.append($('<input id="'+id(i)+'" name="serchcol" type="radio" value="'+fm.escape(i)+'"/><label for="'+id(i)+'">'+fm.i18n(v.name)+'</label>'));
});
}
opts.find('div.buttonset').buttonset();
$('#'+id('SearchFromAll')).next('label').attr('title', fm.i18n('searchTarget', fm.i18n('btnAll')));
if (sTypes) {
$.each(sTypes, function(i, v) {
if (v.title) {
$('#'+id(i)).next('label').attr('title', fm.i18n(v.title));
}
});
}
opts.on('mousedown', 'div.buttonset', function(e){
e.stopPropagation();
opts.data('infocus', true);
})
.on('click', 'input', function(e) {
e.stopPropagation();
$.trim(input.val())? search() : input.trigger('focus');
})
.on('close', function() {
input.trigger('blur');
});
}
// opts = (fm.api < 2.1)? null : $('<div class="ui-front ui-widget ui-widget-content elfinder-button-menu elfinder-button-search-menu ui-corner-all"/>')
// .append(
// $('<div class="buttonset"/>')
// .append(
// $('<input id="'+id('SearchFromCwd')+'" name="serchfrom" type="radio" checked="checked"/><label for="'+id('SearchFromCwd')+'">'+fm.i18n('btnCwd')+'</label>'),
// $('<input id="'+id('SearchFromVol')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromVol')+'">'+fm.i18n('btnVolume')+'</label>'),
// $('<input id="'+id('SearchFromAll')+'" name="serchfrom" type="radio"/><label for="'+id('SearchFromAll')+'">'+fm.i18n('btnAll')+'</label>')
// ),
// $('<div class="buttonset elfinder-search-type"/>')
// .append(
// $('<input id="'+id('SearchName')+'" name="serchcol" type="radio" checked="checked" value="SearchName"/><label for="'+id('SearchName')+'">'+fm.i18n('btnFileName')+'</label>')
// )
// )
// .hide()
// .appendTo(fm.getUI());
// if (opts) {
// if (sTypes) {
// typeSet = opts.find('.elfinder-search-type');
// $.each(cmd.options.searchTypes, function(i, v) {
// typeSet.append($('<input id="'+id(i)+'" name="serchcol" type="radio" value="'+fm.escape(i)+'"/><label for="'+id(i)+'">'+fm.i18n(v.name)+'</label>'));
// });
// }
// opts.find('div.buttonset').buttonset();
// $('#'+id('SearchFromAll')).next('label').attr('title', fm.i18n('searchTarget', fm.i18n('btnAll')));
// if (sTypes) {
// $.each(sTypes, function(i, v) {
// if (v.title) {
// $('#'+id(i)).next('label').attr('title', fm.i18n(v.title));
// }
// });
// }
// opts.on('mousedown', 'div.buttonset', function(e){
// e.stopPropagation();
// opts.data('infocus', true);
// })
// .on('click', 'input', function(e) {
// e.stopPropagation();
// $.trim(input.val())? search() : input.trigger('focus');
// })
// .on('close', function() {
// input.trigger('blur');
// });
// }
})
.bind('searchend', function() {
input.val('');
......
......@@ -51,7 +51,10 @@
['copy', 'cut', 'paste'],
['rm'],
['rename'],
['view']
['view'],
{{if eq . "_"}}
['search']
{{end}}
],
cwd : {oldSchool: true}
},
......
......@@ -6,7 +6,7 @@ require (
github.com/Azure/azure-pipeline-go v0.1.9 // indirect
github.com/Azure/azure-storage-blob-go v0.6.0
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/LeeEirc/elfinder v0.0.9
github.com/LeeEirc/elfinder v0.0.11-0.20191224095556-900471613ab8
github.com/aliyun/aliyun-oss-go-sdk v1.9.8
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 // indirect
github.com/aws/aws-sdk-go v1.19.46
......
......@@ -5,8 +5,8 @@ github.com/Azure/azure-storage-blob-go v0.6.0 h1:SEATKb3LIHcaSIX+E6/K4kJpwfuozFE
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/LeeEirc/elfinder v0.0.9 h1:LfGY1UNVWAgZ8dYHBsrA+ROsGtwdZc7BcDQcG74kprE=
github.com/LeeEirc/elfinder v0.0.9/go.mod h1:d1bMAAydkZSBxSN/EuQjBg6B0xcPP3boHuYEpzEHYTs=
github.com/LeeEirc/elfinder v0.0.11-0.20191224095556-900471613ab8 h1:+q8TcqE/oiVu3B/rmlcsT9wZuzGLL3Wk7HGKVGuAHGo=
github.com/LeeEirc/elfinder v0.0.11-0.20191224095556-900471613ab8/go.mod h1:d1bMAAydkZSBxSN/EuQjBg6B0xcPP3boHuYEpzEHYTs=
github.com/LeeEirc/sftp v1.10.2 h1:SGpj84RbStlwH+ThXYUsxtxtbzAzpUY8z5gQN4p12OI=
github.com/LeeEirc/sftp v1.10.2/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/aliyun/aliyun-oss-go-sdk v1.9.8 h1:BOflvK0Zs/zGmoabyFIzTg5c3kguktWTXEwewwbuba0=
......
......@@ -322,6 +322,21 @@ func (u *UserVolume) RootFileDir() elfinder.FileDir {
func (u *UserVolume) Close() {
u.UserSftp.Close()
logger.Infof("User %s's volume close", u.UserSftp.User.Name)
}
func (u *UserVolume) Search(path, key string, mimes ...string) (res []elfinder.FileDir, err error) {
originFileInfolist, err := u.UserSftp.Search(key)
if err != nil {
return nil, err
}
res = make([]elfinder.FileDir, 0, len(originFileInfolist))
searchPath := fmt.Sprintf("/%s", srvconn.SearchFolderName)
for i := 0; i < len(originFileInfolist); i++ {
res = append(res, NewElfinderFileInfo(u.Uuid, searchPath, originFileInfolist[i]))
}
return
}
func NewElfinderFileInfo(id, dirPath string, originFileInfo os.FileInfo) elfinder.FileDir {
......
......@@ -182,3 +182,13 @@ func GetUserNodeTreeWithAsset(userID, nodeID, cachePolicy string) (nodeTrees mod
}
return
}
func SearchPermAsset(uid, key string) (res model.NodeTreeList, err error) {
Url := fmt.Sprintf(UserAssetsTree, uid)
payload := map[string]string{"search": key}
_, err = authClient.Get(Url, &res, payload)
if err != nil {
logger.Error("Get user node tree error: ", err)
}
return
}
\ No newline at end of file
......@@ -49,4 +49,6 @@ const (
UserDatabaseSystemUsersURL = "/api/v1/perms/users/%s/database-apps/%s/system-users/"
SystemUserAuthURL = "/api/v1/assets/system-users/%s/auth-info/"
UserAssetsTree = "/api/v1/perms/users/%s/assets/tree/"
)
......@@ -24,6 +24,8 @@ type UserSftpConn struct {
logChan chan *model.FTPLog
closed chan struct{}
searchDir *SearchResultDir
}
func (u *UserSftpConn) ReadDir(path string) (res []os.FileInfo, err error) {
......@@ -189,6 +191,9 @@ func (u *UserSftpConn) Close() {
continue
}
}
if u.searchDir != nil{
u.searchDir.close()
}
close(u.closed)
}
......@@ -224,8 +229,15 @@ func (u *UserSftpConn) ParsePath(path string) (fi os.FileInfo, restPath string)
fi = u
return
}
dirs := u.Dirs
var dirs map[string]os.FileInfo
var ok bool
if data[0] == SearchFolderName {
dirs = u.searchDir.subDirs
data = data[1:]
} else {
dirs = u.Dirs
}
for i := 0; i < len(data); i++ {
fi, ok = dirs[data[i]]
if !ok {
......@@ -251,6 +263,11 @@ func (u *UserSftpConn) initial() {
if u.Dirs == nil {
u.Dirs = map[string]os.FileInfo{}
}
u.searchDir = &SearchResultDir{
folderName: SearchFolderName,
modeTime: time.Now().UTC(),
subDirs: map[string]os.FileInfo{}}
for _, item := range nodeTrees {
if item.Pid != "" {
continue
......@@ -352,6 +369,56 @@ func (u *UserSftpConn) loopPushFTPLog() {
}
}
func (u *UserSftpConn) Search(key string) (res []os.FileInfo, err error) {
if u.searchDir == nil{
logger.Errorf("not found search folder")
return nil, fmt.Errorf("not found")
}
assetsTree, err := service.SearchPermAsset(u.User.ID, key)
if err != nil {
logger.Errorf("search asset err: %s", err)
return nil, err
}
subDirs := map[string]os.FileInfo{}
for _, item := range assetsTree {
typeName, ok := item.Meta["type"].(string)
if !ok {
continue
}
body, err := json.Marshal(item.Meta[typeName])
if err != nil {
logger.Errorf("Search Json Marshal err: %s", err)
continue
}
switch typeName {
case "asset":
asset, err := model.ConvertMetaToAsset(body)
if err != nil {
logger.Errorf("convert to asset err: %s", err)
continue
}
if !asset.IsSupportProtocol("ssh") {
continue
}
assetDir := NewAssetDir(u.User, asset, u.Addr, u.logChan)
folderName := assetDir.folderName
for {
_, ok := subDirs[folderName]
if !ok {
break
}
folderName = fmt.Sprintf("%s_", folderName)
}
if folderName != assetDir.folderName {
assetDir.folderName = folderName
}
subDirs[assetDir.folderName] = &assetDir
}
}
u.searchDir.SetSubDirs(subDirs)
return u.searchDir.List()
}
func NewUserSftpConn(user *model.User, addr string) *UserSftpConn {
u := UserSftpConn{
User: user,
......
......@@ -19,6 +19,60 @@ import (
"github.com/jumpserver/koko/pkg/service"
)
const (
SearchFolderName = "_Search"
)
type SearchResultDir struct {
subDirs map[string]os.FileInfo
folderName string
modeTime time.Time
}
func (sd *SearchResultDir) Name() string {
return sd.folderName
}
func (sd *SearchResultDir) Size() int64 { return 0 }
func (sd *SearchResultDir) Mode() os.FileMode {
return os.ModePerm | os.ModeDir
}
func (sd *SearchResultDir) ModTime() time.Time { return sd.modeTime }
func (sd *SearchResultDir) IsDir() bool { return true }
func (sd *SearchResultDir) Sys() interface{} {
return &syscall.Stat_t{Uid: 0, Gid: 0}
}
func (sd *SearchResultDir) List() (res []os.FileInfo, err error) {
for _, item := range sd.subDirs {
res = append(res, item)
}
return
}
func (sd *SearchResultDir) SetSubDirs(subDirs map[string]os.FileInfo) {
if sd.subDirs != nil {
for _, dir := range sd.subDirs {
if assetDir, ok := dir.(*AssetDir); ok {
assetDir.close()
}
}
}
sd.subDirs = subDirs
}
func (sd *SearchResultDir) close() {
for _, dir := range sd.subDirs {
if assetDir, ok := dir.(*AssetDir); ok {
assetDir.close()
}
}
}
type NodeDir struct {
node *model.Node
subDirs map[string]os.FileInfo
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment