PLT-3745 - Deauthorize OAuth Apps (#3852)
* Deauthorize OAuth APIs * Deautorize OAuth Apps Account Settings * Fix typo in client method * Fix issues found by PM * Show help text only when there is at least one authorized app
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
e406a92fbb
Коммит
9ab5a79962
@@ -211,6 +211,29 @@ func (as SqlOAuthStore) GetApps() StoreChannel {
|
||||
return storeChannel
|
||||
}
|
||||
|
||||
func (as SqlOAuthStore) GetAuthorizedApps(userId string) StoreChannel {
|
||||
storeChannel := make(StoreChannel)
|
||||
|
||||
go func() {
|
||||
result := StoreResult{}
|
||||
|
||||
var apps []*model.OAuthApp
|
||||
|
||||
if _, err := as.GetReplica().Select(&apps,
|
||||
`SELECT o.* FROM OAuthApps AS o INNER JOIN
|
||||
Preferences AS p ON p.Name=o.Id AND p.UserId=:UserId`, map[string]interface{}{"UserId": userId}); err != nil {
|
||||
result.Err = model.NewLocAppError("SqlOAuthStore.GetAuthorizedApps", "store.sql_oauth.get_apps.find.app_error", nil, "err="+err.Error())
|
||||
}
|
||||
|
||||
result.Data = apps
|
||||
|
||||
storeChannel <- result
|
||||
close(storeChannel)
|
||||
}()
|
||||
|
||||
return storeChannel
|
||||
}
|
||||
|
||||
func (as SqlOAuthStore) DeleteApp(id string) StoreChannel {
|
||||
storeChannel := make(StoreChannel)
|
||||
|
||||
@@ -294,6 +317,33 @@ func (as SqlOAuthStore) GetAccessData(token string) StoreChannel {
|
||||
return storeChannel
|
||||
}
|
||||
|
||||
func (as SqlOAuthStore) GetAccessDataByUserForApp(userId, clientId string) StoreChannel {
|
||||
|
||||
storeChannel := make(StoreChannel)
|
||||
|
||||
go func() {
|
||||
result := StoreResult{}
|
||||
|
||||
var accessData []*model.AccessData
|
||||
|
||||
if _, err := as.GetReplica().Select(&accessData,
|
||||
"SELECT * FROM OAuthAccessData WHERE UserId = :UserId AND ClientId = :ClientId",
|
||||
map[string]interface{}{"UserId": userId, "ClientId": clientId}); err != nil {
|
||||
result.Err = model.NewLocAppError("SqlOAuthStore.GetAccessDataByUserForApp",
|
||||
"store.sql_oauth.get_access_data_by_user_for_app.app_error", nil,
|
||||
"user_id="+userId+" client_id="+clientId)
|
||||
} else {
|
||||
result.Data = accessData
|
||||
}
|
||||
|
||||
storeChannel <- result
|
||||
close(storeChannel)
|
||||
|
||||
}()
|
||||
|
||||
return storeChannel
|
||||
}
|
||||
|
||||
func (as SqlOAuthStore) GetAccessDataByRefreshToken(token string) StoreChannel {
|
||||
|
||||
storeChannel := make(StoreChannel)
|
||||
|
||||
@@ -202,6 +202,82 @@ func TestOAuthStoreRemoveAuthDataByUser(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuthGetAuthorizedApps(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
a1 := model.OAuthApp{}
|
||||
a1.CreatorId = model.NewId()
|
||||
a1.Name = "TestApp" + model.NewId()
|
||||
a1.CallbackUrls = []string{"https://nowhere.com"}
|
||||
a1.Homepage = "https://nowhere.com"
|
||||
Must(store.OAuth().SaveApp(&a1))
|
||||
|
||||
// allow the app
|
||||
p := model.Preference{}
|
||||
p.UserId = a1.CreatorId
|
||||
p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP
|
||||
p.Name = a1.Id
|
||||
p.Value = "true"
|
||||
Must(store.Preference().Save(&model.Preferences{p}))
|
||||
|
||||
if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil {
|
||||
t.Fatal(result.Err)
|
||||
} else {
|
||||
apps := result.Data.([]*model.OAuthApp)
|
||||
if len(apps) == 0 {
|
||||
t.Fatal("It should have return apps")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuthGetAccessDataByUserForApp(t *testing.T) {
|
||||
Setup()
|
||||
|
||||
a1 := model.OAuthApp{}
|
||||
a1.CreatorId = model.NewId()
|
||||
a1.Name = "TestApp" + model.NewId()
|
||||
a1.CallbackUrls = []string{"https://nowhere.com"}
|
||||
a1.Homepage = "https://nowhere.com"
|
||||
Must(store.OAuth().SaveApp(&a1))
|
||||
|
||||
// allow the app
|
||||
p := model.Preference{}
|
||||
p.UserId = a1.CreatorId
|
||||
p.Category = model.PREFERENCE_CATEGORY_AUTHORIZED_OAUTH_APP
|
||||
p.Name = a1.Id
|
||||
p.Value = "true"
|
||||
Must(store.Preference().Save(&model.Preferences{p}))
|
||||
|
||||
if result := <-store.OAuth().GetAuthorizedApps(a1.CreatorId); result.Err != nil {
|
||||
t.Fatal(result.Err)
|
||||
} else {
|
||||
apps := result.Data.([]*model.OAuthApp)
|
||||
if len(apps) == 0 {
|
||||
t.Fatal("It should have return apps")
|
||||
}
|
||||
}
|
||||
|
||||
// save the token
|
||||
ad1 := model.AccessData{}
|
||||
ad1.ClientId = a1.Id
|
||||
ad1.UserId = a1.CreatorId
|
||||
ad1.Token = model.NewId()
|
||||
ad1.RefreshToken = model.NewId()
|
||||
|
||||
if err := (<-store.OAuth().SaveAccessData(&ad1)).Err; err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if result := <-store.OAuth().GetAccessDataByUserForApp(a1.CreatorId, a1.Id); result.Err != nil {
|
||||
t.Fatal(result.Err)
|
||||
} else {
|
||||
accessData := result.Data.([]*model.AccessData)
|
||||
if len(accessData) == 0 {
|
||||
t.Fatal("It should have return access data")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOAuthStoreDeleteApp(t *testing.T) {
|
||||
a1 := model.OAuthApp{}
|
||||
a1.CreatorId = model.NewId()
|
||||
|
||||
@@ -188,6 +188,7 @@ type OAuthStore interface {
|
||||
GetApp(id string) StoreChannel
|
||||
GetAppByUser(userId string) StoreChannel
|
||||
GetApps() StoreChannel
|
||||
GetAuthorizedApps(userId string) StoreChannel
|
||||
DeleteApp(id string) StoreChannel
|
||||
SaveAuthData(authData *model.AuthData) StoreChannel
|
||||
GetAuthData(code string) StoreChannel
|
||||
@@ -196,6 +197,7 @@ type OAuthStore interface {
|
||||
SaveAccessData(accessData *model.AccessData) StoreChannel
|
||||
UpdateAccessData(accessData *model.AccessData) StoreChannel
|
||||
GetAccessData(token string) StoreChannel
|
||||
GetAccessDataByUserForApp(userId, clientId string) StoreChannel
|
||||
GetAccessDataByRefreshToken(token string) StoreChannel
|
||||
GetPreviousAccessData(userId, clientId string) StoreChannel
|
||||
RemoveAccessData(token string) StoreChannel
|
||||
|
||||
Ссылка в новой задаче
Block a user