github.com/cs3org/reva/v2@v2.27.7/pkg/siteacc/manager/sitesmanager.go (about)

     1  // Copyright 2018-2020 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package manager
    20  
    21  import (
    22  	"strings"
    23  	"sync"
    24  
    25  	"github.com/cs3org/reva/v2/pkg/siteacc/config"
    26  	"github.com/cs3org/reva/v2/pkg/siteacc/data"
    27  	"github.com/pkg/errors"
    28  	"github.com/rs/zerolog"
    29  )
    30  
    31  // SitesManager is responsible for all sites related tasks.
    32  type SitesManager struct {
    33  	conf *config.Configuration
    34  	log  *zerolog.Logger
    35  
    36  	storage data.Storage
    37  
    38  	sites data.Sites
    39  
    40  	mutex sync.RWMutex
    41  }
    42  
    43  func (mngr *SitesManager) initialize(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) error {
    44  	if conf == nil {
    45  		return errors.Errorf("no configuration provided")
    46  	}
    47  	mngr.conf = conf
    48  
    49  	if log == nil {
    50  		return errors.Errorf("no logger provided")
    51  	}
    52  	mngr.log = log
    53  
    54  	if storage == nil {
    55  		return errors.Errorf("no storage provided")
    56  	}
    57  	mngr.storage = storage
    58  
    59  	mngr.sites = make(data.Sites, 0, 32) // Reserve some space for sites
    60  	mngr.readAllSites()
    61  
    62  	return nil
    63  }
    64  
    65  func (mngr *SitesManager) readAllSites() {
    66  	if sites, err := mngr.storage.ReadSites(); err == nil {
    67  		mngr.sites = *sites
    68  	} else {
    69  		// Just warn when not being able to read sites
    70  		mngr.log.Warn().Err(err).Msg("error while reading sites")
    71  	}
    72  }
    73  
    74  func (mngr *SitesManager) writeAllSites() {
    75  	if err := mngr.storage.WriteSites(&mngr.sites); err != nil {
    76  		// Just warn when not being able to write sites
    77  		mngr.log.Warn().Err(err).Msg("error while writing sites")
    78  	}
    79  }
    80  
    81  // GetSite retrieves the site with the given ID, creating it first if necessary.
    82  func (mngr *SitesManager) GetSite(id string, cloneSite bool) (*data.Site, error) {
    83  	mngr.mutex.RLock()
    84  	defer mngr.mutex.RUnlock()
    85  
    86  	site, err := mngr.getSite(id)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	if cloneSite {
    92  		site = site.Clone(false)
    93  	}
    94  
    95  	return site, nil
    96  }
    97  
    98  // FindSite returns the site specified by the ID if one exists.
    99  func (mngr *SitesManager) FindSite(id string) *data.Site {
   100  	site, _ := mngr.findSite(id)
   101  	return site
   102  }
   103  
   104  // UpdateSite updates the site identified by the site ID; if no such site exists, one will be created first.
   105  func (mngr *SitesManager) UpdateSite(siteData *data.Site) error {
   106  	mngr.mutex.Lock()
   107  	defer mngr.mutex.Unlock()
   108  
   109  	site, err := mngr.getSite(siteData.ID)
   110  	if err != nil {
   111  		return errors.Wrap(err, "site to update not found")
   112  	}
   113  
   114  	if err := site.Update(siteData, mngr.conf.Security.CredentialsPassphrase); err == nil {
   115  		mngr.storage.SiteUpdated(site)
   116  		mngr.writeAllSites()
   117  	} else {
   118  		return errors.Wrap(err, "error while updating site")
   119  	}
   120  
   121  	return nil
   122  }
   123  
   124  // CloneSites retrieves all sites currently stored by cloning the data, thus avoiding race conflicts and making outside modifications impossible.
   125  func (mngr *SitesManager) CloneSites(eraseCredentials bool) data.Sites {
   126  	mngr.mutex.RLock()
   127  	defer mngr.mutex.RUnlock()
   128  
   129  	clones := make(data.Sites, 0, len(mngr.sites))
   130  	for _, site := range mngr.sites {
   131  		clones = append(clones, site.Clone(eraseCredentials))
   132  	}
   133  
   134  	return clones
   135  }
   136  
   137  func (mngr *SitesManager) getSite(id string) (*data.Site, error) {
   138  	site, err := mngr.findSite(id)
   139  	if site == nil {
   140  		site, err = mngr.createSite(id)
   141  	}
   142  	return site, err
   143  }
   144  
   145  func (mngr *SitesManager) createSite(id string) (*data.Site, error) {
   146  	site, err := data.NewSite(id)
   147  	if err != nil {
   148  		return nil, errors.Wrap(err, "error while creating site")
   149  	}
   150  	mngr.sites = append(mngr.sites, site)
   151  	mngr.storage.SiteAdded(site)
   152  	mngr.writeAllSites()
   153  	return site, nil
   154  }
   155  
   156  func (mngr *SitesManager) findSite(id string) (*data.Site, error) {
   157  	if len(id) == 0 {
   158  		return nil, errors.Errorf("no search ID specified")
   159  	}
   160  
   161  	site := mngr.findSiteByPredicate(func(site *data.Site) bool { return strings.EqualFold(site.ID, id) })
   162  	if site != nil {
   163  		return site, nil
   164  	}
   165  
   166  	return nil, errors.Errorf("no site found matching the specified ID")
   167  }
   168  
   169  func (mngr *SitesManager) findSiteByPredicate(predicate func(*data.Site) bool) *data.Site {
   170  	for _, site := range mngr.sites {
   171  		if predicate(site) {
   172  			return site
   173  		}
   174  	}
   175  	return nil
   176  }
   177  
   178  // NewSitesManager creates a new sites manager instance.
   179  func NewSitesManager(storage data.Storage, conf *config.Configuration, log *zerolog.Logger) (*SitesManager, error) {
   180  	mngr := &SitesManager{}
   181  	if err := mngr.initialize(storage, conf, log); err != nil {
   182  		return nil, errors.Wrap(err, "unable to initialize the sites manager")
   183  	}
   184  	return mngr, nil
   185  }