Implemented Multiple API key deletion. Added Notification for API key deletion result. (#1298)

* Implemented Notification for API key deletion result.

* Moved several API keys deletion to Service side.
This commit is contained in:
Bogdan Artemenko 2019-02-13 13:34:40 +02:00 committed by GitHub
parent 3beaeebdb6
commit ad95d881c7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 111 additions and 52 deletions

View File

@ -38,8 +38,8 @@ const (
// CreateAPIKeyMutation is a mutation name for api key creation
CreateAPIKeyMutation = "createAPIKey"
// DeleteAPIKeyMutation is a mutation name for api key deleting
DeleteAPIKeyMutation = "deleteAPIKey"
// DeleteAPIKeysMutation is a mutation name for api key deleting
DeleteAPIKeysMutation = "deleteAPIKeys"
// InputArg is argument name for all input types
InputArg = "input"
@ -329,32 +329,39 @@ func rootMutation(service *console.Service, types Types) *graphql.Object {
},
},
// deletes api key
DeleteAPIKeyMutation: &graphql.Field{
Type: types.APIKeyInfo(),
DeleteAPIKeysMutation: &graphql.Field{
Type: graphql.NewList(types.APIKeyInfo()),
Args: graphql.FieldConfigArgument{
FieldID: &graphql.ArgumentConfig{
Type: graphql.NewNonNull(graphql.String),
Type: graphql.NewNonNull(graphql.NewList(graphql.String)),
},
},
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
keyID, _ := p.Args[FieldID].(string)
paramKeysID, _ := p.Args[FieldID].([]interface{})
id, err := uuid.Parse(keyID)
var keyIds []uuid.UUID
var keys []console.APIKeyInfo
for _, id := range paramKeysID {
keyID, err := uuid.Parse(id.(string))
if err != nil {
return nil, err
}
key, err := service.GetAPIKeyInfo(p.Context, *keyID)
if err != nil {
return nil, err
}
keyIds = append(keyIds, *keyID)
keys = append(keys, *key)
}
err := service.DeleteAPIKeys(p.Context, keyIds)
if err != nil {
return nil, err
}
key, err := service.GetAPIKeyInfo(p.Context, *id)
if err != nil {
return nil, err
}
err = service.DeleteAPIKey(p.Context, *id)
if err != nil {
return nil, err
}
return key, nil
return keys, nil
},
},
},

View File

@ -491,17 +491,20 @@ func TestGrapqhlMutation(t *testing.T) {
}
query := fmt.Sprintf(
"mutation {deleteAPIKey(id:\"%s\"){name,projectID}}",
id.String(),
"mutation {deleteAPIKeys(id:[\"%s\"]){name,projectID}}",
keyID,
)
result := testQuery(t, query)
data := result.(map[string]interface{})
keyInfo := data[consoleql.DeleteAPIKeyMutation].(map[string]interface{})
keyInfoList := data[consoleql.DeleteAPIKeysMutation].([]interface{})
assert.Equal(t, info.Name, keyInfo[consoleql.FieldName])
assert.Equal(t, project.ID.String(), keyInfo[consoleql.FieldProjectID])
for _, k := range keyInfoList {
keyInfo := k.(map[string]interface{})
assert.Equal(t, info.Name, keyInfo[consoleql.FieldName])
assert.Equal(t, project.ID.String(), keyInfo[consoleql.FieldProjectID])
}
})
t.Run("Delete project mutation", func(t *testing.T) {

View File

@ -547,25 +547,56 @@ func (s *Service) GetAPIKeyInfo(ctx context.Context, id uuid.UUID) (*APIKeyInfo,
return key, nil
}
// DeleteAPIKey deletes api key by id
func (s *Service) DeleteAPIKey(ctx context.Context, id uuid.UUID) (err error) {
// DeleteAPIKeys deletes api key by id
func (s *Service) DeleteAPIKeys(ctx context.Context, ids []uuid.UUID) (err error) {
defer mon.Task()(&ctx)(&err)
auth, err := GetAuth(ctx)
if err != nil {
return err
}
key, err := s.store.APIKeys().Get(ctx, id)
var keysErr errs.Group
for _, keyID := range ids {
key, err := s.store.APIKeys().Get(ctx, keyID)
if err != nil {
keysErr.Add(err)
continue
}
_, err = s.isProjectMember(ctx, auth.User.ID, key.ProjectID)
if err != nil {
keysErr.Add(ErrUnauthorized.Wrap(err))
continue
}
}
if err = keysErr.Err(); err != nil {
return err
}
tx, err := s.store.BeginTx(ctx)
if err != nil {
return err
}
_, err = s.isProjectMember(ctx, auth.User.ID, key.ProjectID)
if err != nil {
return ErrUnauthorized.Wrap(err)
defer func() {
if err != nil {
err = errs.Combine(err, tx.Rollback())
return
}
err = tx.Commit()
}()
for _, keyToDeleteID := range ids {
err = tx.APIKeys().Delete(ctx, keyToDeleteID)
if err != nil {
return err
}
}
return s.store.APIKeys().Delete(ctx, id)
return nil
}
// GetAPIKeysInfoByProjectID retrieves all api keys for a given project

View File

@ -72,7 +72,6 @@ export async function createAPIKey(projectID: string, name: string) {
if (response.errors) {
result.errorMessage = response.errors[0].message;
} else {
console.log('response', response)
result.isSuccess = true;
result.data = {
key: response.data.createAPIKey.key,
@ -86,7 +85,7 @@ export async function createAPIKey(projectID: string, name: string) {
return result;
}
export async function deleteAPIKey(id: string) {
export async function deleteAPIKeys(ids: string[]) {
let result: RequestResponse<any> = {
errorMessage: '',
isSuccess: false,
@ -97,7 +96,7 @@ export async function deleteAPIKey(id: string) {
let response: any = await apollo.mutate({
mutation: gql(
`mutation {
deleteAPIKey(id: "${id}") {
deleteAPIKeys(id: [${prepareIdList(ids)}]) {
id
}
}`
@ -109,11 +108,21 @@ export async function deleteAPIKey(id: string) {
result.errorMessage = response.errors[0].message;
} else {
result.isSuccess = true;
result.data = response.data.deleteAPIKey;
result.data = response.data.deleteAPIKeys;
}
} catch (e) {
result.errorMessage = e.message;
}
return result;
}
}
function prepareIdList(ids: string[]): string {
let idString: string = '';
ids.forEach(id => {
idString += `"${id}", `;
});
return idString;
}

View File

@ -30,17 +30,23 @@
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
import Button from '@/components/common/Button.vue';
import { API_KEYS_ACTIONS } from "@/utils/constants/actionNames";
import { API_KEYS_ACTIONS, NOTIFICATION_ACTIONS } from "@/utils/constants/actionNames";
@Component({
methods: {
onDelete: async function () {
let selectedKeys: any[] = this.$store.getters.selectedAPIKeys;
onDelete: async function () {
let selectedKeys: any[] = this.$store.getters.selectedAPIKeys.map((key)=>{return key.id});
for (let i = 0; i < selectedKeys.length; i++) {
this.$store.dispatch(API_KEYS_ACTIONS.DELETE, selectedKeys[i].id);
}
},
const dispatchResult = await this.$store.dispatch(API_KEYS_ACTIONS.DELETE, selectedKeys);
let keySuffix = selectedKeys.length > 1 ? '\'s' : '';
if(dispatchResult.isSuccess){
this.$store.dispatch(NOTIFICATION_ACTIONS.SUCCESS, `API key${keySuffix} deleted successfully`);
} else {
this.$store.dispatch(NOTIFICATION_ACTIONS.ERROR, `Error during deletion API key${keySuffix}`);
}
},
onClearSelection: function (): void {
this.$store.dispatch(API_KEYS_ACTIONS.CLEAR_SELECTION);
},

View File

@ -2,7 +2,7 @@
// See LICENSE for copying information.
import { API_KEYS_MUTATIONS } from '../mutationConstants';
import { createAPIKey, deleteAPIKey, fetchAPIKeys } from "@/api/apiKeys";
import { createAPIKey, deleteAPIKeys, fetchAPIKeys } from '@/api/apiKeys';
import { API_KEYS_ACTIONS } from "@/utils/constants/actionNames";
export const apiKeysModule = {
@ -16,8 +16,14 @@ export const apiKeysModule = {
[API_KEYS_MUTATIONS.ADD](state: any, apiKey: any) {
state.apiKeys.push(apiKey);
},
[API_KEYS_MUTATIONS.DELETE](state: any, id: string) {
state.apiKeys = state.apiKeys.filter((key => key.id !== id))
[API_KEYS_MUTATIONS.DELETE](state: any, ids: string[]) {
const keysCount = ids.length;
for (let j = 0; j < keysCount; j++) {
state.apiKeys = state.apiKeys.filter((element: any) => {
return element.id !== ids[j];
});
}
},
[API_KEYS_MUTATIONS.TOGGLE_SELECTION](state: any, apiKeyID: string) {
state.apiKeys = state.apiKeys.map((apiKey: any) => {
@ -52,7 +58,6 @@ export const apiKeysModule = {
const projectId = rootGetters.selectedProject.id;
let result = await createAPIKey(projectId, name);
console.log(result);
if (result.isSuccess) {
commit(API_KEYS_MUTATIONS.ADD, result.data.keyInfo);
@ -60,15 +65,13 @@ export const apiKeysModule = {
return result;
},
[API_KEYS_ACTIONS.DELETE]: async function({commit}: any, id: string): Promise<RequestResponse<any>> {
let result = await deleteAPIKey(id);
[API_KEYS_ACTIONS.DELETE]: async function({commit}: any, ids: string[]): Promise<RequestResponse<any>> {
let result = await deleteAPIKeys(ids);
if (result.isSuccess) {
commit(API_KEYS_MUTATIONS.DELETE, result.data.id);
commit(API_KEYS_MUTATIONS.DELETE, ids);
}
console.log(result);
return result;
},
[API_KEYS_ACTIONS.TOGGLE_SELECTION]: function({commit}, apiKeyID: string): void {