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