Repository: artipie/artipie
Issue: GitHub API quota is drained too fast when authenticating via personal tokens

When using personal GitHub access tokens, the quota is drained very fast, it seems caching is not working.

Changed files:
src/main/java/com/artipie/auth/GithubAuth.java, src/main/java/com/artipie/auth/LoggingAuth.java, src/main/java/com/artipie/auth/AuthFromEnv.java, src/main/java/com/artipie/auth/ChainedAuth.java, src/main/java/com/artipie/auth/AuthFromYaml.java, src/main/java/com/artipie/auth/CachedAuth.java, src/main/java/com/artipie/YamlSettings.java

diff --git a/src/main/java/com/artipie/YamlSettings.java b/src/main/java/com/artipie/YamlSettings.java
index e3cbaeb09..fb1b249af 100644
--- a/src/main/java/com/artipie/YamlSettings.java
+++ b/src/main/java/com/artipie/YamlSettings.java
@@ -29,6 +29,7 @@ import com.artipie.asto.Remaining;
 import com.artipie.asto.Storage;
 import com.artipie.auth.AuthFromEnv;
 import com.artipie.auth.AuthFromYaml;
+import com.artipie.auth.CachedAuth;
 import com.artipie.auth.ChainedAuth;
 import com.artipie.auth.GithubAuth;
 import com.artipie.http.auth.Authentication;
@@ -120,7 +121,7 @@ public final class YamlSettings implements Settings {
                     return auth;
                 }
             ).thenApply(
-                auth -> new ChainedAuth(new GithubAuth(), auth)
+                auth -> new ChainedAuth(new CachedAuth(new GithubAuth()), auth)
             );
         } else if (YamlSettings.hasTypeFile(cred)) {
             res = CompletableFuture.failedFuture(
diff --git a/src/main/java/com/artipie/auth/AuthFromEnv.java b/src/main/java/com/artipie/auth/AuthFromEnv.java
index c6a8c8c0c..26f42418f 100644
--- a/src/main/java/com/artipie/auth/AuthFromEnv.java
+++ b/src/main/java/com/artipie/auth/AuthFromEnv.java
@@ -77,4 +77,9 @@ public final class AuthFromEnv implements Authentication {
         }
         return result;
     }
+
+    @Override
+    public String toString() {
+        return String.format("%s()", this.getClass().getSimpleName());
+    }
 }
diff --git a/src/main/java/com/artipie/auth/AuthFromYaml.java b/src/main/java/com/artipie/auth/AuthFromYaml.java
index b5a68c23b..c4f265709 100644
--- a/src/main/java/com/artipie/auth/AuthFromYaml.java
+++ b/src/main/java/com/artipie/auth/AuthFromYaml.java
@@ -87,6 +87,11 @@ public final class AuthFromYaml implements Authentication {
         return res;
     }
 
+    @Override
+    public String toString() {
+        return String.format("%s()", this.getClass().getSimpleName());
+    }
+
     /**
      * Checks stored password against the given one with type.
      * @param stored Password from settings
diff --git a/src/main/java/com/artipie/auth/CachedAuth.java b/src/main/java/com/artipie/auth/CachedAuth.java
index 5397bd5af..159baee15 100644
--- a/src/main/java/com/artipie/auth/CachedAuth.java
+++ b/src/main/java/com/artipie/auth/CachedAuth.java
@@ -81,4 +81,12 @@ public final class CachedAuth implements Authentication {
     public Optional<String> user(final String username, final String password) {
         return this.cache.computeIfAbsent(username, key -> this.origin.user(key, password));
     }
+
+    @Override
+    public String toString() {
+        return String.format(
+            "%s(origin=%s, size=%d)",
+            this.getClass().getSimpleName(), this.origin, this.cache.size()
+        );
+    }
 }
diff --git a/src/main/java/com/artipie/auth/ChainedAuth.java b/src/main/java/com/artipie/auth/ChainedAuth.java
index 4ca9a9838..40c3733a5 100644
--- a/src/main/java/com/artipie/auth/ChainedAuth.java
+++ b/src/main/java/com/artipie/auth/ChainedAuth.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * Chained authentication provider, composed by multiple
@@ -79,4 +80,13 @@ public final class ChainedAuth implements Authentication {
         }
         return result;
     }
+
+    @Override
+    public String toString() {
+        return String.format(
+            "%s([%s])",
+            this.getClass().getSimpleName(),
+            this.list.stream().map(Object::toString).collect(Collectors.joining(","))
+        );
+    }
 }
diff --git a/src/main/java/com/artipie/auth/GithubAuth.java b/src/main/java/com/artipie/auth/GithubAuth.java
index 1bd721f81..c6868aace 100644
--- a/src/main/java/com/artipie/auth/GithubAuth.java
+++ b/src/main/java/com/artipie/auth/GithubAuth.java
@@ -92,4 +92,9 @@ public final class GithubAuth implements Authentication {
         }
         return result;
     }
+
+    @Override
+    public String toString() {
+        return String.format("%s()", this.getClass().getSimpleName());
+    }
 }
diff --git a/src/main/java/com/artipie/auth/LoggingAuth.java b/src/main/java/com/artipie/auth/LoggingAuth.java
index 6454fef29..a253ec359 100644
--- a/src/main/java/com/artipie/auth/LoggingAuth.java
+++ b/src/main/java/com/artipie/auth/LoggingAuth.java
@@ -67,9 +67,17 @@ public final class LoggingAuth implements Authentication {
     public Optional<String> user(final String username, final String password) {
         final Optional<String> res = this.origin.user(username, password);
         if (res.isEmpty()) {
-            Logger.log(this.level, this.origin, "Failed to authenticate '%s' user", username);
+            Logger.log(
+                this.level, this.origin,
+                "Failed to authenticate '%s' user via %s",
+                username, this.origin
+            );
         } else {
-            Logger.log(this.level, this.origin, "Successfully authenticated '%s' user", username);
+            Logger.log(
+                this.level, this.origin,
+                "Successfully authenticated '%s' user via %s",
+                username, this.origin
+            );
         }
         return res;
     }