Example #1
0
// GetOrCreateTimestamp returns the current timestamp for the gun. This may mean
// a new timestamp is generated either because none exists, or because the current
// one has expired. Once generated, the timestamp is saved in the store.
// Additionally, if we had to generate a new snapshot for this timestamp,
// it is also saved in the store
func GetOrCreateTimestamp(gun string, store storage.MetaStore, cryptoService signed.CryptoService) (
	*time.Time, []byte, error) {

	updates := []storage.MetaUpdate{}

	lastModified, timestampJSON, err := store.GetCurrent(gun, data.CanonicalTimestampRole)
	if err != nil {
		logrus.Debug("error retrieving timestamp: ", err.Error())
		return nil, nil, err
	}

	prev := &data.SignedTimestamp{}
	if err := json.Unmarshal(timestampJSON, prev); err != nil {
		logrus.Error("Failed to unmarshal existing timestamp")
		return nil, nil, err
	}
	snapChecksums, err := prev.GetSnapshot()
	if err != nil || snapChecksums == nil {
		return nil, nil, err
	}
	snapshotSha256Bytes, ok := snapChecksums.Hashes[notary.SHA256]
	if !ok {
		return nil, nil, data.ErrMissingMeta{Role: data.CanonicalSnapshotRole}
	}
	snapshotSha256Hex := hex.EncodeToString(snapshotSha256Bytes[:])
	snapshotTime, snapshot, err := snapshot.GetOrCreateSnapshot(gun, snapshotSha256Hex, store, cryptoService)
	if err != nil {
		logrus.Debug("Previous timestamp, but no valid snapshot for GUN ", gun)
		return nil, nil, err
	}
	snapshotRole := &data.SignedSnapshot{}
	if err := json.Unmarshal(snapshot, snapshotRole); err != nil {
		logrus.Error("Failed to unmarshal retrieved snapshot")
		return nil, nil, err
	}

	// If the snapshot was generated, we should write it with the timestamp
	if snapshotTime == nil {
		updates = append(updates, storage.MetaUpdate{Role: data.CanonicalSnapshotRole, Version: snapshotRole.Signed.Version, Data: snapshot})
	}

	if !timestampExpired(prev) && !snapshotExpired(prev, snapshot) {
		return lastModified, timestampJSON, nil
	}

	tsUpdate, err := createTimestamp(gun, prev, snapshot, store, cryptoService)
	if err != nil {
		logrus.Error("Failed to create a new timestamp")
		return nil, nil, err
	}
	updates = append(updates, *tsUpdate)

	c := time.Now()

	// Write the timestamp, and potentially snapshot
	if err = store.UpdateMany(gun, updates); err != nil {
		return nil, nil, err
	}
	return &c, tsUpdate.Data, nil
}