mirror of
https://github.com/haiwen/seafile-server.git
synced 2025-05-08 16:16:32 +00:00
* Support argon2id password hash algo * CI install argon2 deps * Go support argonid algo * RPC add pwd_hash_algo and pwd_hash_params * Support password hash algo * Don't set magic when pwd_hash is set * Fix ci error --------- Co-authored-by: 杨赫然 <heran.yang@seafile.com>
183 lines
4.8 KiB
Go
183 lines
4.8 KiB
Go
// Package commitmgr manages commit objects.
|
|
package commitmgr
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"time"
|
|
|
|
"github.com/haiwen/seafile-server/fileserver/objstore"
|
|
"github.com/haiwen/seafile-server/fileserver/utils"
|
|
)
|
|
|
|
// Commit is a commit object
|
|
type Commit struct {
|
|
CommitID string `json:"commit_id"`
|
|
RepoID string `json:"repo_id"`
|
|
RootID string `json:"root_id"`
|
|
CreatorName string `json:"creator_name,omitempty"`
|
|
CreatorID string `json:"creator"`
|
|
Desc string `json:"description"`
|
|
Ctime int64 `json:"ctime"`
|
|
ParentID String `json:"parent_id"`
|
|
SecondParentID String `json:"second_parent_id"`
|
|
RepoName string `json:"repo_name"`
|
|
RepoDesc string `json:"repo_desc"`
|
|
RepoCategory string `json:"repo_category"`
|
|
DeviceName string `json:"device_name,omitempty"`
|
|
ClientVersion string `json:"client_version,omitempty"`
|
|
Encrypted string `json:"encrypted,omitempty"`
|
|
EncVersion int `json:"enc_version,omitempty"`
|
|
Magic string `json:"magic,omitempty"`
|
|
RandomKey string `json:"key,omitempty"`
|
|
Salt string `json:"salt,omitempty"`
|
|
PwdHash string `json:"pwd_hash,omitempty"`
|
|
PwdHashAlgo string `json:"pwd_hash_algo,omitempty"`
|
|
PwdHashParams string `json:"pwd_hash_params,omitempty"`
|
|
Version int `json:"version,omitempty"`
|
|
Conflict int `json:"conflict,omitempty"`
|
|
NewMerge int `json:"new_merge,omitempty"`
|
|
Repaired int `json:"repaired,omitempty"`
|
|
}
|
|
|
|
var store *objstore.ObjectStore
|
|
|
|
// Init initializes commit manager and creates underlying object store.
|
|
func Init(seafileConfPath string, seafileDataDir string) {
|
|
store = objstore.New(seafileConfPath, seafileDataDir, "commits")
|
|
}
|
|
|
|
// NewCommit initializes a Commit object.
|
|
func NewCommit(repoID, parentID, newRoot, user, desc string) *Commit {
|
|
commit := new(Commit)
|
|
commit.RepoID = repoID
|
|
commit.RootID = newRoot
|
|
commit.Desc = desc
|
|
commit.CreatorName = user
|
|
commit.CreatorID = "0000000000000000000000000000000000000000"
|
|
commit.Ctime = time.Now().Unix()
|
|
commit.CommitID = computeCommitID(commit)
|
|
if parentID != "" {
|
|
commit.ParentID.SetValid(parentID)
|
|
}
|
|
|
|
return commit
|
|
}
|
|
|
|
func computeCommitID(commit *Commit) string {
|
|
hash := sha1.New()
|
|
hash.Write([]byte(commit.RootID))
|
|
hash.Write([]byte(commit.CreatorID))
|
|
hash.Write([]byte(commit.CreatorName))
|
|
hash.Write([]byte(commit.Desc))
|
|
tmpBuf := make([]byte, 8)
|
|
binary.BigEndian.PutUint64(tmpBuf, uint64(commit.Ctime))
|
|
hash.Write(tmpBuf)
|
|
|
|
checkSum := hash.Sum(nil)
|
|
id := hex.EncodeToString(checkSum[:])
|
|
|
|
return id
|
|
}
|
|
|
|
// FromData reads from p and converts JSON-encoded data to commit.
|
|
func (commit *Commit) FromData(p []byte) error {
|
|
err := json.Unmarshal(p, commit)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if !utils.IsValidUUID(commit.RepoID) {
|
|
return fmt.Errorf("repo id %s is invalid", commit.RepoID)
|
|
}
|
|
if !utils.IsObjectIDValid(commit.RootID) {
|
|
return fmt.Errorf("root id %s is invalid", commit.RootID)
|
|
}
|
|
if len(commit.CreatorID) != 40 {
|
|
return fmt.Errorf("creator id %s is invalid", commit.CreatorID)
|
|
}
|
|
if commit.ParentID.Valid && !utils.IsObjectIDValid(commit.ParentID.String) {
|
|
return fmt.Errorf("parent id %s is invalid", commit.ParentID.String)
|
|
}
|
|
if commit.SecondParentID.Valid && !utils.IsObjectIDValid(commit.SecondParentID.String) {
|
|
return fmt.Errorf("second parent id %s is invalid", commit.SecondParentID.String)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ToData converts commit to JSON-encoded data and writes to w.
|
|
func (commit *Commit) ToData(w io.Writer) error {
|
|
jsonstr, err := json.Marshal(commit)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
_, err = w.Write(jsonstr)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ReadRaw reads data in binary format from storage backend.
|
|
func ReadRaw(repoID string, commitID string, w io.Writer) error {
|
|
err := store.Read(repoID, commitID, w)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// WriteRaw writes data in binary format to storage backend.
|
|
func WriteRaw(repoID string, commitID string, r io.Reader) error {
|
|
err := store.Write(repoID, commitID, r, false)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Load commit from storage backend.
|
|
func Load(repoID string, commitID string) (*Commit, error) {
|
|
var buf bytes.Buffer
|
|
commit := new(Commit)
|
|
err := ReadRaw(repoID, commitID, &buf)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
err = commit.FromData(buf.Bytes())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return commit, nil
|
|
}
|
|
|
|
// Save commit to storage backend.
|
|
func Save(commit *Commit) error {
|
|
var buf bytes.Buffer
|
|
err := commit.ToData(&buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = WriteRaw(commit.RepoID, commit.CommitID, &buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return err
|
|
}
|
|
|
|
// Exists checks commit if exists.
|
|
func Exists(repoID string, commitID string) (bool, error) {
|
|
return store.Exists(repoID, commitID)
|
|
}
|