From: Peter Amstutz Date: Thu, 2 Aug 2018 19:35:17 +0000 (-0400) Subject: 13146: Projects shared with me WIP X-Git-Tag: 1.3.0~112^2~6 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/c976171138862577a90b34a5d9d21daac52aefec 13146: Projects shared with me WIP Arvados-DCO-1.1-Signed-off-by: Peter Amstutz --- diff --git a/lib/controller/federation.go b/lib/controller/federation.go index 24b9250531..c610a70ec7 100644 --- a/lib/controller/federation.go +++ b/lib/controller/federation.go @@ -54,6 +54,19 @@ func (h *Handler) proxyRemoteCluster(w http.ResponseWriter, req *http.Request, n h.proxy.Do(w, req, urlOut, client) } +type CurrentUser struct { + Authorization arvados.APIClientAuthorization + UUID string +} + +func (h *Handler) validateAPItoken(req *http.Request, user *CurrentUser) error { + db, err := h.db(req) + if err != nil { + return err + } + return db.QueryRowContext(req.Context(), `SELECT api_client_authorizations.uuid, users.uuid FROM api_client_authorizations JOIN users on api_client_authorizations.user_id=users.id WHERE api_token=$1 AND (expires_at IS NULL OR expires_at > current_timestamp) LIMIT 1`, user.Authorization.APIToken).Scan(&user.Authorization.UUID, &user.UUID) +} + // Extract the auth token supplied in req, and replace it with a // salted token for the remote cluster. func (h *Handler) saltAuthToken(req *http.Request, remote string) error { @@ -82,20 +95,16 @@ func (h *Handler) saltAuthToken(req *http.Request, remote string) error { // If the token exists in our own database, salt it // for the remote. Otherwise, assume it was issued by // the remote, and pass it through unmodified. - db, err := h.db(req) - if err != nil { - return err - } - aca := arvados.APIClientAuthorization{APIToken: creds.Tokens[0]} - err = db.QueryRowContext(req.Context(), `SELECT uuid FROM api_client_authorizations WHERE api_token=$1 AND (expires_at IS NULL OR expires_at > current_timestamp) LIMIT 1`, aca.APIToken).Scan(&aca.UUID) + currentUser := CurrentUser{Authorization: arvados.APIClientAuthorization{APIToken: creds.Tokens[0]}} + err = h.validateAPItoken(req, ¤tUser) if err == sql.ErrNoRows { // Not ours; pass through unmodified. - token = aca.APIToken + token = currentUser.Authorization.APIToken } else if err != nil { return err } else { // Found; make V2 version and salt it. - token, err = auth.SaltToken(aca.TokenV2(), remote) + token, err = auth.SaltToken(currentUser.Authorization.TokenV2(), remote) if err != nil { return err } diff --git a/lib/controller/handler.go b/lib/controller/handler.go index 25799aae9e..caa84a90cd 100644 --- a/lib/controller/handler.go +++ b/lib/controller/handler.go @@ -68,6 +68,7 @@ func (h *Handler) setup() { }) hs := http.NotFoundHandler() hs = prepend(hs, h.proxyRailsAPI) + hs = prepend(hs, h.handleGoAPI) hs = prepend(hs, h.proxyRemoteCluster) mux.Handle("/", hs) h.handlerStack = mux diff --git a/lib/controller/shared.go b/lib/controller/shared.go new file mode 100644 index 0000000000..a816ef736f --- /dev/null +++ b/lib/controller/shared.go @@ -0,0 +1,47 @@ +package controller + +import ( + "database/sql" + "fmt" + "net/http" + + "git.curoverse.com/arvados.git/sdk/go/arvados" + "git.curoverse.com/arvados.git/sdk/go/auth" + "git.curoverse.com/arvados.git/sdk/go/httpserver" +) + +func (h *Handler) groupsShared(w http.ResponseWriter, req *http.Request, currentUser CurrentUser) { + w.Write([]byte(fmt.Sprintf("Hello world %v\n", currentUser.UUID))) +} + +func (h *Handler) handleGoAPI(w http.ResponseWriter, req *http.Request, next http.Handler) { + if req.URL.Path != "/arvados/v1/groups/shared" { + next.ServeHTTP(w, req) + return + } + + // Check token and get user UUID + + creds := auth.NewCredentials() + creds.LoadTokensFromHTTPRequest(req) + + if len(creds.Tokens) == 0 { + httpserver.Error(w, "Not logged in", http.StatusForbidden) + return + } + + currentUser := CurrentUser{Authorization: arvados.APIClientAuthorization{APIToken: creds.Tokens[0]}} + err := h.validateAPItoken(req, ¤tUser) + if err != nil { + if err == sql.ErrNoRows { + httpserver.Error(w, "Not logged in", http.StatusForbidden) + } else { + httpserver.Error(w, err.Error(), http.StatusBadRequest) + } + return + } + + // Handle /arvados/v1/groups/shared + + h.groupsShared(w, req, currentUser) +}