github.com/stolowski/snapd@v0.0.0-20210407085831-115137ce5a22/store/userinfo_test.go (about)

     1  // -*- Mode: Go; indent-tabs-mode: t -*-
     2  
     3  /*
     4   * Copyright (C) 2016 Canonical Ltd
     5   *
     6   * This program is free software: you can redistribute it and/or modify
     7   * it under the terms of the GNU General Public License version 3 as
     8   * published by the Free Software Foundation.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package store_test
    21  
    22  import (
    23  	"fmt"
    24  	"net/http"
    25  	"net/http/httptest"
    26  	"os"
    27  	"time"
    28  
    29  	"gopkg.in/check.v1"
    30  	"gopkg.in/retry.v1"
    31  
    32  	"github.com/snapcore/snapd/logger"
    33  	"github.com/snapcore/snapd/store"
    34  	"github.com/snapcore/snapd/testutil"
    35  )
    36  
    37  type userInfoSuite struct {
    38  	testutil.BaseTest
    39  
    40  	store         *store.Store
    41  	restoreLogger func()
    42  }
    43  
    44  var _ = check.Suite(&userInfoSuite{})
    45  
    46  // obtained via:
    47  //  `curl https://login.staging.ubuntu.com/api/v2/keys/mvo@ubuntu.com`
    48  //  `curl https://login.staging.ubuntu.com/api/v2/keys/xDPXBdB`
    49  var mockServerJSON = `{
    50      "username": "mvo",
    51      "ssh_keys": [
    52          "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAqwsTkky+laeukWyGFmtiAQUFgjD+wKYuRtOj11gjTe3qUNDgMR54W8IUELZ6NwNWs2wium+jQZLY4vlsDq4PkYK8J2qgjRZURCKp4JbjbVNSg2WO7vDtl+0FIC1GaCdglRVWffrwKN1RLlwqBCVXi01nnTk3+hEpWddjqoTXMwM= egon@top",
    53          "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKBFmfD1KNULZv35907+ArIfxdGGzF1XCQj287AgK7k5GWcEdnUQfkSUHRZ4cNOqshY6W3CyDzVAmaDmeB9A7qpmsVlQp2D8y253+F2NMm1bcDdT3weG5vxkdF5qdx99gRMwDYJ4WZgIryrCAOqDLKmoSEuyuh1Zil9pDGPh/grf+EgXzDFnntgE8XJVKIldsbUplCmycSNtk47PtJATJ8q5v2dIazlxwmxKfarXS7x805u4ElrZ2h3JMCOOfL1k3sJbYc4JbZ6zB8DAhSsZ79KrStn3DE+gULmPJjM0HEbtouegZpE5wcHldoo4Oi78uNrwtv1lWp4AnK/Xwm3bl/ egon@bod\r\n"
    54      ],
    55      "openid_identifier": "xDPXBdB"
    56  }`
    57  
    58  var mockServerNoSSHJSON = `{
    59      "username": "mvo",
    60      "openid_identifier": "xDPXBdB"
    61  }`
    62  
    63  func (t *userInfoSuite) SetUpTest(c *check.C) {
    64  	t.BaseTest.SetUpTest(c)
    65  
    66  	_, t.restoreLogger = logger.MockLogger()
    67  	t.store = store.New(nil, nil)
    68  
    69  	store.MockDefaultRetryStrategy(&t.BaseTest, retry.LimitCount(6, retry.LimitTime(1*time.Second,
    70  		retry.Exponential{
    71  			Initial: 1 * time.Millisecond,
    72  			Factor:  1.1,
    73  		},
    74  	)))
    75  }
    76  
    77  func (t *userInfoSuite) TearDownTest(c *check.C) {
    78  	t.BaseTest.TearDownTest(c)
    79  
    80  	t.restoreLogger()
    81  }
    82  
    83  func (s *userInfoSuite) redirectToTestSSO(handler func(http.ResponseWriter, *http.Request)) {
    84  	server := httptest.NewServer(http.HandlerFunc(handler))
    85  	s.BaseTest.AddCleanup(func() { server.Close() })
    86  	os.Setenv("SNAPPY_FORCE_SSO_URL", server.URL+"/api/v2")
    87  	s.BaseTest.AddCleanup(func() { os.Unsetenv("SNAPPY_FORCE_SSO_URL") })
    88  }
    89  
    90  func (s *userInfoSuite) TestCreateUserNoSSHKeys(c *check.C) {
    91  	n := 0
    92  	s.redirectToTestSSO(func(w http.ResponseWriter, r *http.Request) {
    93  		switch n {
    94  		case 0, 1:
    95  			w.WriteHeader(500) // force retry of the request
    96  		case 2:
    97  			c.Check(r.Method, check.Equals, "GET")
    98  			c.Check(r.URL.Path, check.Equals, "/api/v2/keys/popper@lse.ac.uk")
    99  			fmt.Fprintln(w, mockServerNoSSHJSON)
   100  		default:
   101  			c.Fatalf("expected to get 1 requests, now on %d", n+1)
   102  		}
   103  
   104  		n++
   105  	})
   106  
   107  	info, err := s.store.UserInfo("popper@lse.ac.uk")
   108  	c.Assert(err, check.IsNil)
   109  	c.Assert(n, check.Equals, 3) // number of requests after retries
   110  	c.Check(info.Username, check.Equals, "mvo")
   111  	c.Check(info.OpenIDIdentifier, check.Equals, "xDPXBdB")
   112  	c.Check(info.SSHKeys, check.HasLen, 0)
   113  }
   114  
   115  func (s *userInfoSuite) TestCreateUser(c *check.C) {
   116  	n := 0
   117  	s.redirectToTestSSO(func(w http.ResponseWriter, r *http.Request) {
   118  		switch n {
   119  		case 0, 1:
   120  			w.WriteHeader(500) // force retry of the request
   121  		case 2:
   122  			c.Check(r.Method, check.Equals, "GET")
   123  			c.Check(r.URL.Path, check.Equals, "/api/v2/keys/popper@lse.ac.uk")
   124  			fmt.Fprintln(w, mockServerJSON)
   125  		default:
   126  			c.Fatalf("expected to get 1 requests, now on %d", n+1)
   127  		}
   128  
   129  		n++
   130  	})
   131  
   132  	info, err := s.store.UserInfo("popper@lse.ac.uk")
   133  	c.Assert(err, check.IsNil)
   134  	c.Assert(n, check.Equals, 3) // number of requests after retries
   135  	c.Check(info.Username, check.Equals, "mvo")
   136  	c.Check(info.OpenIDIdentifier, check.Equals, "xDPXBdB")
   137  	c.Check(info.SSHKeys, check.DeepEquals, []string{"ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAIEAqwsTkky+laeukWyGFmtiAQUFgjD+wKYuRtOj11gjTe3qUNDgMR54W8IUELZ6NwNWs2wium+jQZLY4vlsDq4PkYK8J2qgjRZURCKp4JbjbVNSg2WO7vDtl+0FIC1GaCdglRVWffrwKN1RLlwqBCVXi01nnTk3+hEpWddjqoTXMwM= egon@top",
   138  		"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDKBFmfD1KNULZv35907+ArIfxdGGzF1XCQj287AgK7k5GWcEdnUQfkSUHRZ4cNOqshY6W3CyDzVAmaDmeB9A7qpmsVlQp2D8y253+F2NMm1bcDdT3weG5vxkdF5qdx99gRMwDYJ4WZgIryrCAOqDLKmoSEuyuh1Zil9pDGPh/grf+EgXzDFnntgE8XJVKIldsbUplCmycSNtk47PtJATJ8q5v2dIazlxwmxKfarXS7x805u4ElrZ2h3JMCOOfL1k3sJbYc4JbZ6zB8DAhSsZ79KrStn3DE+gULmPJjM0HEbtouegZpE5wcHldoo4Oi78uNrwtv1lWp4AnK/Xwm3bl/ egon@bod\r\n"})
   139  }
   140  
   141  func (s *userInfoSuite) TestCreateUser500RetriesExhausted(c *check.C) {
   142  	n := 0
   143  	s.redirectToTestSSO(func(w http.ResponseWriter, r *http.Request) {
   144  		w.WriteHeader(500)
   145  		n++
   146  	})
   147  
   148  	_, err := s.store.UserInfo("popper@lse.ac.uk")
   149  	c.Assert(err, check.NotNil)
   150  	c.Assert(err, check.ErrorMatches, `cannot look up user.*?got unexpected HTTP status code 500.*`)
   151  	c.Assert(n, check.Equals, 6)
   152  }