From 0298d0fdda767d03b4cc247574d09cf6b5229528 Mon Sep 17 00:00:00 2001 From: VSevostianov <167165727+VSevostianov@users.noreply.github.com> Date: Mon, 7 Oct 2024 10:34:52 +0200 Subject: [PATCH] Feature/home 1781 new permission related api (#54) * HOME-1781: added new permission related API calls * HOME-1781: extracted templates separately, added tests * HOME-1781: fixed test --- api.go | 2 + svc_contributor_test.go | 95 +++++++++++++++++++++++++++++++++ svc_permissiontemplates.go | 41 ++++++++++++++ svc_permissiontemplates_test.go | 88 ++++++++++++++++++++++++++++++ svc_teamusergroup.go | 18 ++++--- 5 files changed, 238 insertions(+), 6 deletions(-) create mode 100644 svc_permissiontemplates.go create mode 100644 svc_permissiontemplates_test.go diff --git a/api.go b/api.go index 8a648d5..7eadae1 100644 --- a/api.go +++ b/api.go @@ -26,6 +26,7 @@ type Api struct { Teams func() *TeamService TeamUserGroups func() *TeamUserGroupService TeamUsers func() *TeamUserService + PermissionTemplates func() *PermissionTemplateService TranslationProviders func() *TranslationProviderService Translations func() *TranslationService TranslationStatuses func() *TranslationStatusService @@ -57,6 +58,7 @@ func New(apiToken string, options ...ClientOption) (*Api, error) { c.Projects = func() *ProjectService { return &ProjectService{BaseService: bs, opts: prjOpts} } c.Branches = func() *BranchService { return &BranchService{bs} } c.Teams = func() *TeamService { return &TeamService{bs} } + c.PermissionTemplates = func() *PermissionTemplateService { return &PermissionTemplateService{bs} } c.TeamUsers = func() *TeamUserService { return &TeamUserService{bs} } c.TeamUserGroups = func() *TeamUserGroupService { return &TeamUserGroupService{bs} } diff --git a/svc_contributor_test.go b/svc_contributor_test.go index 3982c25..b5875a4 100644 --- a/svc_contributor_test.go +++ b/svc_contributor_test.go @@ -100,6 +100,101 @@ func TestContributorService_Create(t *testing.T) { } } +func TestContributorService_CreateWithRoleId(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc( + fmt.Sprintf("/projects/%s/contributors", testProjectID), + func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + testMethod(t, r, "POST") + testHeader(t, r, apiTokenHeader, testApiToken) + data := `{ + "contributors": [ + { + "email": "translator@mycompany.com", + "fullname": "Mr. Translator", + "is_admin": false, + "is_reviewer": true, + "languages": [ + { + "lang_iso": "en", + "is_writable": false + } + ], + "role_id": 2 + } + ] + }` + + req := new(bytes.Buffer) + _ = json.Compact(req, []byte(data)) + + testBody(t, r, req.String()) + + _, _ = fmt.Fprint(w, `{ + "project_id": "`+testProjectID+`", + "contributors": [{ + "user_id": 421, + "email": "translator@mycompany.com", + "fullname": "Mr. Translator", + "is_admin": false, + "is_reviewer": true, + "languages": [ + { + "lang_iso": "en", + "is_writable": false + } + ], + "role_id": 2 + }] + }`) + }) + + r, err := client.Contributors().Create(testProjectID, []NewContributor{ + { + Email: "translator@mycompany.com", + Fullname: "Mr. Translator", + Permission: Permission{ + IsAdmin: false, + IsReviewer: true, + Languages: []Language{{ + LangISO: "en", + IsWritable: false, + }}, + AdminRights: nil, + RoleId: 2, + }, + }, + }) + if err != nil { + t.Errorf("Contributors.Create returned error: %v", err) + } + + want := []Contributor{ + { + WithUserID: WithUserID{UserID: 421}, + Email: "translator@mycompany.com", + Fullname: "Mr. Translator", + Permission: Permission{ + IsAdmin: false, + IsReviewer: true, + Languages: []Language{{ + LangISO: "en", + IsWritable: false, + }}, + AdminRights: nil, + RoleId: 2, + }, + }, + } + + if !reflect.DeepEqual(r.Contributors, want) { + t.Errorf("Contributors.Create returned %+v, want %+v", r.Contributors, want) + } +} + func TestContributorService_Delete(t *testing.T) { client, mux, _, teardown := setup() defer teardown() diff --git a/svc_permissiontemplates.go b/svc_permissiontemplates.go new file mode 100644 index 0000000..22ca322 --- /dev/null +++ b/svc_permissiontemplates.go @@ -0,0 +1,41 @@ +package lokalise + +import "fmt" + +const ( + pathTemplates = "teams/%d/roles" +) + +// The PermissionTemplate service +type PermissionTemplateService struct { + BaseService +} + +type PermissionTemplate struct { + ID int `json:"id"` + Role string `json:"role"` + Permissions []string `json:"permissions"` + Description string `json:"description"` + Tag string `json:"tag"` + TagColor string `json:"tagColor"` + TagInfo string `json:"tagInfo"` + DoesEnableAllReadOnlyLanguages bool `json:"doesEnableAllReadOnlyLanguages"` +} + +type PermissionRoleResponse struct { + Roles []PermissionTemplate `json:"roles"` +} + +// List all possible permission roles +func (c *PermissionTemplateService) ListPermissionRoles(teamID int64) (r PermissionRoleResponse, err error) { + resp, err := c.getWithOptions(c.Ctx(), pathPermissionRoles(teamID), &r, c.PageOpts()) + + if err != nil { + return r, err + } + return r, apiError(resp) +} + +func pathPermissionRoles(teamID int64) string { + return fmt.Sprintf(pathTemplates, teamID) +} diff --git a/svc_permissiontemplates_test.go b/svc_permissiontemplates_test.go new file mode 100644 index 0000000..e52e0d5 --- /dev/null +++ b/svc_permissiontemplates_test.go @@ -0,0 +1,88 @@ +package lokalise + +import ( + "fmt" + "net/http" + "reflect" + "testing" +) + +func TestTeamPermissionTemplates_List(t *testing.T) { + client, mux, _, teardown := setup() + defer teardown() + + mux.HandleFunc( + "/teams/1/roles", + func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Content-Type", "application/json") + testMethod(t, r, "GET") + testHeader(t, r, apiTokenHeader, testApiToken) + + _, _ = fmt.Fprint(w, `{ + "roles": [ + { + "id": 1, + "role": "Localisation management", + "permissions": [ + "activity", + "branches_main_modify" + ], + "description": "Manage project settings, contributors and tasks", + "tag": "Full access", + "tagColor": "green", + "doesEnableAllReadOnlyLanguages": true + }, + { + "id": 2, + "role": "Developer", + "permissions": [ + "download", + "upload" + ], + "description": "Create keys, upload and download content", + "tag": "Advanced", + "tagColor": "cyan", + "doesEnableAllReadOnlyLanguages": true + } + ] + }`) + }) + + r, err := client.PermissionTemplates().ListPermissionRoles(1) + if err != nil { + t.Errorf("Teams.List returned error: %v", err) + } + + want := PermissionRoleResponse{ + Roles: []PermissionTemplate{ + { + ID: 1, + Role: "Localisation management", + Permissions: []string{ + "activity", + "branches_main_modify", + }, + Description: "Manage project settings, contributors and tasks", + Tag: "Full access", + TagColor: "green", + DoesEnableAllReadOnlyLanguages: true, + }, + { + ID: 2, + Role: "Developer", + Permissions: []string{ + "download", + "upload", + }, + Description: "Create keys, upload and download content", + Tag: "Advanced", + TagColor: "cyan", + DoesEnableAllReadOnlyLanguages: true, + }, + }, + } + + if !reflect.DeepEqual(r, want) { + t.Errorf("Team.PermissionRoles.List returned %+v, want %+v", r, want) + } +} diff --git a/svc_teamusergroup.go b/svc_teamusergroup.go index d683b52..53d5917 100644 --- a/svc_teamusergroup.go +++ b/svc_teamusergroup.go @@ -26,12 +26,14 @@ type TeamUserGroup struct { } type Permission struct { - IsAdmin bool `json:"is_admin"` + // IsAdmin is deprecated, and will be removed in next release. Use AdminRights for more granular control. + IsAdmin bool `json:"is_admin"` + // IsReviewer is deprecated, and will be removed in next release. Use the appropriate permissions in AdminRights instead. IsReviewer bool `json:"is_reviewer"` Languages []Language `json:"languages,omitempty"` - - // Possible values are upload, activity, download, settings, statistics, keys, screenshots, contributors, languages + // Possible values are activity, branches_main_modify, branches_create, branches_merge, statistics, tasks, contributors, settings, manage_languages, download, upload, glossary_delete, glossary_edit, manage_keys, screenshots, custom_status_modify, review AdminRights []string `json:"admin_rights,omitempty"` // todo make admin rights as constants available in the lib + RoleId int64 `json:"role_id,omitempty"` } // ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ @@ -43,9 +45,13 @@ type NewGroupLanguages struct { } type NewGroup struct { - Name string `json:"name"` - IsAdmin bool `json:"is_admin"` - IsReviewer bool `json:"is_reviewer"` + Name string `json:"name"` + // IsAdmin is deprecated, and will be removed in next release. Use AdminRights for more granular control. + IsAdmin bool `json:"is_admin"` + // IsReviewer is deprecated, and will be removed in next release. Use the appropriate permissions in AdminRights instead. + IsReviewer bool `json:"is_reviewer"` + + // Possible values are activity, branches_main_modify, branches_create, branches_merge, statistics, tasks, contributors, settings, manage_languages, download, upload, glossary_delete, glossary_edit, manage_keys, screenshots, custom_status_modify, review AdminRights []string `json:"admin_rights,omitempty"` Languages NewGroupLanguages `json:"languages,omitempty"` }