github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/store/storetest/oauth_store.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package storetest
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/mattermost/mattermost-server/v5/model"
    10  	"github.com/mattermost/mattermost-server/v5/store"
    11  	"github.com/stretchr/testify/assert"
    12  	"github.com/stretchr/testify/require"
    13  )
    14  
    15  func TestOAuthStore(t *testing.T, ss store.Store) {
    16  	t.Run("SaveApp", func(t *testing.T) { testOAuthStoreSaveApp(t, ss) })
    17  	t.Run("GetApp", func(t *testing.T) { testOAuthStoreGetApp(t, ss) })
    18  	t.Run("UpdateApp", func(t *testing.T) { testOAuthStoreUpdateApp(t, ss) })
    19  	t.Run("SaveAccessData", func(t *testing.T) { testOAuthStoreSaveAccessData(t, ss) })
    20  	t.Run("OAuthUpdateAccessData", func(t *testing.T) { testOAuthUpdateAccessData(t, ss) })
    21  	t.Run("GetAccessData", func(t *testing.T) { testOAuthStoreGetAccessData(t, ss) })
    22  	t.Run("RemoveAccessData", func(t *testing.T) { testOAuthStoreRemoveAccessData(t, ss) })
    23  	t.Run("RemoveAllAccessData", func(t *testing.T) { testOAuthStoreRemoveAllAccessData(t, ss) })
    24  	t.Run("SaveAuthData", func(t *testing.T) { testOAuthStoreSaveAuthData(t, ss) })
    25  	t.Run("GetAuthData", func(t *testing.T) { testOAuthStoreGetAuthData(t, ss) })
    26  	t.Run("RemoveAuthData", func(t *testing.T) { testOAuthStoreRemoveAuthData(t, ss) })
    27  	t.Run("RemoveAuthDataByUser", func(t *testing.T) { testOAuthStoreRemoveAuthDataByUser(t, ss) })
    28  	t.Run("OAuthGetAuthorizedApps", func(t *testing.T) { testOAuthGetAuthorizedApps(t, ss) })
    29  	t.Run("OAuthGetAccessDataByUserForApp", func(t *testing.T) { testOAuthGetAccessDataByUserForApp(t, ss) })
    30  	t.Run("DeleteApp", func(t *testing.T) { testOAuthStoreDeleteApp(t, ss) })
    31  }
    32  
    33  func testOAuthStoreSaveApp(t *testing.T, ss store.Store) {
    34  	a1 := model.OAuthApp{}
    35  	a1.CreatorId = model.NewId()
    36  	a1.CallbackUrls = []string{"https://nowhere.com"}
    37  	a1.Homepage = "https://nowhere.com"
    38  
    39  	// Try to save an app that already has an Id
    40  	a1.Id = model.NewId()
    41  	_, err := ss.OAuth().SaveApp(&a1)
    42  	require.NotNil(t, err, "Should have failed, cannot add an OAuth app cannot be save with an Id, it has to be updated")
    43  
    44  	// Try to save an Invalid App
    45  	a1.Id = ""
    46  	_, err = ss.OAuth().SaveApp(&a1)
    47  	require.NotNil(t, err, "Should have failed, app should be invalid cause it doesn' have a name set")
    48  
    49  	// Save the app
    50  	a1.Id = ""
    51  	a1.Name = "TestApp" + model.NewId()
    52  	_, err = ss.OAuth().SaveApp(&a1)
    53  	require.Nil(t, err)
    54  }
    55  
    56  func testOAuthStoreGetApp(t *testing.T, ss store.Store) {
    57  	a1 := model.OAuthApp{}
    58  	a1.CreatorId = model.NewId()
    59  	a1.Name = "TestApp" + model.NewId()
    60  	a1.CallbackUrls = []string{"https://nowhere.com"}
    61  	a1.Homepage = "https://nowhere.com"
    62  	_, err := ss.OAuth().SaveApp(&a1)
    63  	require.Nil(t, err)
    64  
    65  	// Lets try to get and app that does not exists
    66  	_, err = ss.OAuth().GetApp("fake0123456789abcderfgret1")
    67  	require.NotNil(t, err, "Should have failed. App does not exists")
    68  
    69  	_, err = ss.OAuth().GetApp(a1.Id)
    70  	require.Nil(t, err)
    71  
    72  	// Lets try and get the app from a user that hasn't created any apps
    73  	apps, err := ss.OAuth().GetAppByUser("fake0123456789abcderfgret1", 0, 1000)
    74  	require.Nil(t, err)
    75  	assert.Empty(t, apps, "Should have failed. Fake user hasn't created any apps")
    76  
    77  	_, err = ss.OAuth().GetAppByUser(a1.CreatorId, 0, 1000)
    78  	require.Nil(t, err)
    79  
    80  	_, err = ss.OAuth().GetApps(0, 1000)
    81  	require.Nil(t, err)
    82  }
    83  
    84  func testOAuthStoreUpdateApp(t *testing.T, ss store.Store) {
    85  	a1 := model.OAuthApp{}
    86  	a1.CreatorId = model.NewId()
    87  	a1.Name = "TestApp" + model.NewId()
    88  	a1.CallbackUrls = []string{"https://nowhere.com"}
    89  	a1.Homepage = "https://nowhere.com"
    90  	_, err := ss.OAuth().SaveApp(&a1)
    91  	require.Nil(t, err)
    92  
    93  	// temporarily save the created app id
    94  	id := a1.Id
    95  
    96  	a1.CreateAt = 1
    97  	a1.ClientSecret = "pwd"
    98  	a1.CreatorId = "12345678901234567890123456"
    99  
   100  	// Lets update the app by removing the name
   101  	a1.Name = ""
   102  	_, err = ss.OAuth().UpdateApp(&a1)
   103  	require.NotNil(t, err, "Should have failed. App name is not set")
   104  
   105  	// Lets not find the app that we are trying to update
   106  	a1.Id = "fake0123456789abcderfgret1"
   107  	a1.Name = "NewName"
   108  	_, err = ss.OAuth().UpdateApp(&a1)
   109  	require.NotNil(t, err, "Should have failed. Not able to find the app")
   110  
   111  	a1.Id = id
   112  	ua, err := ss.OAuth().UpdateApp(&a1)
   113  	require.Nil(t, err)
   114  	require.Equal(t, ua.Name, "NewName", "name did not update")
   115  	require.NotEqual(t, ua.CreateAt, 1, "create at should not have updated")
   116  	require.NotEqual(t, ua.CreatorId, "12345678901234567890123456", "creator id should not have updated")
   117  }
   118  
   119  func testOAuthStoreSaveAccessData(t *testing.T, ss store.Store) {
   120  	a1 := model.AccessData{}
   121  	a1.ClientId = model.NewId()
   122  	a1.UserId = model.NewId()
   123  
   124  	// Lets try and save an incomplete access data
   125  	_, err := ss.OAuth().SaveAccessData(&a1)
   126  	require.NotNil(t, err, "Should have failed. Access data needs the token")
   127  
   128  	a1.Token = model.NewId()
   129  	a1.RefreshToken = model.NewId()
   130  	a1.RedirectUri = "http://example.com"
   131  
   132  	_, err = ss.OAuth().SaveAccessData(&a1)
   133  	require.Nil(t, err)
   134  }
   135  
   136  func testOAuthUpdateAccessData(t *testing.T, ss store.Store) {
   137  	a1 := model.AccessData{}
   138  	a1.ClientId = model.NewId()
   139  	a1.UserId = model.NewId()
   140  	a1.Token = model.NewId()
   141  	a1.RefreshToken = model.NewId()
   142  	a1.ExpiresAt = model.GetMillis()
   143  	a1.RedirectUri = "http://example.com"
   144  	_, err := ss.OAuth().SaveAccessData(&a1)
   145  	require.Nil(t, err)
   146  
   147  	//Try to update to invalid Refresh Token
   148  	refreshToken := a1.RefreshToken
   149  	a1.RefreshToken = model.NewId() + "123"
   150  	_, err = ss.OAuth().UpdateAccessData(&a1)
   151  	require.NotNil(t, err, "Should have failed with invalid token")
   152  
   153  	//Try to update to invalid RedirectUri
   154  	a1.RefreshToken = model.NewId()
   155  	a1.RedirectUri = ""
   156  	_, err = ss.OAuth().UpdateAccessData(&a1)
   157  	require.NotNil(t, err, "Should have failed with invalid Redirect URI")
   158  
   159  	// Should update fine
   160  	a1.RedirectUri = "http://example.com"
   161  	ra1, err := ss.OAuth().UpdateAccessData(&a1)
   162  	require.Nil(t, err)
   163  	require.NotEqual(t, ra1.RefreshToken, refreshToken, "refresh tokens didn't match")
   164  }
   165  
   166  func testOAuthStoreGetAccessData(t *testing.T, ss store.Store) {
   167  	a1 := model.AccessData{}
   168  	a1.ClientId = model.NewId()
   169  	a1.UserId = model.NewId()
   170  	a1.Token = model.NewId()
   171  	a1.RefreshToken = model.NewId()
   172  	a1.ExpiresAt = model.GetMillis()
   173  	a1.RedirectUri = "http://example.com"
   174  	_, err := ss.OAuth().SaveAccessData(&a1)
   175  	require.Nil(t, err)
   176  
   177  	_, err = ss.OAuth().GetAccessData("invalidToken")
   178  	require.NotNil(t, err, "Should have failed. There is no data with an invalid token")
   179  
   180  	ra1, err := ss.OAuth().GetAccessData(a1.Token)
   181  	require.Nil(t, err)
   182  	assert.Equal(t, a1.Token, ra1.Token, "tokens didn't match")
   183  
   184  	_, err = ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)
   185  	require.Nil(t, err)
   186  
   187  	_, err = ss.OAuth().GetPreviousAccessData("user", "junk")
   188  	require.Nil(t, err)
   189  
   190  	// Try to get the Access data using an invalid refresh token
   191  	_, err = ss.OAuth().GetAccessDataByRefreshToken(a1.Token)
   192  	require.NotNil(t, err, "Should have failed. There is no data with an invalid token")
   193  
   194  	// Get the Access Data using the refresh token
   195  	ra1, err = ss.OAuth().GetAccessDataByRefreshToken(a1.RefreshToken)
   196  	require.Nil(t, err)
   197  	assert.Equal(t, a1.RefreshToken, ra1.RefreshToken, "tokens didn't match")
   198  }
   199  
   200  func testOAuthStoreRemoveAccessData(t *testing.T, ss store.Store) {
   201  	a1 := model.AccessData{}
   202  	a1.ClientId = model.NewId()
   203  	a1.UserId = model.NewId()
   204  	a1.Token = model.NewId()
   205  	a1.RefreshToken = model.NewId()
   206  	a1.RedirectUri = "http://example.com"
   207  	_, err := ss.OAuth().SaveAccessData(&a1)
   208  	require.Nil(t, err)
   209  
   210  	err = ss.OAuth().RemoveAccessData(a1.Token)
   211  	require.Nil(t, err)
   212  
   213  	result, _ := ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)
   214  	require.Nil(t, result, "did not delete access token")
   215  }
   216  
   217  func testOAuthStoreRemoveAllAccessData(t *testing.T, ss store.Store) {
   218  	a1 := model.AccessData{}
   219  	a1.ClientId = model.NewId()
   220  	a1.UserId = model.NewId()
   221  	a1.Token = model.NewId()
   222  	a1.RefreshToken = model.NewId()
   223  	a1.RedirectUri = "http://example.com"
   224  	_, err := ss.OAuth().SaveAccessData(&a1)
   225  	require.Nil(t, err)
   226  
   227  	err = ss.OAuth().RemoveAllAccessData()
   228  	require.Nil(t, err)
   229  
   230  	result, _ := ss.OAuth().GetPreviousAccessData(a1.UserId, a1.ClientId)
   231  	require.Nil(t, result, "did not delete access token")
   232  }
   233  
   234  func testOAuthStoreSaveAuthData(t *testing.T, ss store.Store) {
   235  	a1 := model.AuthData{}
   236  	a1.ClientId = model.NewId()
   237  	a1.UserId = model.NewId()
   238  	a1.Code = model.NewId()
   239  	a1.RedirectUri = "http://example.com"
   240  	_, err := ss.OAuth().SaveAuthData(&a1)
   241  	require.Nil(t, err)
   242  }
   243  
   244  func testOAuthStoreGetAuthData(t *testing.T, ss store.Store) {
   245  	a1 := model.AuthData{}
   246  	a1.ClientId = model.NewId()
   247  	a1.UserId = model.NewId()
   248  	a1.Code = model.NewId()
   249  	a1.RedirectUri = "http://example.com"
   250  	_, err := ss.OAuth().SaveAuthData(&a1)
   251  	require.Nil(t, err)
   252  
   253  	_, err = ss.OAuth().GetAuthData(a1.Code)
   254  	require.Nil(t, err)
   255  }
   256  
   257  func testOAuthStoreRemoveAuthData(t *testing.T, ss store.Store) {
   258  	a1 := model.AuthData{}
   259  	a1.ClientId = model.NewId()
   260  	a1.UserId = model.NewId()
   261  	a1.Code = model.NewId()
   262  	a1.RedirectUri = "http://example.com"
   263  	_, err := ss.OAuth().SaveAuthData(&a1)
   264  	require.Nil(t, err)
   265  
   266  	err = ss.OAuth().RemoveAuthData(a1.Code)
   267  	require.Nil(t, err)
   268  
   269  	_, err = ss.OAuth().GetAuthData(a1.Code)
   270  	require.NotNil(t, err, "should have errored - auth code removed")
   271  }
   272  
   273  func testOAuthStoreRemoveAuthDataByUser(t *testing.T, ss store.Store) {
   274  	a1 := model.AuthData{}
   275  	a1.ClientId = model.NewId()
   276  	a1.UserId = model.NewId()
   277  	a1.Code = model.NewId()
   278  	a1.RedirectUri = "http://example.com"
   279  	_, err := ss.OAuth().SaveAuthData(&a1)
   280  	require.Nil(t, err)
   281  
   282  	err = ss.OAuth().PermanentDeleteAuthDataByUser(a1.UserId)
   283  	require.Nil(t, err)
   284  }
   285  
   286  func testOAuthGetAuthorizedApps(t *testing.T, ss store.Store) {
   287  	a1 := model.OAuthApp{}
   288  	a1.CreatorId = model.NewId()
   289  	a1.Name = "TestApp" + model.NewId()
   290  	a1.CallbackUrls = []string{"https://nowhere.com"}
   291  	a1.Homepage = "https://nowhere.com"
   292  	_, err := ss.OAuth().SaveApp(&a1)
   293  	require.Nil(t, err)
   294  
   295  	// Lets try and get an Authorized app for a user who hasn't authorized it
   296  	apps, err := ss.OAuth().GetAuthorizedApps("fake0123456789abcderfgret1", 0, 1000)
   297  	require.Nil(t, err)
   298  	assert.Empty(t, apps, "Should have failed. Fake user hasn't authorized the app")
   299  
   300  	// allow the app
   301  	p := model.Preference{}
   302  	p.UserId = a1.CreatorId
   303  	p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP
   304  	p.Name = a1.Id
   305  	p.Value = "true"
   306  	nErr := ss.Preference().Save(&model.Preferences{p})
   307  	require.Nil(t, nErr)
   308  
   309  	apps, err = ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000)
   310  	require.Nil(t, err)
   311  	assert.NotEqual(t, len(apps), 0, "It should have return apps")
   312  }
   313  
   314  func testOAuthGetAccessDataByUserForApp(t *testing.T, ss store.Store) {
   315  	a1 := model.OAuthApp{}
   316  	a1.CreatorId = model.NewId()
   317  	a1.Name = "TestApp" + model.NewId()
   318  	a1.CallbackUrls = []string{"https://nowhere.com"}
   319  	a1.Homepage = "https://nowhere.com"
   320  	_, err := ss.OAuth().SaveApp(&a1)
   321  	require.Nil(t, err)
   322  
   323  	// allow the app
   324  	p := model.Preference{}
   325  	p.UserId = a1.CreatorId
   326  	p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP
   327  	p.Name = a1.Id
   328  	p.Value = "true"
   329  	nErr := ss.Preference().Save(&model.Preferences{p})
   330  	require.Nil(t, nErr)
   331  
   332  	apps, err := ss.OAuth().GetAuthorizedApps(a1.CreatorId, 0, 1000)
   333  	require.Nil(t, err)
   334  	assert.NotEqual(t, len(apps), 0, "It should have return apps")
   335  
   336  	// save the token
   337  	ad1 := model.AccessData{}
   338  	ad1.ClientId = a1.Id
   339  	ad1.UserId = a1.CreatorId
   340  	ad1.Token = model.NewId()
   341  	ad1.RefreshToken = model.NewId()
   342  	ad1.RedirectUri = "http://example.com"
   343  
   344  	_, err = ss.OAuth().SaveAccessData(&ad1)
   345  	require.Nil(t, err)
   346  
   347  	accessData, err := ss.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id)
   348  	require.Nil(t, err)
   349  	assert.NotEqual(t, len(accessData), 0, "It should have return access data")
   350  }
   351  
   352  func testOAuthStoreDeleteApp(t *testing.T, ss store.Store) {
   353  	a1 := model.OAuthApp{}
   354  	a1.CreatorId = model.NewId()
   355  	a1.Name = "TestApp" + model.NewId()
   356  	a1.CallbackUrls = []string{"https://nowhere.com"}
   357  	a1.Homepage = "https://nowhere.com"
   358  	_, err := ss.OAuth().SaveApp(&a1)
   359  	require.Nil(t, err)
   360  
   361  	// delete a non-existent app
   362  	err = ss.OAuth().DeleteApp("fakeclientId")
   363  	require.Nil(t, err)
   364  
   365  	s1 := &model.Session{}
   366  	s1.UserId = model.NewId()
   367  	s1.Token = model.NewId()
   368  	s1.IsOAuth = true
   369  
   370  	s1, nErr := ss.Session().Save(s1)
   371  	require.Nil(t, nErr)
   372  
   373  	ad1 := model.AccessData{}
   374  	ad1.ClientId = a1.Id
   375  	ad1.UserId = a1.CreatorId
   376  	ad1.Token = s1.Token
   377  	ad1.RefreshToken = model.NewId()
   378  	ad1.RedirectUri = "http://example.com"
   379  
   380  	_, err = ss.OAuth().SaveAccessData(&ad1)
   381  	require.Nil(t, err)
   382  
   383  	err = ss.OAuth().DeleteApp(a1.Id)
   384  	require.Nil(t, err)
   385  
   386  	_, nErr = ss.Session().Get(s1.Token)
   387  	require.NotNil(t, nErr, "should error - session should be deleted")
   388  
   389  	_, err = ss.OAuth().GetAccessData(s1.Token)
   390  	require.NotNil(t, err, "should error - access data should be deleted")
   391  }