Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in
Toggle navigation
K
koko
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ops
koko
Commits
bba9f607
Commit
bba9f607
authored
Jun 06, 2019
by
Eric
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[update] add sftp volume support
parent
11ef7697
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
846 additions
and
10 deletions
+846
-10
Gopkg.lock
Gopkg.lock
+1
-0
elfhandler.go
pkg/httpd/elfhandler.go
+26
-10
sftpvolume.go
pkg/httpd/sftpvolume.go
+784
-0
volumemanager.go
pkg/httpd/volumemanager.go
+35
-0
No files found.
Gopkg.lock
View file @
bba9f607
...
...
@@ -329,6 +329,7 @@
"github.com/aws/aws-sdk-go/aws",
"github.com/aws/aws-sdk-go/aws/credentials",
"github.com/aws/aws-sdk-go/aws/session",
"github.com/aws/aws-sdk-go/service/s3",
"github.com/aws/aws-sdk-go/service/s3/s3manager",
"github.com/elastic/go-elasticsearch",
"github.com/gliderlabs/ssh",
...
...
pkg/httpd/elfhandler.go
View file @
bba9f607
...
...
@@ -4,7 +4,6 @@ import (
"context"
"fmt"
"html/template"
"log"
"net/http"
"strings"
...
...
@@ -51,18 +50,15 @@ func AuthDecorator(handler http.HandlerFunc) http.HandlerFunc {
}
func
OnELFinderConnect
(
s
socketio
.
Conn
)
error
{
u
:=
s
.
URL
()
sid
:=
u
.
Query
()
.
Get
(
"sid"
)
data
:=
EmitSidMsg
{
Sid
:
sid
}
data
:=
EmitSidMsg
{
Sid
:
s
.
ID
()}
s
.
Emit
(
"data"
,
data
)
return
nil
}
func
OnELFinderDisconnect
(
s
socketio
.
Conn
,
msg
string
)
{
u
:=
s
.
URL
()
sid
:=
u
.
Query
()
.
Get
(
"sid"
)
log
.
Println
(
"disconnect: "
,
sid
)
log
.
Println
(
"disconnect msg "
,
msg
)
logger
.
Debug
(
"disconnect: "
,
s
.
ID
())
logger
.
Debug
(
"disconnect msg "
,
msg
)
removeUserVolume
(
s
.
ID
())
}
func
sftpHostFinder
(
wr
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
...
...
@@ -80,7 +76,27 @@ func sftpFinder(wr http.ResponseWriter, req *http.Request) {
func
sftpHostConnectorView
(
wr
http
.
ResponseWriter
,
req
*
http
.
Request
)
{
user
:=
req
.
Context
()
.
Value
(
cctx
.
ContextKeyUser
)
.
(
*
model
.
User
)
remoteIP
:=
req
.
Context
()
.
Value
(
cctx
.
ContextKeyRemoteAddr
)
.
(
string
)
logger
.
Debugf
(
"user: %s; remote ip: %s; create connector"
,
user
.
Name
,
remoteIP
)
con
:=
elfinder
.
NewElFinderConnector
([]
elfinder
.
Volume
{
&
elfinder
.
DefaultVolume
})
switch
req
.
Method
{
case
"GET"
:
if
err
:=
req
.
ParseForm
();
err
!=
nil
{
http
.
Error
(
wr
,
err
.
Error
(),
http
.
StatusBadRequest
)
return
}
case
"POST"
:
err
:=
req
.
ParseMultipartForm
(
32
<<
20
)
if
err
!=
nil
{
http
.
Error
(
wr
,
err
.
Error
(),
http
.
StatusBadRequest
)
return
}
}
sid
:=
req
.
Form
.
Get
(
"sid"
)
userV
,
ok
:=
GetUserVolume
(
sid
)
if
!
ok
{
userV
=
NewUserVolume
(
user
,
remoteIP
)
addUserVolume
(
sid
,
userV
)
}
logger
.
Debugf
(
"sid: %s"
,
sid
)
logger
.
Debug
(
userVolumes
)
con
:=
elfinder
.
NewElFinderConnector
([]
elfinder
.
Volume
{
userV
})
con
.
ServeHTTP
(
wr
,
req
)
}
pkg/httpd/sftpvolume.go
0 → 100644
View file @
bba9f607
package
httpd
import
(
"cocogo/pkg/common"
"cocogo/pkg/srvconn"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/LeeEirc/elfinder"
"github.com/pkg/sftp"
gossh
"golang.org/x/crypto/ssh"
"cocogo/pkg/config"
"cocogo/pkg/logger"
"cocogo/pkg/model"
"cocogo/pkg/service"
)
var
(
defaultHomeName
=
"Home"
)
func
NewUserVolume
(
user
*
model
.
User
,
addr
string
)
*
UserVolume
{
rawID
:=
fmt
.
Sprintf
(
"'%s@%s"
,
user
.
Username
,
addr
)
fmt
.
Println
(
rawID
)
uVolume
:=
&
UserVolume
{
Uuid
:
elfinder
.
GenerateID
(
rawID
),
user
:
user
,
Name
:
defaultHomeName
,
basePath
:
fmt
.
Sprintf
(
"/%s"
,
defaultHomeName
),
}
uVolume
.
initial
()
return
uVolume
}
type
UserVolume
struct
{
Uuid
string
Name
string
basePath
string
user
*
model
.
User
assets
model
.
AssetList
rootPath
string
// tmp || home || ~
hosts
map
[
string
]
*
hostnameVolume
localTmpPath
string
}
func
(
u
*
UserVolume
)
initial
()
{
conf
:=
config
.
GetConf
()
u
.
loadAssets
()
u
.
rootPath
=
conf
.
SftpRoot
u
.
localTmpPath
=
filepath
.
Join
(
conf
.
RootPath
,
"data"
,
"tmp"
)
_
=
common
.
EnsureDirExist
(
u
.
localTmpPath
)
u
.
hosts
=
make
(
map
[
string
]
*
hostnameVolume
)
for
i
,
item
:=
range
u
.
assets
{
tmpDir
:=
&
hostnameVolume
{
VID
:
u
.
ID
(),
homePath
:
u
.
basePath
,
hostPath
:
filepath
.
Join
(
u
.
basePath
,
item
.
Hostname
),
asset
:
&
u
.
assets
[
i
],
time
:
time
.
Now
()
.
UTC
(),
}
u
.
hosts
[
item
.
Hostname
]
=
tmpDir
}
}
func
(
u
*
UserVolume
)
loadAssets
()
{
u
.
assets
=
service
.
GetUserAssets
(
u
.
user
.
ID
,
"1"
)
}
func
(
u
*
UserVolume
)
ID
()
string
{
return
u
.
Uuid
}
func
(
u
*
UserVolume
)
Info
(
path
string
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
if
path
==
""
||
path
==
"/"
{
path
=
u
.
basePath
}
if
path
==
u
.
basePath
{
return
u
.
RootFileDir
(),
nil
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
path
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
path
{
return
hostDir
.
info
(),
nil
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
path
==
sysUserDir
.
suPath
{
return
sysUserDir
.
info
(),
nil
}
realPath
:=
sysUserDir
.
ParsePath
(
path
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
dirname
:=
filepath
.
Dir
(
path
)
fileInfos
,
err
:=
sysUserDir
.
client
.
Stat
(
realPath
)
if
err
!=
nil
{
return
rest
,
err
}
rest
.
Name
=
fileInfos
.
Name
()
rest
.
Hash
=
hashPath
(
u
.
ID
(),
path
)
rest
.
Phash
=
hashPath
(
u
.
ID
(),
dirname
)
rest
.
Size
=
fileInfos
.
Size
()
rest
.
Volumeid
=
u
.
ID
()
if
fileInfos
.
IsDir
()
{
rest
.
Mime
=
"directory"
rest
.
Dirs
=
1
}
else
{
rest
.
Mime
=
"file"
rest
.
Dirs
=
0
}
rest
.
Read
,
rest
.
Write
=
elfinder
.
ReadWritePem
(
fileInfos
.
Mode
())
return
rest
,
nil
}
func
(
u
*
UserVolume
)
List
(
path
string
)
[]
elfinder
.
FileDir
{
var
dirs
[]
elfinder
.
FileDir
if
path
==
""
||
path
==
"/"
{
path
=
u
.
basePath
}
if
path
==
u
.
basePath
{
dirs
=
make
([]
elfinder
.
FileDir
,
0
,
len
(
u
.
hosts
))
for
_
,
item
:=
range
u
.
hosts
{
dirs
=
append
(
dirs
,
item
.
info
())
}
return
dirs
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
path
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
dirs
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
if
hostDir
.
hostPath
==
path
{
dirs
=
make
([]
elfinder
.
FileDir
,
0
,
len
(
hostDir
.
suMaps
))
for
_
,
item
:=
range
hostDir
.
suMaps
{
dirs
=
append
(
dirs
,
item
.
info
())
}
return
dirs
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
dirs
}
realPath
:=
sysUserDir
.
ParsePath
(
path
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
dirs
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
subFiles
,
err
:=
sysUserDir
.
client
.
ReadDir
(
realPath
)
if
err
!=
nil
{
return
dirs
}
dirs
=
make
([]
elfinder
.
FileDir
,
0
,
len
(
subFiles
))
for
_
,
fInfo
:=
range
subFiles
{
fileDir
,
err
:=
u
.
Info
(
filepath
.
Join
(
path
,
fInfo
.
Name
()))
if
err
!=
nil
{
continue
}
dirs
=
append
(
dirs
,
fileDir
)
}
return
dirs
}
func
(
u
*
UserVolume
)
Parents
(
path
string
,
dep
int
)
[]
elfinder
.
FileDir
{
relativepath
:=
strings
.
TrimPrefix
(
strings
.
TrimPrefix
(
path
,
u
.
basePath
),
"/"
)
relativePaths
:=
strings
.
Split
(
relativepath
,
"/"
)
dirs
:=
make
([]
elfinder
.
FileDir
,
0
,
len
(
relativePaths
))
for
i
:=
range
relativePaths
{
realDirPath
:=
filepath
.
Join
(
u
.
basePath
,
filepath
.
Join
(
relativePaths
[
:
i
]
...
))
result
,
err
:=
u
.
Info
(
realDirPath
)
if
err
!=
nil
{
continue
}
dirs
=
append
(
dirs
,
result
)
tmpDir
:=
u
.
List
(
realDirPath
)
for
j
,
item
:=
range
tmpDir
{
if
item
.
Dirs
==
1
{
dirs
=
append
(
dirs
,
tmpDir
[
j
])
}
}
}
return
dirs
}
func
(
u
*
UserVolume
)
GetFile
(
path
string
)
(
reader
io
.
ReadCloser
,
err
error
)
{
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
path
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
nil
,
os
.
ErrNotExist
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
nil
,
os
.
ErrNotExist
}
realPath
:=
sysUserDir
.
ParsePath
(
path
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
nil
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
return
sysUserDir
.
client
.
Open
(
realPath
)
}
func
(
u
*
UserVolume
)
UploadFile
(
dir
,
filename
string
,
reader
io
.
Reader
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
var
err
error
if
dir
==
""
||
dir
==
"/"
{
dir
=
u
.
basePath
}
if
dir
==
u
.
basePath
{
return
rest
,
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
dir
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
dir
{
return
rest
,
os
.
ErrPermission
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
realPath
:=
sysUserDir
.
ParsePath
(
dir
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
realFilenamePath
:=
filepath
.
Join
(
realPath
,
filename
)
fd
,
err
:=
sysUserDir
.
client
.
Create
(
realFilenamePath
)
if
err
!=
nil
{
return
rest
,
err
}
defer
fd
.
Close
()
_
,
err
=
io
.
Copy
(
fd
,
reader
)
if
err
!=
nil
{
return
rest
,
err
}
return
u
.
Info
(
filepath
.
Join
(
dir
,
filename
))
}
func
(
u
*
UserVolume
)
UploadChunk
(
cid
int
,
dirPath
,
chunkName
string
,
reader
io
.
Reader
)
error
{
//chunkName format "filename.[NUMBER]_[TOTAL].part"
var
err
error
tmpDir
:=
filepath
.
Join
(
u
.
localTmpPath
,
dirPath
)
err
=
common
.
EnsureDirExist
(
tmpDir
)
if
err
!=
nil
{
return
err
}
chunkRealPath
:=
fmt
.
Sprintf
(
"%s_%d"
,
filepath
.
Join
(
tmpDir
,
chunkName
),
cid
)
fd
,
err
:=
os
.
Create
(
chunkRealPath
)
defer
fd
.
Close
()
if
err
!=
nil
{
return
err
}
_
,
err
=
io
.
Copy
(
fd
,
reader
)
fmt
.
Println
(
err
)
return
err
}
func
(
u
*
UserVolume
)
MergeChunk
(
cid
,
total
int
,
dirPath
,
filename
string
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
if
u
.
basePath
==
dirPath
{
return
rest
,
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
dirPath
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
dirPath
{
return
rest
,
os
.
ErrPermission
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
realDirPath
:=
sysUserDir
.
ParsePath
(
dirPath
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
filenamePath
:=
filepath
.
Join
(
realDirPath
,
filename
)
fd
,
err
:=
sysUserDir
.
client
.
OpenFile
(
filenamePath
,
os
.
O_WRONLY
|
os
.
O_APPEND
|
os
.
O_CREATE
|
os
.
O_TRUNC
)
if
err
!=
nil
{
return
rest
,
err
}
defer
fd
.
Close
()
for
i
:=
0
;
i
<=
total
;
i
++
{
partPath
:=
fmt
.
Sprintf
(
"%s.%d_%d.part_%d"
,
filepath
.
Join
(
u
.
localTmpPath
,
dirPath
,
filename
),
i
,
total
,
cid
)
partFD
,
err
:=
os
.
Open
(
partPath
)
if
err
!=
nil
{
return
rest
,
err
}
_
,
err
=
io
.
Copy
(
fd
,
partFD
)
if
err
!=
nil
{
return
rest
,
os
.
ErrNotExist
}
_
=
partFD
.
Close
()
err
=
os
.
Remove
(
partPath
)
}
return
u
.
Info
(
filepath
.
Join
(
dirPath
,
filename
))
}
func
(
u
*
UserVolume
)
CompleteChunk
(
cid
,
total
int
,
dirPath
,
filename
string
)
bool
{
for
i
:=
0
;
i
<=
total
;
i
++
{
partPath
:=
fmt
.
Sprintf
(
"%s.%d_%d.part_%d"
,
filepath
.
Join
(
u
.
localTmpPath
,
dirPath
,
filename
),
i
,
total
,
cid
)
_
,
err
:=
os
.
Stat
(
partPath
)
if
err
!=
nil
{
return
false
}
}
return
true
}
func
(
u
*
UserVolume
)
MakeDir
(
dir
,
newDirname
string
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
if
dir
==
""
||
dir
==
"/"
{
dir
=
u
.
basePath
}
if
dir
==
u
.
basePath
{
return
rest
,
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
dir
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
dir
{
return
rest
,
os
.
ErrPermission
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
realPath
:=
sysUserDir
.
ParsePath
(
dir
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
realDirPath
:=
filepath
.
Join
(
realPath
,
newDirname
)
err
:=
sysUserDir
.
client
.
MkdirAll
(
realDirPath
)
if
err
!=
nil
{
return
rest
,
err
}
return
u
.
Info
(
filepath
.
Join
(
dir
,
newDirname
))
}
func
(
u
*
UserVolume
)
MakeFile
(
dir
,
newFilename
string
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
if
dir
==
""
||
dir
==
"/"
{
dir
=
u
.
basePath
}
if
dir
==
u
.
basePath
{
return
rest
,
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
dir
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
dir
{
return
rest
,
os
.
ErrPermission
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
realPath
:=
sysUserDir
.
ParsePath
(
dir
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
realFilePath
:=
filepath
.
Join
(
realPath
,
newFilename
)
_
,
err
:=
sysUserDir
.
client
.
Create
(
realFilePath
)
if
err
!=
nil
{
return
rest
,
err
}
return
u
.
Info
(
filepath
.
Join
(
dir
,
newFilename
))
}
func
(
u
*
UserVolume
)
Rename
(
oldNamePath
,
newname
string
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
oldNamePath
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
sysUserDir
.
suPath
==
oldNamePath
{
return
rest
,
os
.
ErrPermission
}
realPath
:=
sysUserDir
.
ParsePath
(
oldNamePath
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
dirpath
:=
filepath
.
Dir
(
realPath
)
newFilePath
:=
filepath
.
Join
(
dirpath
,
newname
)
err
:=
sysUserDir
.
client
.
Rename
(
oldNamePath
,
newFilePath
)
if
err
!=
nil
{
return
rest
,
err
}
return
u
.
Info
(
newFilePath
)
}
func
(
u
*
UserVolume
)
Remove
(
path
string
)
error
{
if
path
==
""
||
path
==
"/"
{
path
=
u
.
basePath
}
if
path
==
u
.
basePath
{
return
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
path
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
os
.
ErrNotExist
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
os
.
ErrNotExist
}
if
sysUserDir
.
suPath
==
path
{
return
os
.
ErrPermission
}
realPath
:=
sysUserDir
.
ParsePath
(
path
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
return
sysUserDir
.
client
.
Remove
(
realPath
)
}
func
(
u
*
UserVolume
)
Paste
(
dir
,
filename
,
suffix
string
,
reader
io
.
ReadCloser
)
(
elfinder
.
FileDir
,
error
)
{
var
rest
elfinder
.
FileDir
if
dir
==
""
||
dir
==
"/"
{
dir
=
u
.
basePath
}
if
dir
==
u
.
basePath
{
return
rest
,
os
.
ErrPermission
}
pathNames
:=
strings
.
Split
(
strings
.
TrimPrefix
(
dir
,
"/"
),
"/"
)
hostDir
,
ok
:=
u
.
hosts
[
pathNames
[
1
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
if
hostDir
.
hostPath
==
dir
{
return
rest
,
os
.
ErrPermission
}
if
hostDir
.
suMaps
==
nil
{
hostDir
.
suMaps
=
make
(
map
[
string
]
*
sysUserVolume
)
systemUsers
:=
hostDir
.
asset
.
SystemUsers
for
i
,
sysUser
:=
range
systemUsers
{
hostDir
.
suMaps
[
sysUser
.
Name
]
=
&
sysUserVolume
{
VID
:
u
.
ID
(),
hostpath
:
hostDir
.
hostPath
,
suPath
:
filepath
.
Join
(
hostDir
.
hostPath
,
sysUser
.
Name
),
systemUser
:
&
systemUsers
[
i
],
rootPath
:
u
.
rootPath
,
}
}
}
sysUserDir
,
ok
:=
hostDir
.
suMaps
[
pathNames
[
2
]]
if
!
ok
{
return
rest
,
os
.
ErrNotExist
}
realPath
:=
sysUserDir
.
ParsePath
(
dir
)
if
sysUserDir
.
client
==
nil
{
sftClient
,
conn
,
err
:=
u
.
GetSftpClient
(
hostDir
.
asset
,
sysUserDir
.
systemUser
)
if
err
!=
nil
{
return
rest
,
os
.
ErrPermission
}
sysUserDir
.
client
=
sftClient
sysUserDir
.
conn
=
conn
}
realFilePath
:=
filepath
.
Join
(
realPath
,
filename
)
_
,
err
:=
sysUserDir
.
client
.
Stat
(
realFilePath
)
if
err
==
nil
{
realPath
+=
suffix
}
fd
,
err
:=
sysUserDir
.
client
.
OpenFile
(
realPath
,
os
.
O_RDWR
|
os
.
O_CREATE
)
if
err
!=
nil
{
return
rest
,
err
}
defer
fd
.
Close
()
_
,
err
=
io
.
Copy
(
fd
,
reader
)
if
err
!=
nil
{
return
rest
,
err
}
return
u
.
Info
(
realPath
)
}
func
(
u
*
UserVolume
)
RootFileDir
()
elfinder
.
FileDir
{
var
resFDir
=
elfinder
.
FileDir
{}
resFDir
.
Name
=
u
.
Name
resFDir
.
Hash
=
hashPath
(
u
.
Uuid
,
u
.
basePath
)
resFDir
.
Mime
=
"directory"
resFDir
.
Volumeid
=
u
.
Uuid
resFDir
.
Dirs
=
1
resFDir
.
Read
,
resFDir
.
Write
=
1
,
1
resFDir
.
Locked
=
1
return
resFDir
}
func
(
u
*
UserVolume
)
GetSftpClient
(
asset
*
model
.
Asset
,
sysUser
*
model
.
SystemUser
)
(
sftpClient
*
sftp
.
Client
,
sshClient
*
gossh
.
Client
,
err
error
)
{
sshClient
,
err
=
srvconn
.
NewClient
(
u
.
user
,
asset
,
sysUser
,
config
.
GetConf
()
.
SSHTimeout
*
time
.
Second
)
if
err
!=
nil
{
return
}
sftpClient
,
err
=
sftp
.
NewClient
(
sshClient
)
if
err
!=
nil
{
return
}
return
sftpClient
,
sshClient
,
nil
}
func
(
u
*
UserVolume
)
Close
()
{
for
_
,
host
:=
range
u
.
hosts
{
if
host
.
suMaps
==
nil
{
continue
}
for
_
,
su
:=
range
host
.
suMaps
{
su
.
Close
()
}
}
}
type
hostnameVolume
struct
{
VID
string
homePath
string
hostPath
string
// /home/hostname/
time
time
.
Time
asset
*
model
.
Asset
suMaps
map
[
string
]
*
sysUserVolume
}
func
(
h
*
hostnameVolume
)
info
()
elfinder
.
FileDir
{
var
resFDir
=
elfinder
.
FileDir
{}
resFDir
.
Name
=
h
.
asset
.
Hostname
resFDir
.
Hash
=
hashPath
(
h
.
VID
,
h
.
hostPath
)
resFDir
.
Phash
=
hashPath
(
h
.
VID
,
h
.
homePath
)
resFDir
.
Mime
=
"directory"
resFDir
.
Volumeid
=
h
.
VID
resFDir
.
Dirs
=
1
resFDir
.
Read
,
resFDir
.
Write
=
1
,
1
return
resFDir
}
type
sysUserVolume
struct
{
VID
string
hostpath
string
suPath
string
rootPath
string
systemUser
*
model
.
SystemUser
client
*
sftp
.
Client
conn
*
gossh
.
Client
}
func
(
su
*
sysUserVolume
)
info
()
elfinder
.
FileDir
{
var
resFDir
=
elfinder
.
FileDir
{}
resFDir
.
Name
=
su
.
systemUser
.
Name
resFDir
.
Hash
=
hashPath
(
su
.
VID
,
su
.
suPath
)
resFDir
.
Phash
=
hashPath
(
su
.
VID
,
su
.
hostpath
)
resFDir
.
Mime
=
"directory"
resFDir
.
Volumeid
=
su
.
VID
resFDir
.
Dirs
=
1
resFDir
.
Read
,
resFDir
.
Write
=
1
,
1
return
resFDir
}
func
(
su
*
sysUserVolume
)
ParsePath
(
path
string
)
string
{
realPath
:=
strings
.
ReplaceAll
(
path
,
su
.
suPath
,
su
.
rootPath
)
logger
.
Debug
(
"real path: "
,
realPath
)
return
realPath
}
func
(
su
*
sysUserVolume
)
Close
()
{
if
su
.
client
!=
nil
{
_
=
su
.
client
.
Close
()
su
.
client
=
nil
}
srvconn
.
RecycleClient
(
su
.
conn
)
}
func
hashPath
(
id
,
path
string
)
string
{
return
elfinder
.
CreateHash
(
id
,
path
)
}
pkg/httpd/volumemanager.go
0 → 100644
View file @
bba9f607
package
httpd
import
(
"sync"
)
var
userVolumes
=
make
(
map
[
string
]
*
UserVolume
)
var
volumeLock
=
new
(
sync
.
RWMutex
)
func
addUserVolume
(
sid
string
,
v
*
UserVolume
)
{
volumeLock
.
Lock
()
defer
volumeLock
.
Unlock
()
userVolumes
[
sid
]
=
v
}
func
removeUserVolume
(
sid
string
)
{
volumeLock
.
RLock
()
v
,
ok
:=
userVolumes
[
sid
]
volumeLock
.
RUnlock
()
if
!
ok
{
return
}
v
.
Close
()
volumeLock
.
Lock
()
delete
(
userVolumes
,
sid
)
volumeLock
.
Unlock
()
}
func
GetUserVolume
(
sid
string
)
(
*
UserVolume
,
bool
)
{
volumeLock
.
RLock
()
defer
volumeLock
.
RUnlock
()
v
,
ok
:=
userVolumes
[
sid
]
return
v
,
ok
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment