X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/2eaa77dc327c024f2faa3fbd322e7054454b6442..c240206e4fc7dd12bf716b7d8de865c785c1bb60:/services/ws/permission.go diff --git a/services/ws/permission.go b/services/ws/permission.go index 42f7b37433..ac895f80e5 100644 --- a/services/ws/permission.go +++ b/services/ws/permission.go @@ -1,11 +1,17 @@ -package main +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +package ws import ( + "context" "net/http" "net/url" "time" - "git.curoverse.com/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/ctxlog" ) const ( @@ -15,10 +21,10 @@ const ( type permChecker interface { SetToken(token string) - Check(uuid string) (bool, error) + Check(ctx context.Context, uuid string) (bool, error) } -func NewPermChecker(ac arvados.Client) permChecker { +func newPermChecker(ac arvados.Client) permChecker { ac.AuthToken = "" return &cachingPermChecker{ Client: &ac, @@ -36,14 +42,23 @@ type cachingPermChecker struct { *arvados.Client cache map[string]cacheEnt maxCurrent int + + nChecks uint64 + nMisses uint64 + nInvalid uint64 } func (pc *cachingPermChecker) SetToken(token string) { + if pc.Client.AuthToken == token { + return + } pc.Client.AuthToken = token + pc.cache = make(map[string]cacheEnt) } -func (pc *cachingPermChecker) Check(uuid string) (bool, error) { - logger := logger(nil). +func (pc *cachingPermChecker) Check(ctx context.Context, uuid string) (bool, error) { + pc.nChecks++ + logger := ctxlog.FromContext(ctx). WithField("token", pc.Client.AuthToken). WithField("uuid", uuid) pc.tidy() @@ -55,21 +70,20 @@ func (pc *cachingPermChecker) Check(uuid string) (bool, error) { var buf map[string]interface{} path, err := pc.PathForUUID("get", uuid) if err != nil { + pc.nInvalid++ return false, err } + + pc.nMisses++ err = pc.RequestAndDecode(&buf, "GET", path, nil, url.Values{ - "select": {`["uuid"]`}, + "include_trash": {"true"}, + "select": {`["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). + } else if txErr, ok := err.(*arvados.TransactionError); ok && pc.isNotAllowed(txErr.StatusCode) { allowed = false } else { logger.WithError(err).Error("lookup error") @@ -80,6 +94,15 @@ func (pc *cachingPermChecker) Check(uuid string) (bool, error) { return allowed, nil } +func (pc *cachingPermChecker) isNotAllowed(status int) bool { + switch status { + case http.StatusForbidden, http.StatusUnauthorized, http.StatusNotFound: + return true + default: + return false + } +} + func (pc *cachingPermChecker) tidy() { if len(pc.cache) <= pc.maxCurrent*2 { return