github.com/rpdict/ponzu@v0.10.1-0.20190226054626-477f29d6bf5e/system/db/init.go (about)

     1  // Package db contains all interfaces to the databases used by Ponzu, including
     2  // exported functions to easily manage addons, users, indices, search, content,
     3  // and configuration.
     4  package db
     5  
     6  import (
     7  	"log"
     8  
     9  	"github.com/rpdict/ponzu/system/item"
    10  	"github.com/rpdict/ponzu/system/search"
    11  
    12  	"github.com/boltdb/bolt"
    13  	"github.com/nilslice/jwt"
    14  )
    15  
    16  var (
    17  	store *bolt.DB
    18  
    19  	buckets = []string{
    20  		"__config", "__users",
    21  		"__addons", "__uploads",
    22  		"__contentIndex",
    23  	}
    24  
    25  	bucketsToAdd []string
    26  )
    27  
    28  // Store provides access to the underlying *bolt.DB store
    29  func Store() *bolt.DB {
    30  	return store
    31  }
    32  
    33  // Close exports the abillity to close our db file. Should be called with defer
    34  // after call to Init() from the same place.
    35  func Close() {
    36  	err := store.Close()
    37  	if err != nil {
    38  		log.Println(err)
    39  	}
    40  }
    41  
    42  // Init creates a db connection, initializes db with required info, sets secrets
    43  func Init() {
    44  	if store != nil {
    45  		return
    46  	}
    47  
    48  	var err error
    49  	store, err = bolt.Open("system.db", 0666, nil)
    50  	if err != nil {
    51  		log.Fatalln(err)
    52  	}
    53  
    54  	err = store.Update(func(tx *bolt.Tx) error {
    55  		// initialize db with all content type buckets & sorted bucket for type
    56  		for t := range item.Types {
    57  			_, err := tx.CreateBucketIfNotExists([]byte(t))
    58  			if err != nil {
    59  				return err
    60  			}
    61  
    62  			_, err = tx.CreateBucketIfNotExists([]byte(t + "__sorted"))
    63  			if err != nil {
    64  				return err
    65  			}
    66  		}
    67  
    68  		// init db with other buckets as needed
    69  		buckets = append(buckets, bucketsToAdd...)
    70  
    71  		for _, name := range buckets {
    72  			_, err := tx.CreateBucketIfNotExists([]byte(name))
    73  			if err != nil {
    74  				return err
    75  			}
    76  		}
    77  
    78  		return nil
    79  	})
    80  	if err != nil {
    81  		log.Fatalln("Coudn't initialize db with buckets.", err)
    82  	}
    83  
    84  	err = LoadCacheConfig()
    85  	if err != nil {
    86  		log.Fatalln("Failed to load config cache.", err)
    87  	}
    88  
    89  	clientSecret := ConfigCache("client_secret").(string)
    90  
    91  	if clientSecret != "" {
    92  		jwt.Secret([]byte(clientSecret))
    93  	}
    94  
    95  	// invalidate cache on system start
    96  	err = InvalidateCache()
    97  	if err != nil {
    98  		log.Fatalln("Failed to invalidate cache.", err)
    99  	}
   100  }
   101  
   102  // AddBucket adds a bucket to be created if it doesn't already exist
   103  func AddBucket(name string) {
   104  	bucketsToAdd = append(bucketsToAdd, name)
   105  }
   106  
   107  // InitSearchIndex initializes Search Index for search to be functional
   108  // This was moved out of db.Init and put to main(), because addon checker was initializing db together with
   109  // search indexing initialisation in time when there were no item.Types defined so search index was always
   110  // empty when using addons. We still have no guarentee whatsoever that item.Types is defined
   111  // Should be called from a goroutine after SetContent is successful (SortContent requirement)
   112  func InitSearchIndex() {
   113  	for t := range item.Types {
   114  		err := search.MapIndex(t)
   115  		if err != nil {
   116  			log.Fatalln(err)
   117  			return
   118  		}
   119  		SortContent(t)
   120  	}
   121  }
   122  
   123  // SystemInitComplete checks if there is at least 1 admin user in the db which
   124  // would indicate that the system has been configured to the minimum required.
   125  func SystemInitComplete() bool {
   126  	complete := false
   127  
   128  	err := store.View(func(tx *bolt.Tx) error {
   129  		users := tx.Bucket([]byte("__users"))
   130  		if users == nil {
   131  			return bolt.ErrBucketNotFound
   132  		}
   133  
   134  		err := users.ForEach(func(k, v []byte) error {
   135  			complete = true
   136  			return nil
   137  		})
   138  		if err != nil {
   139  			return err
   140  		}
   141  
   142  		return nil
   143  	})
   144  	if err != nil {
   145  		complete = false
   146  		log.Fatalln(err)
   147  	}
   148  
   149  	return complete
   150  }