github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/instance/service.go (about)

     1  package instance
     2  
     3  import (
     4  	"encoding/json"
     5  
     6  	"github.com/cozy/cozy-stack/pkg/couchdb"
     7  	"github.com/cozy/cozy-stack/pkg/crypto"
     8  	"github.com/cozy/cozy-stack/pkg/logger"
     9  	"github.com/cozy/cozy-stack/pkg/prefixer"
    10  )
    11  
    12  type InstanceService struct {
    13  	logger logger.Logger
    14  }
    15  
    16  func NewService(logger logger.Logger) *InstanceService {
    17  	return &InstanceService{
    18  		logger: logger,
    19  	}
    20  }
    21  
    22  // Get finds an instance from its domain by using CouchDB.
    23  func (s *InstanceService) Get(domain string) (*Instance, error) {
    24  	var res couchdb.ViewResponse
    25  	err := couchdb.ExecView(prefixer.GlobalPrefixer, couchdb.DomainAndAliasesView, &couchdb.ViewRequest{
    26  		Key:         domain,
    27  		IncludeDocs: true,
    28  		Limit:       1,
    29  	}, &res)
    30  	if couchdb.IsNoDatabaseError(err) {
    31  		return nil, ErrNotFound
    32  	}
    33  
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  
    38  	if len(res.Rows) == 0 {
    39  		return nil, ErrNotFound
    40  	}
    41  
    42  	inst := &Instance{}
    43  	err = json.Unmarshal(res.Rows[0].Doc, inst)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  
    48  	if err = inst.MakeVFS(); err != nil {
    49  		return nil, err
    50  	}
    51  
    52  	return inst, nil
    53  }
    54  
    55  // Update saves the changes in CouchDB.
    56  func (s *InstanceService) Update(inst *Instance) error {
    57  	return couchdb.UpdateDoc(prefixer.GlobalPrefixer, inst)
    58  }
    59  
    60  // Delete removes the instance document in CouchDB.
    61  func (s *InstanceService) Delete(inst *Instance) error {
    62  	return couchdb.DeleteDoc(prefixer.GlobalPrefixer, inst)
    63  }
    64  
    65  // CheckPassphrase confirm an instance password
    66  func (s *InstanceService) CheckPassphrase(inst *Instance, pass []byte) error {
    67  	if len(pass) == 0 {
    68  		return ErrMissingPassphrase
    69  	}
    70  
    71  	needUpdate, err := crypto.CompareHashAndPassphrase(inst.PassphraseHash, pass)
    72  	if err != nil {
    73  		return err
    74  	}
    75  
    76  	if !needUpdate {
    77  		return nil
    78  	}
    79  
    80  	newHash, err := crypto.GenerateFromPassphrase(pass)
    81  	if err != nil {
    82  		return err
    83  	}
    84  
    85  	inst.PassphraseHash = newHash
    86  	if err = s.Update(inst); err != nil {
    87  		s.logger.WithDomain(inst.Domain).Errorf("Failed to update hash in db: %s", err)
    88  	}
    89  	return nil
    90  }