Skip to content

Commit

Permalink
Handle customer permissions of a project (#37)
Browse files Browse the repository at this point in the history
* Handle customer permissions of a project
  • Loading branch information
rehanjaved237 authored Sep 29, 2020
1 parent 1f0d60f commit fbeb210
Show file tree
Hide file tree
Showing 8 changed files with 69 additions and 8 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,12 @@ Examples for Project Custom Resource can be found at [here](https://github.com/s
* Following are the immutable fields that cannot be updated:
* ProjectTemplateKey
* ProjectTypeKey
* leadAccountId
* LeadAccountId
* CategoryId
* NotificationScheme
* PermissionScheme
* issueSecurityScheme
* IssueSecurityScheme
* OpenAccess

You can read more about these fields on [Jira Service Desk api docs](https://developer.atlassian.com/cloud/jira/platform/rest/v3/api-group-projects/#api-rest-api-3-project-post).

Expand Down
7 changes: 7 additions & 0 deletions api/v1alpha1/project_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ type ProjectSpec struct {
// The ID of the project's category
// +optional
CategoryId int `json:"categoryId,omitempty"`

// The Open Access status, which dictates who can access the project. If set to true all customers can access the project. If false, only customers added to project can access the project.
// +optional, if not provided default behaviour is False
OpenAccess bool `json:"openAccess,omitempty"`
}

// ProjectStatus defines the observed state of Project
Expand Down Expand Up @@ -160,6 +164,9 @@ func (project *Project) IsValidUpdate(existingProject Project) (bool, error) {
if project.Spec.IssueSecurityScheme != existingProject.Spec.IssueSecurityScheme {
return false, fmt.Errorf("%s %s", "IssueSecurityScheme", errorImmutableFieldMsg)
}
if project.Spec.OpenAccess != existingProject.Spec.OpenAccess {
return false, fmt.Errorf("%s %s", "OpenAccess", errorImmutableFieldMsg)
}

return true, nil
}
5 changes: 5 additions & 0 deletions config/crd/bases/jiraservicedesk.stakater.com_projects.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ spec:
notificationScheme:
description: The ID of the notification scheme for the project
type: integer
openAccess:
description: The Open Access status, which dictates who can access the
project. If set to true all customers can access the project. If false,
only customers added to project can access the project.
type: boolean
permissionScheme:
description: The ID of the permission scheme for the project
type: integer
Expand Down
11 changes: 11 additions & 0 deletions controllers/project_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,16 @@ func (r *ProjectReconciler) handleCreate(req ctrl.Request, instance *jiraservice
}

log.Info("Successfully created Jira Service Desk Project: " + instance.Spec.Name)

if !instance.Spec.OpenAccess {
err = r.JiraServiceDeskClient.UpdateProjectAccessPermissions(instance.Spec.OpenAccess, project.Key)
if err != nil {
return reconcilerUtil.ManageError(r.Client, instance, err, false)
}

log.Info("Successfully updated the Access Permissions to customer")
}

instance.Status.ID = projectId
return reconcilerUtil.ManageSuccess(r.Client, instance)
}
Expand Down Expand Up @@ -180,6 +190,7 @@ func (r *ProjectReconciler) handleUpdate(req ctrl.Request, existingProject jiras
if ok, err := instance.IsValidUpdate(existingProjectInstance); !ok {
return reconcilerUtil.ManageError(r.Client, instance, err, false)
}

updatedProject := r.JiraServiceDeskClient.GetProjectForUpdateRequest(existingProject, instance)
err := r.JiraServiceDeskClient.UpdateProject(updatedProject, existingProject.Id)
if err != nil {
Expand Down
1 change: 0 additions & 1 deletion examples/project/classic-project.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,3 @@ spec:
assigneeType: PROJECT_LEAD
leadAccountId: 5ebfbc3ead226b0ba46c3590
url: https://stakater.com

4 changes: 2 additions & 2 deletions mock/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ var ProjectIDInt, _ = strconv.Atoi(ProjectID)
var InvalidPermissionScheme = "4000"

var GetProjectFailedErrorMsg = "Rest request to get Project failed with status: 404"
var CreateProjectFailedErrorMsg = "Rest request to create Project failed with status 400 and response: "
var UpdateProjectFailedErrorMsg = "Rest request to update Project failed with status 404 and response: "
var CreateProjectFailedErrorMsg = "Rest request to create Project failed with status: 400 and response: "
var UpdateProjectFailedErrorMsg = "Rest request to update Project failed with status: 404 and response: "
var DeleteProjectFailedErrorMsg = "Rest request to delete Project failed with status: 404"

var CreateProjectInputJSON = map[string]string{
Expand Down
1 change: 1 addition & 0 deletions pkg/jiraservicedesk/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ type Client interface {
UpdateProject(updatedProject Project, id string) error
ProjectEqual(oldProject Project, newProject Project) bool
GetProjectForUpdateRequest(existingProject Project, newProject *jiraservicedeskv1alpha1.Project) Project
UpdateProjectAccessPermissions(status bool, key string) error
GetCustomerById(customerAccountId string) (Customer, error)
CreateCustomer(customer Customer) (string, error)
AddCustomerToProject(customerAccountId string, projectKey string) error
Expand Down
43 changes: 40 additions & 3 deletions pkg/jiraservicedesk/client/client_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import (
const (
// Endpoints
EndpointApiVersion3Project = "/rest/api/3/project"
ServiceDeskV1ApiPath = "/rest/servicedesk/1/servicedesk/"
RequestSecurityPath = "/settings/requestsecurity"

// Project Template Types
ClassicProjectTemplateKey = "com.atlassian.servicedesk:itil-v2-service-desk-project"
Expand Down Expand Up @@ -59,6 +61,13 @@ type ProjectCreateResponse struct {
Key string `json:"key"`
}

type CustomerAccessRequestBody struct {
autocompleteEnabled bool
manageEnabled bool
serviceDeskOpenAccess bool
serviceDeskPublicSignup bool
}

func (c *jiraServiceDeskClient) GetProjectById(id string) (Project, error) {
var project Project

Expand Down Expand Up @@ -103,7 +112,7 @@ func (c *jiraServiceDeskClient) CreateProject(project Project) (string, error) {
responseData, _ := ioutil.ReadAll(response.Body)

if response.StatusCode < 200 || response.StatusCode > 299 {
err := errors.New("Rest request to create Project failed with status " + strconv.Itoa(response.StatusCode) +
err := errors.New("Rest request to create Project failed with status: " + strconv.Itoa(response.StatusCode) +
" and response: " + string(responseData))
return "", err
}
Expand Down Expand Up @@ -133,7 +142,7 @@ func (c *jiraServiceDeskClient) UpdateProject(updatedProject Project, id string)
responseData, _ := ioutil.ReadAll(response.Body)

if response.StatusCode < 200 || response.StatusCode > 299 {
err := errors.New("Rest request to update Project failed with status " + strconv.Itoa(response.StatusCode) +
err := errors.New("Rest request to update Project failed with status: " + strconv.Itoa(response.StatusCode) +
" and response: " + string(responseData))
return err
}
Expand All @@ -152,13 +161,41 @@ func (c *jiraServiceDeskClient) DeleteProject(id string) error {
return err
}

if response.StatusCode != 204 {
if response.StatusCode < 200 || response.StatusCode > 299 {
return errors.New("Rest request to delete Project failed with status: " + strconv.Itoa(response.StatusCode))
}

return err
}

func (c *jiraServiceDeskClient) UpdateProjectAccessPermissions(status bool, key string) error {
body := CustomerAccessRequestBody{
autocompleteEnabled: false,
manageEnabled: false,
serviceDeskOpenAccess: status,
serviceDeskPublicSignup: status,
}

request, err := c.newRequest("POST", ServiceDeskV1ApiPath+key+RequestSecurityPath, body, false)
if err != nil {
return err
}

response, err := c.do(request)
if err != nil {
return err
}

defer response.Body.Close()

if response.StatusCode < 200 || response.StatusCode > 299 {
err := errors.New("Rest request to update project permissions failed with status: " + strconv.Itoa(response.StatusCode))
return err
}

return err
}

func (c *jiraServiceDeskClient) ProjectEqual(oldProject Project, newProject Project) bool {
// The fields AvatarId, IssueSecurityScheme, NotificationScheme, PermissionScheme, CategoryId are not retrieved
// through get project REST API call so they cannot be used in project comparison
Expand Down

0 comments on commit fbeb210

Please sign in to comment.