X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/0f2a62815c97a47b610b76a748a7d092c89e3e7b..57170c25230cf56c99c5b2cbc795f4599cbda87f:/services/ws/permission.go diff --git a/services/ws/permission.go b/services/ws/permission.go index b2b962c7ce..e467e06720 100644 --- a/services/ws/permission.go +++ b/services/ws/permission.go @@ -18,18 +18,23 @@ type permChecker interface { Check(uuid string) (bool, error) } -func NewPermChecker(ac arvados.Client) permChecker { +func newPermChecker(ac arvados.Client) permChecker { ac.AuthToken = "" return &cachingPermChecker{ Client: &ac, - cache: make(map[string]time.Time), + cache: make(map[string]cacheEnt), maxCurrent: 16, } } +type cacheEnt struct { + time.Time + allowed bool +} + type cachingPermChecker struct { *arvados.Client - cache map[string]time.Time + cache map[string]cacheEnt maxCurrent int } @@ -38,10 +43,14 @@ func (pc *cachingPermChecker) SetToken(token string) { } func (pc *cachingPermChecker) Check(uuid string) (bool, error) { + logger := logger(nil). + WithField("token", pc.Client.AuthToken). + WithField("uuid", uuid) pc.tidy() - if t, ok := pc.cache[uuid]; ok && time.Now().Sub(t) < maxPermCacheAge { - debugLogf("perm ok (cached): %+q %+q", pc.Client.AuthToken, uuid) - return true, nil + now := time.Now() + if perm, ok := pc.cache[uuid]; ok && now.Sub(perm.Time) < maxPermCacheAge { + logger.WithField("allowed", perm.allowed).Debug("cache hit") + return perm.allowed, nil } var buf map[string]interface{} path, err := pc.PathForUUID("get", uuid) @@ -51,17 +60,24 @@ func (pc *cachingPermChecker) Check(uuid string) (bool, error) { err = pc.RequestAndDecode(&buf, "GET", path, nil, url.Values{ "select": {`["uuid"]`}, }) - if err, ok := err.(arvados.TransactionError); ok && err.StatusCode == http.StatusNotFound { - debugLogf("perm err: %+q %+q: %s", pc.Client.AuthToken, uuid, err) - return false, nil - } - if err != nil { - debugLogf("perm !ok: %+q %+q", pc.Client.AuthToken, uuid) + + var allowed bool + if err == nil { + allowed = true + } else if txErr, ok := err.(*arvados.TransactionError); ok && txErr.StatusCode == http.StatusNotFound { + allowed = false + } else if txErr.StatusCode == http.StatusForbidden { + // Some requests are expressly forbidden for reasons + // other than "you aren't allowed to know whether this + // UUID exists" (404). + allowed = false + } else { + logger.WithError(err).Error("lookup error") return false, err } - debugLogf("perm ok: %+q %+q", pc.Client.AuthToken, uuid) - pc.cache[uuid] = time.Now() - return true, nil + logger.WithField("allowed", allowed).Debug("cache miss") + pc.cache[uuid] = cacheEnt{Time: now, allowed: allowed} + return allowed, nil } func (pc *cachingPermChecker) tidy() {