feat(multi-home): enable separated home dir for each user (#64)
* feat(files): make files service supporting home dir * fix(files): add path access control and avoid redirecting path in the backend * feat(files): add ListHome API * fix(server): fix access control issues * feat(client/web): support multi-home * feat(server): cleanup * fix(server): failed to init admin folder
This commit is contained in:
parent
9748d0cab4
commit
81da97650b
18 changed files with 527 additions and 212 deletions
|
@ -10,15 +10,17 @@ import (
|
|||
)
|
||||
|
||||
type FilesClient struct {
|
||||
addr string
|
||||
r *gorequest.SuperAgent
|
||||
addr string
|
||||
r *gorequest.SuperAgent
|
||||
token *http.Cookie
|
||||
}
|
||||
|
||||
func NewFilesClient(addr string) *FilesClient {
|
||||
func NewFilesClient(addr string, token *http.Cookie) *FilesClient {
|
||||
gr := gorequest.New()
|
||||
return &FilesClient{
|
||||
addr: addr,
|
||||
r: gr,
|
||||
addr: addr,
|
||||
r: gr,
|
||||
token: token,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -28,6 +30,7 @@ func (cl *FilesClient) url(urlpath string) string {
|
|||
|
||||
func (cl *FilesClient) Create(filepath string, size int64) (*http.Response, string, []error) {
|
||||
return cl.r.Post(cl.url("/v1/fs/files")).
|
||||
AddCookie(cl.token).
|
||||
Send(fileshdr.CreateReq{
|
||||
Path: filepath,
|
||||
FileSize: size,
|
||||
|
@ -37,12 +40,14 @@ func (cl *FilesClient) Create(filepath string, size int64) (*http.Response, stri
|
|||
|
||||
func (cl *FilesClient) Delete(filepath string) (*http.Response, string, []error) {
|
||||
return cl.r.Delete(cl.url("/v1/fs/files")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.FilePathQuery, filepath).
|
||||
End()
|
||||
}
|
||||
|
||||
func (cl *FilesClient) Metadata(filepath string) (*http.Response, *fileshdr.MetadataResp, []error) {
|
||||
resp, body, errs := cl.r.Get(cl.url("/v1/fs/metadata")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.FilePathQuery, filepath).
|
||||
End()
|
||||
|
||||
|
@ -57,12 +62,14 @@ func (cl *FilesClient) Metadata(filepath string) (*http.Response, *fileshdr.Meta
|
|||
|
||||
func (cl *FilesClient) Mkdir(dirpath string) (*http.Response, string, []error) {
|
||||
return cl.r.Post(cl.url("/v1/fs/dirs")).
|
||||
AddCookie(cl.token).
|
||||
Send(fileshdr.MkdirReq{Path: dirpath}).
|
||||
End()
|
||||
}
|
||||
|
||||
func (cl *FilesClient) Move(oldpath, newpath string) (*http.Response, string, []error) {
|
||||
return cl.r.Patch(cl.url("/v1/fs/files/move")).
|
||||
AddCookie(cl.token).
|
||||
Send(fileshdr.MoveReq{
|
||||
OldPath: oldpath,
|
||||
NewPath: newpath,
|
||||
|
@ -72,6 +79,7 @@ func (cl *FilesClient) Move(oldpath, newpath string) (*http.Response, string, []
|
|||
|
||||
func (cl *FilesClient) UploadChunk(filepath string, content string, offset int64) (*http.Response, string, []error) {
|
||||
return cl.r.Patch(cl.url("/v1/fs/files/chunks")).
|
||||
AddCookie(cl.token).
|
||||
Send(fileshdr.UploadChunkReq{
|
||||
Path: filepath,
|
||||
Content: content,
|
||||
|
@ -82,6 +90,7 @@ func (cl *FilesClient) UploadChunk(filepath string, content string, offset int64
|
|||
|
||||
func (cl *FilesClient) UploadStatus(filepath string) (*http.Response, *fileshdr.UploadStatusResp, []error) {
|
||||
resp, body, errs := cl.r.Get(cl.url("/v1/fs/files/chunks")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.FilePathQuery, filepath).
|
||||
End()
|
||||
|
||||
|
@ -96,6 +105,7 @@ func (cl *FilesClient) UploadStatus(filepath string) (*http.Response, *fileshdr.
|
|||
|
||||
func (cl *FilesClient) Download(filepath string, headers map[string]string) (*http.Response, string, []error) {
|
||||
r := cl.r.Get(cl.url("/v1/fs/files")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.FilePathQuery, filepath)
|
||||
for key, val := range headers {
|
||||
r = r.Set(key, val)
|
||||
|
@ -105,6 +115,7 @@ func (cl *FilesClient) Download(filepath string, headers map[string]string) (*ht
|
|||
|
||||
func (cl *FilesClient) List(dirPath string) (*http.Response, *fileshdr.ListResp, []error) {
|
||||
resp, body, errs := cl.r.Get(cl.url("/v1/fs/dirs")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.ListDirQuery, dirPath).
|
||||
End()
|
||||
if len(errs) > 0 {
|
||||
|
@ -121,6 +132,7 @@ func (cl *FilesClient) List(dirPath string) (*http.Response, *fileshdr.ListResp,
|
|||
|
||||
func (cl *FilesClient) ListUploadings() (*http.Response, *fileshdr.ListUploadingsResp, []error) {
|
||||
resp, body, errs := cl.r.Get(cl.url("/v1/fs/uploadings")).
|
||||
AddCookie(cl.token).
|
||||
End()
|
||||
if len(errs) > 0 {
|
||||
return nil, nil, errs
|
||||
|
@ -136,6 +148,7 @@ func (cl *FilesClient) ListUploadings() (*http.Response, *fileshdr.ListUploading
|
|||
|
||||
func (cl *FilesClient) DelUploading(filepath string) (*http.Response, string, []error) {
|
||||
return cl.r.Delete(cl.url("/v1/fs/uploadings")).
|
||||
AddCookie(cl.token).
|
||||
Param(fileshdr.FilePathQuery, filepath).
|
||||
End()
|
||||
}
|
||||
|
|
|
@ -136,6 +136,14 @@ export class FilesClient extends BaseClient {
|
|||
});
|
||||
};
|
||||
|
||||
listHome = (): Promise<Response<ListResp>> => {
|
||||
return this.do({
|
||||
method: "get",
|
||||
url: `${this.url}/v1/fs/dirs/home`,
|
||||
params: {},
|
||||
});
|
||||
};
|
||||
|
||||
listUploadings = (): Promise<Response<ListUploadingsResp>> => {
|
||||
return this.do({
|
||||
method: "get",
|
||||
|
|
|
@ -19,6 +19,7 @@ export class FilesClient {
|
|||
private uploadStatusMockResps: Array<Promise<Response<UploadStatusResp>>>;
|
||||
private uploadStatusMockRespID: number = 0;
|
||||
private listMockResp: Promise<Response<ListResp>>;
|
||||
private listHomeMockResp: Promise<Response<ListResp>>;
|
||||
private listUploadingsMockResp: Promise<Response<ListUploadingsResp>>;
|
||||
private deleteUploadingMockResp: Promise<Response>;
|
||||
|
||||
|
@ -58,6 +59,10 @@ export class FilesClient {
|
|||
this.listMockResp = resp;
|
||||
};
|
||||
|
||||
listHomeMock = (resp: Promise<Response<ListResp>>) => {
|
||||
this.listMockResp = resp;
|
||||
};
|
||||
|
||||
listUploadingsMock = (resp: Promise<Response<ListUploadingsResp>>) => {
|
||||
this.listUploadingsMockResp = resp;
|
||||
}
|
||||
|
@ -111,6 +116,10 @@ export class FilesClient {
|
|||
return this.listMockResp;
|
||||
};
|
||||
|
||||
listHome = (): Promise<Response<ListResp>> => {
|
||||
return this.listHomeMockResp;
|
||||
};
|
||||
|
||||
listUploadings = (): Promise<Response<ListUploadingsResp>> => {
|
||||
return this.listUploadingsMockResp;
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface UploadStatusResp {
|
|||
}
|
||||
|
||||
export interface ListResp {
|
||||
cwd: string;
|
||||
metadatas: MetadataResp[];
|
||||
}
|
||||
|
||||
|
@ -50,6 +51,7 @@ export interface IFilesClient {
|
|||
) => Promise<Response<UploadStatusResp>>;
|
||||
uploadStatus: (filePath: string) => Promise<Response<UploadStatusResp>>;
|
||||
list: (dirPath: string) => Promise<Response<ListResp>>;
|
||||
listHome: () => Promise<Response<ListResp>>;
|
||||
listUploadings: () => Promise<Response<ListUploadingsResp>>;
|
||||
deleteUploading: (filePath: string) => Promise<Response>;
|
||||
}
|
||||
|
|
|
@ -114,6 +114,27 @@ export class Updater {
|
|||
: this.props.items;
|
||||
};
|
||||
|
||||
setHomeItems = async (): Promise<void> => {
|
||||
const listResp = await this.filesClient.listHome();
|
||||
|
||||
this.props.dirPath = List<string>(listResp.data.cwd.split("/"));
|
||||
this.props.items =
|
||||
listResp.status === 200
|
||||
? List<MetadataResp>(listResp.data.metadatas)
|
||||
: this.props.items;
|
||||
};
|
||||
|
||||
goHome = async (): Promise<void> => {
|
||||
const listResp = await this.filesClient.listHome();
|
||||
|
||||
// how to get current dir? to dirPath?
|
||||
// this.props.dirPath = dirParts;
|
||||
this.props.items =
|
||||
listResp.status === 200
|
||||
? List<MetadataResp>(listResp.data.metadatas)
|
||||
: this.props.items;
|
||||
};
|
||||
|
||||
moveHere = async (
|
||||
srcDir: string,
|
||||
dstDir: string,
|
||||
|
|
|
@ -104,9 +104,7 @@ export class AuthPane extends React.Component<Props, State, {}> {
|
|||
this.update(PanesUpdater.updateState);
|
||||
|
||||
// refresh
|
||||
return BrowserUpdater().setItems(
|
||||
List<string>(["."])
|
||||
);
|
||||
return BrowserUpdater().setHomeItems();
|
||||
} else {
|
||||
this.setState({ user: "", pwd: "" });
|
||||
alert("Failed to login.");
|
||||
|
|
|
@ -20,7 +20,7 @@ export class StateMgr extends React.Component<Props, State, {}> {
|
|||
BrowserUpdater().init(state.panel.browser);
|
||||
BrowserUpdater().setClients(new UsersClient(""), new FilesClient(""));
|
||||
BrowserUpdater()
|
||||
.setItems(state.panel.browser.dirPath)
|
||||
.setHomeItems()
|
||||
.then(() => {
|
||||
return BrowserUpdater().refreshUploadings();
|
||||
})
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue