Repository: codenotary/immudb
File: pkg/auth/tokenkeys.go (Go)

Code before:
	sync.RWMutex
}{
	keysPerUser:      map[string]*tokenKeyPair{},
	lastEvictedAt:    time.Unix(0, 0),
	minEvictInterval: 1 * time.Hour,
}

func generateKeys(Username string) error {
	publicKey, privateKey, err := ed25519.GenerateKey(nil)
	if err != nil {
		return fmt.Errorf(
			"error generating public and private key pair for user %s: %v",
			Username, err)
	}
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	tokenKeyPairs.keysPerUser[Username] =
		&tokenKeyPair{publicKey, privateKey, time.Now()}
	return nil
}

func updateLastTokenGeneratedAt(Username string) {
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	tokenKeyPairs.keysPerUser[Username].lastTokenGeneratedAt = time.Now()
}

func evictOldTokenKeyPairs() {
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	// 1 public key = 32B, 1 private key = 64B =>
	// 10_000 key pairs = (32 + 64) * 10_000 = 960_000B which is close to 1MB
	// if storing keys requires less memory than that, skip eviction
	if len(tokenKeyPairs.keysPerUser) < 10_000 {
		return
	}

	now := time.Now()
	if now.Before(tokenKeyPairs.lastEvictedAt.Add(tokenKeyPairs.minEvictInterval)) {
		return
	}
	for k, v := range tokenKeyPairs.keysPerUser {
		// - keys are used to generate tokens during login (and to verify them during any call with auth)
		// - if no token was generated with a key during the last 3 days, the user would have to login
		//   again anyway (tokens expire in a much shorter time than that), so we just evict the key
		//   (if user logins again, a new pair will be generated and used from that point on)
		if now.Before(v.lastTokenGeneratedAt.Add(3 * 24 * time.Hour)) {
			continue
		}
		delete(tokenKeyPairs.keysPerUser, k)
	}

Review comment (suggestion):
```suggestion
	return tokenKeyPairs.keysPerUser[Username]
```

Code after:
	sync.RWMutex
}{
	keysPerUser:      map[string]*tokenKeyPair{},
	lastEvictedAt:    time.Unix(0, 0),
	minEvictInterval: 1 * time.Hour,
}

func generateKeys(Username string) error {
	publicKey, privateKey, err := ed25519.GenerateKey(nil)
	if err != nil {
		return fmt.Errorf(
			"error generating public and private key pair for user %s: %v",
			Username, err)
	}
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	tokenKeyPairs.keysPerUser[Username] =
		&tokenKeyPair{publicKey, privateKey, time.Now()}
	return nil
}

func getTokenForUser(Username string) (*tokenKeyPair, bool) {
	tokenKeyPairs.RLock()
	defer tokenKeyPairs.RUnlock()
	kp, ok := tokenKeyPairs.keysPerUser[Username]
	return kp, ok
}

func updateLastTokenGeneratedAt(Username string) {
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	tokenKeyPairs.keysPerUser[Username].lastTokenGeneratedAt = time.Now()
}

func evictOldTokenKeyPairs() {
	tokenKeyPairs.Lock()
	defer tokenKeyPairs.Unlock()
	// 1 public key = 32B, 1 private key = 64B =>
	// 10_000 key pairs = (32 + 64) * 10_000 = 960_000B which is close to 1MB
	// if storing keys requires less memory than that, skip eviction
	if len(tokenKeyPairs.keysPerUser) < 10_000 {
		return
	}

	now := time.Now()
	if now.Before(tokenKeyPairs.lastEvictedAt.Add(tokenKeyPairs.minEvictInterval)) {
		return
	}
	for k, v := range tokenKeyPairs.keysPerUser {
		// - keys are used to generate tokens during login (and to verify them during any call with auth)
		// - if no token was generated with a key during the last 3 days, the user would have to login