diff --git a/common/rpc-service.c b/common/rpc-service.c index 6cafbea..3b216e6 100644 --- a/common/rpc-service.c +++ b/common/rpc-service.c @@ -4643,22 +4643,6 @@ seafile_search_files_by_path (const char *repo_id, const char *path, const char return g_list_reverse (ret); } -char * -seafile_generate_notif_server_jwt (const char *repo_id, const char *username, GError **error) -{ - if (!repo_id || !username) { - g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_BAD_ARGS, "Argument should not be null"); - return NULL; - } - - char *token = seaf_gen_notif_server_jwt (repo_id, username); - if (!token) { - g_set_error (error, SEAFILE_DOMAIN, SEAF_ERR_INTERNAL, - "Failed to generate jwt token"); - } - return token; -} - /*RPC functions merged from ccnet-server*/ int ccnet_rpc_add_emailuser (const char *email, const char *passwd, diff --git a/fileserver/fileop.go b/fileserver/fileop.go index e896fc1..1806aad 100644 --- a/fileserver/fileop.go +++ b/fileserver/fileop.go @@ -30,7 +30,6 @@ import ( "sort" "syscall" - jwt "github.com/golang-jwt/jwt/v5" "github.com/gorilla/mux" "github.com/haiwen/seafile-server/fileserver/blockmgr" "github.com/haiwen/seafile-server/fileserver/commitmgr" @@ -324,19 +323,12 @@ type UserInfo struct { } func checkFileAccess(repoID, token, cookie, filePath, op string) (string, *appError) { - claims := SeahubClaims{ - time.Now().Add(time.Second * 300).Unix(), - true, - jwt.RegisteredClaims{}, - } - - jwtToken := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), &claims) - tokenString, err := jwtToken.SignedString([]byte(seahubPK)) + tokenString, err := utils.GenSeahubJWTToken() if err != nil { err := fmt.Errorf("failed to sign jwt token: %v", err) return "", &appError{err, "", http.StatusInternalServerError} } - url := fmt.Sprintf("%s/repos/%s/check-access/?path=%s", seahubURL, repoID, filePath) + url := fmt.Sprintf("%s/repos/%s/check-access/?path=%s", option.SeahubURL, repoID, filePath) header := map[string][]string{ "Authorization": {"Token " + tokenString}, } @@ -2097,7 +2089,8 @@ func notifRepoUpdate(repoID string, commitID string) error { } url := fmt.Sprintf("http://%s/events", option.NotificationURL) - token, err := genJWTToken(repoID, "") + exp := time.Now().Add(time.Second * 300).Unix() + token, err := utils.GenNotifJWTToken(repoID, "", exp) if err != nil { log.Printf("failed to generate jwt token: %v", err) return err @@ -3631,19 +3624,12 @@ type ShareLinkInfo struct { } func queryShareLinkInfo(token, cookie, opType string) (*ShareLinkInfo, *appError) { - claims := SeahubClaims{ - time.Now().Add(time.Second * 300).Unix(), - true, - jwt.RegisteredClaims{}, - } - - jwtToken := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), &claims) - tokenString, err := jwtToken.SignedString([]byte(seahubPK)) + tokenString, err := utils.GenSeahubJWTToken() if err != nil { err := fmt.Errorf("failed to sign jwt token: %v", err) return nil, &appError{err, "", http.StatusInternalServerError} } - url := fmt.Sprintf("%s?token=%s&type=%s", seahubURL+"/check-share-link-access/", token, opType) + url := fmt.Sprintf("%s?token=%s&type=%s", option.SeahubURL+"/check-share-link-access/", token, opType) header := map[string][]string{ "Authorization": {"Token " + tokenString}, } @@ -3671,7 +3657,7 @@ func queryShareLinkInfo(token, cookie, opType string) (*ShareLinkInfo, *appError } func accessLinkCB(rsp http.ResponseWriter, r *http.Request) *appError { - if seahubPK == "" { + if option.JWTPrivateKey == "" { err := fmt.Errorf("no seahub private key is configured") return &appError{err, "", http.StatusNotFound} } diff --git a/fileserver/fileserver.go b/fileserver/fileserver.go index bbd589d..d2929d8 100644 --- a/fileserver/fileserver.go +++ b/fileserver/fileserver.go @@ -43,7 +43,6 @@ var logFp *os.File var dbType string var seafileDB, ccnetDB *sql.DB -var seahubURL, seahubPK string func init() { flag.StringVar(¢ralDir, "F", "", "central config directory") @@ -264,22 +263,6 @@ func loadSeafileDB() { dbType = dbEngine } -func loadSeahubConfig() error { - seahubPK = os.Getenv("JWT_PRIVATE_KEY") - if seahubPK == "" { - return fmt.Errorf("failed to read JWT_PRIVATE_KEY") - } - - siteRoot := os.Getenv("SITE_ROOT") - if siteRoot != "" { - seahubURL = fmt.Sprintf("http://127.0.0.1:8000%sapi/v2.1/internal", siteRoot) - } else { - seahubURL = "http://127.0.0.1:8000/api/v2.1/internal" - } - - return nil -} - func writePidFile(pid_file_path string) error { file, err := os.OpenFile(pid_file_path, os.O_CREATE|os.O_WRONLY, 0664) if err != nil { @@ -378,7 +361,7 @@ func main() { fp.Close() } - if err := loadSeahubConfig(); err != nil { + if err := option.LoadSeahubConfig(); err != nil { log.Fatalf("Failed to read seahub config: %v", err) } diff --git a/fileserver/merge.go b/fileserver/merge.go index dcd6b48..7c5f8ac 100644 --- a/fileserver/merge.go +++ b/fileserver/merge.go @@ -10,9 +10,9 @@ import ( "strings" "time" - jwt "github.com/golang-jwt/jwt/v5" "github.com/haiwen/seafile-server/fileserver/commitmgr" "github.com/haiwen/seafile-server/fileserver/fsmgr" + "github.com/haiwen/seafile-server/fileserver/option" "github.com/haiwen/seafile-server/fileserver/utils" ) @@ -381,7 +381,7 @@ func getNickNameByModifier(emailToNickname map[string]string, modifier string) s if ok { return nickname } - if seahubPK != "" { + if option.JWTPrivateKey != "" { nickname = postGetNickName(modifier) } @@ -394,25 +394,8 @@ func getNickNameByModifier(emailToNickname map[string]string, modifier string) s return nickname } -type SeahubClaims struct { - Exp int64 - IsInternal bool `json:"is_internal"` - jwt.RegisteredClaims -} - -func (*SeahubClaims) Valid() error { - return nil -} - func postGetNickName(modifier string) string { - claims := SeahubClaims{ - time.Now().Add(time.Second * 300).Unix(), - true, - jwt.RegisteredClaims{}, - } - - token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), &claims) - tokenString, err := token.SignedString([]byte(seahubPK)) + tokenString, err := utils.GenSeahubJWTToken() if err != nil { return "" } @@ -428,7 +411,7 @@ func postGetNickName(modifier string) string { return "" } - url := seahubURL + "/user-list/" + url := option.SeahubURL + "/user-list/" status, body, err := utils.HttpCommon("POST", url, header, bytes.NewReader(data)) if err != nil { return "" diff --git a/fileserver/option/option.go b/fileserver/option/option.go index 9c7ba0b..2593de9 100644 --- a/fileserver/option/option.go +++ b/fileserver/option/option.go @@ -3,6 +3,7 @@ package option import ( "fmt" "log" + "os" "path/filepath" "strconv" "strings" @@ -62,6 +63,10 @@ var ( // DB default timeout DBOpTimeout time.Duration + + // seahub + SeahubURL string + JWTPrivateKey string ) func initDefaultOptions() { @@ -256,3 +261,19 @@ func parseQuota(quotaStr string) int64 { return quota } + +func LoadSeahubConfig() error { + JWTPrivateKey = os.Getenv("JWT_PRIVATE_KEY") + if JWTPrivateKey == "" { + return fmt.Errorf("failed to read JWT_PRIVATE_KEY") + } + + siteRoot := os.Getenv("SITE_ROOT") + if siteRoot != "" { + SeahubURL = fmt.Sprintf("http://127.0.0.1:8000%sapi/v2.1/internal", siteRoot) + } else { + SeahubURL = "http://127.0.0.1:8000/api/v2.1/internal" + } + + return nil +} diff --git a/fileserver/sync_api.go b/fileserver/sync_api.go index c1ef70b..363e040 100644 --- a/fileserver/sync_api.go +++ b/fileserver/sync_api.go @@ -17,7 +17,6 @@ import ( "sync" "time" - jwt "github.com/golang-jwt/jwt/v5" "github.com/gorilla/mux" "github.com/haiwen/seafile-server/fileserver/blockmgr" "github.com/haiwen/seafile-server/fileserver/commitmgr" @@ -726,17 +725,6 @@ func getCheckQuotaCB(rsp http.ResponseWriter, r *http.Request) *appError { return nil } -type MyClaims struct { - Exp int64 - RepoID string `json:"repo_id"` - UserName string `json:"username"` - jwt.RegisteredClaims -} - -func (*MyClaims) Valid() error { - return nil -} - func getJWTTokenCB(rsp http.ResponseWriter, r *http.Request) *appError { vars := mux.Vars(r) repoID := vars["repoid"] @@ -750,7 +738,8 @@ func getJWTTokenCB(rsp http.ResponseWriter, r *http.Request) *appError { return appErr } - tokenString, err := genJWTToken(repoID, user) + exp := time.Now().Add(time.Hour * 72).Unix() + tokenString, err := utils.GenNotifJWTToken(repoID, user, exp) if err != nil { return &appError{err, "", http.StatusInternalServerError} } @@ -762,24 +751,6 @@ func getJWTTokenCB(rsp http.ResponseWriter, r *http.Request) *appError { return nil } -func genJWTToken(repoID, user string) (string, error) { - claims := MyClaims{ - time.Now().Add(time.Hour * 72).Unix(), - repoID, - user, - jwt.RegisteredClaims{}, - } - - token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), &claims) - tokenString, err := token.SignedString([]byte(seahubPK)) - if err != nil { - err := fmt.Errorf("failed to gen jwt token for repo %s", repoID) - return "", err - } - - return tokenString, nil -} - func getFsObjIDCB(rsp http.ResponseWriter, r *http.Request) *appError { recvChan := make(chan *calResult) diff --git a/fileserver/utils/utils.go b/fileserver/utils/utils.go index 34f1ad1..b5da67b 100644 --- a/fileserver/utils/utils.go +++ b/fileserver/utils/utils.go @@ -1,7 +1,12 @@ package utils import ( + "fmt" + "time" + + jwt "github.com/golang-jwt/jwt/v5" "github.com/google/uuid" + "github.com/haiwen/seafile-server/fileserver/option" ) func IsValidUUID(u string) bool { @@ -22,3 +27,55 @@ func IsObjectIDValid(objID string) bool { } return true } + +type SeahubClaims struct { + Exp int64 `json:"exp"` + IsInternal bool `json:"is_internal"` + jwt.RegisteredClaims +} + +func (*SeahubClaims) Valid() error { + return nil +} + +func GenSeahubJWTToken() (string, error) { + claims := new(SeahubClaims) + claims.Exp = time.Now().Add(time.Second * 300).Unix() + claims.IsInternal = true + + token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), claims) + tokenString, err := token.SignedString([]byte(option.JWTPrivateKey)) + if err != nil { + err := fmt.Errorf("failed to gen seahub jwt token: %w", err) + return "", err + } + + return tokenString, nil +} + +type MyClaims struct { + Exp int64 `json:"exp"` + RepoID string `json:"repo_id"` + UserName string `json:"username"` + jwt.RegisteredClaims +} + +func (*MyClaims) Valid() error { + return nil +} + +func GenNotifJWTToken(repoID, user string, exp int64) (string, error) { + claims := new(MyClaims) + claims.Exp = exp + claims.RepoID = repoID + claims.UserName = user + + token := jwt.NewWithClaims(jwt.GetSigningMethod("HS256"), claims) + tokenString, err := token.SignedString([]byte(option.JWTPrivateKey)) + if err != nil { + err := fmt.Errorf("failed to gen jwt token for repo %s: %w", repoID, err) + return "", err + } + + return tokenString, nil +} diff --git a/include/seafile-rpc.h b/include/seafile-rpc.h index acd55e8..0b70da2 100644 --- a/include/seafile-rpc.h +++ b/include/seafile-rpc.h @@ -1155,9 +1155,6 @@ seafile_search_files (const char *repo_id, const char *str, GError **error); GList * seafile_search_files_by_path (const char *repo_id, const char *path, const char *str, GError **error); -char * -seafile_generate_notif_server_jwt (const char *repo_id, const char *username, GError **error); - /*Following is ccnet rpc*/ int ccnet_rpc_add_emailuser (const char *email, const char *passwd, diff --git a/notification-server/client.go b/notification-server/client.go index 93993ca..0fe0fa7 100644 --- a/notification-server/client.go +++ b/notification-server/client.go @@ -40,7 +40,7 @@ type Repo struct { } type myClaims struct { - Exp int64 + Exp int64 `json:"exp"` RepoID string `json:"repo_id"` UserName string `json:"username"` jwt.RegisteredClaims diff --git a/python/seafile/rpcclient.py b/python/seafile/rpcclient.py index fc3cd45..1c0aae2 100644 --- a/python/seafile/rpcclient.py +++ b/python/seafile/rpcclient.py @@ -826,10 +826,6 @@ class SeafServerThreadedRpcClient(NamedPipeClient): def search_files_by_path(self, repo_id, path, search_str): pass - @searpc_func("string", ["string", "string"]) - def generate_notif_server_jwt(self, repo_id, username): - pass - #user management @searpc_func("int", ["string", "string", "int", "int"]) def add_emailuser(self, email, passwd, is_staff, is_active): diff --git a/python/seaserv/api.py b/python/seaserv/api.py index b8fb770..291f9a1 100644 --- a/python/seaserv/api.py +++ b/python/seaserv/api.py @@ -862,9 +862,6 @@ class SeafileAPI(object): def search_files_by_path (self, repo_id, path, search_str): return seafserv_threaded_rpc.search_files_by_path(repo_id, path, search_str) - def gen_notif_server_jwt (self, repo_id, username): - return seafserv_threaded_rpc.generate_notif_server_jwt (repo_id, username) - seafile_api = SeafileAPI() class CcnetAPI(object): diff --git a/server/seaf-server.c b/server/seaf-server.c index 31610f9..6a589cd 100644 --- a/server/seaf-server.c +++ b/server/seaf-server.c @@ -355,11 +355,6 @@ static void start_rpc_service (const char *seafile_dir, "search_files_by_path", searpc_signature_objlist__string_string_string()); - searpc_server_register_function ("seafserv-threaded-rpcserver", - seafile_generate_notif_server_jwt, - "generate_notif_server_jwt", - searpc_signature_string__string_string()); - /* share repo to user */ searpc_server_register_function ("seafserv-threaded-rpcserver", seafile_add_share,