syntax = "proto3";

package com.wixpress.authorization.abac.management;

import "google/api/annotations.proto";
import "wix/api/validations.proto";
import "wix/api/permissions.proto";
import "wix/api/annotations.proto";
import "google/protobuf/wrappers.proto";
import "com/wixpress/authorization/abac/management/Conditions.proto";
import "com/wixpress/authorization/abac/management/Policy.proto";
import "com/wixpress/authorization/abac/management/Subject.proto";
import "com/wixpress/authorization/abac/Context.proto";
import "wix/api/entity.proto";

service AbacManagementService {
    option (wix.api.service_exposure) = INTERNAL;

    option (wix.api.service_entity).message = "com.wixpress.authorization.abac.management.Policy";
    // This service is used to manage authorization data. Use it in order to CRUD over policies, and assign them to subjects.
    // If you need to simply assign policies to team members to contributors, you can use the typed services:
    // AccountPoliciesManagement and SitePoliciesManagement

    // An API to create a new policy (custom or predefined). In order to create a custom policy use AccountPoliciesManagement.CreatePolicy
    //flynt-disable missing-cud-event
    rpc CreatePolicy (CreatePolicyRequest) returns (CreatePolicyResponse) {
        option (wix.api.required) = "CreatePolicyRequest.policy";
        option (wix.api.required) = "CreatePolicyRequest.policy.name";
        option (google.api.http).post = "/v1/policies/predefined";
        option (.wix.api.crud) = {
            method: CREATE
            create_options: {
                item_field: "policy"
            }
        };
    }

    // An API to delete a policy
    //flynt-disable missing-cud-event
    //flynt-disable crud-add-delete-annotation
    rpc DeletePolicy (DeletePolicyRequest) returns (DeletePolicyResponse) {
        option (wix.api.required) = "DeletePolicyRequest.policy_id";
        option (google.api.http).delete = "/v1/policies/predefined/{policy_id}";
    }

    // Policies are devided into metadata and authorization data. The authorization data includes all the statements.
    // This endpoint overrides the existing authorization data of the policy with the one passed (it is not an append API)
    rpc UpdatePolicyAuthorizationData (UpdatePolicyAuthorizationDataRequest) returns (UpdatePolicyResponse) {
        option (wix.api.required) = "UpdatePolicyAuthorizationDataRequest.policy_id";
        option (google.api.http).put = "/v1/policies/predefined/{policy_id}/authorization-data";
    }

    // Adds a new statement to the given policy.
    rpc AddStatementToPolicy (AddStatementToPolicyRequest) returns (AddStatementToPolicyResponse) {
        option (wix.api.required) = "AddStatementToPolicyRequest.policy_id";
        option (wix.api.required) = "AddStatementToPolicyRequest.policy_statement";
        option (google.api.http).put = "/v1/policies/predefined/{policy_id}/add-statement";
        option (wix.api.permission) = {
            name: "MANAGE_POLICIES"
            type: MANUAL
        };
    }

    // Policies are devided into metadata and authorization data.
    // This endpoint updates the metadata of the policy, without affecting isPermitted / Query.
    rpc UpdatePolicyMetadata (UpdatePolicyMetadataRequest) returns (UpdatePolicyResponse) {
        option (wix.api.required) = "UpdatePolicyMetadataRequest.policy_id";
        option (google.api.http).patch = "/v1/policies/predefined/{policy_id}/metadata";
    }

    // Returns the policy with the specified id.
    rpc GetPolicy (GetPolicyRequest) returns (GetPolicyResponse) {
        option (wix.api.required) = "GetPolicyRequest.policy_id";
        option (google.api.http).get = "/v1/policies/{policy_id}";
        option (.wix.api.crud) = {
            method: GET_ITEM
            get_options: {
                id_field: "policy_id"
                item_field: "policy"
            }
        };
    }

    // Returns all of the predefined policies that exist in the system.
    rpc GetPolicies (GetPoliciesRequest) returns (GetPoliciesResponse) {
        option (google.api.http).get = "/v1/management/policies";
    }

    // This endpoint deletes a specific endpoint from a policy.
    //flynt-disable missing-cud-event
    rpc DeletePolicyStatement (DeletePolicyStatementRequest) returns (DeletePolicyStatementResponse) {
        option (wix.api.required) = "DeletePolicyStatementRequest.statement_id";
        option (google.api.http).delete = "/v1/statements/{statement_id}";
        option (.wix.api.crud) = {
            method: DELETE
            delete_options: {
                id_field: "statement_id"
            }
        };
    }

    // This endpoint assign a policy to a subject. If you need to assign a role to a contributor or to a team member,
    // Please use the typed APIs - AccountPoliciesManagement and SitePoliciesManagement
    rpc AssignPolicy (AssignPolicyRequest) returns (AssignPolicyResponse) {
        option (wix.api.required) = "AssignPolicyRequest.subject";
        option (wix.api.required) = "AssignPolicyRequest.subject.id";
        option (wix.api.required) = "AssignPolicyRequest.policy_id";
        option (wix.api.required) = "AssignPolicyRequest.resource_context";
        option (google.api.http).post = "/v1/policies/{policy_id}/assignments";
    };

    // Does the opposite of `assignPolicy`.
    // If you need to assign a role to a contributor or to a team member - please use the typed APIs - AccountPoliciesManagement and SitePoliciesManagement
    rpc UnassignPolicyFromSubject (UnassignPolicyFromSubjectRequest) returns (UnassignPolicyFromSubjectResponse) {
        option (wix.api.required) = "UnassignPolicyFromSubjectRequest.subject";
        option (wix.api.required) = "UnassignPolicyFromSubjectRequest.subject.id";
        option (wix.api.required) = "UnassignPolicyFromSubjectRequest.policy_id";
        option (wix.api.required) = "UnassignPolicyFromSubjectRequest.resource_context";
        option (google.api.http).delete = "/v1/policies/{policy_id}/assignments/subject/{subject.id}";
    };

    // Deletes assignments by ids
    rpc DeleteAssignments (DeleteAssignmentsRequest) returns (DeleteAssignmentsResponse) {
        option (wix.api.required) = "DeleteAssignmentsRequest.assignment_ids";
        option (google.api.http).delete = "/v1/policies/assignments";
    };

    // Update assignment by id
    rpc UpdateAssignment (UpdateAssignmentRequest) returns (UpdateAssignmentResponse) {
        option (wix.api.required) = "UpdateAssignmentRequest.assignment_id";
        option (google.api.http).put = "/v1/policies/assignments";
        option (wix.api.permission).name = "AUTHORIZATION.UPDATE_ASSIGNMENT_RESOURCE";
    };

    // In case the policy have statements with a condition on the passed spec, this endpoint merges the experiment based on the winning value
    // If the winning value is the expected value - the statement will remain without it. Otherwise - it will be removed.
    rpc FoldExperiment(FoldExperimentRequest) returns (FoldExperimentResponse) {
        option (wix.api.required) = "FoldExperimentRequest.policy_id";
        option (wix.api.required) = "FoldExperimentRequest.spec";
        option (wix.api.required) = "FoldExperimentRequest.winning_value";
        option (google.api.http).post = "/v1/policies/experiments/{policy_id}/fold";
    }
}

message CreatePolicyRequest {
    // The policy to create
    Policy policy = 1;
}

message CreatePolicyResponse {
    // The created policy
    Policy policy = 1;
}

message UpdatePolicyAuthorizationDataRequest {
    // The id of the policy to update
    string policy_id = 1;
    // A list of the new statements. They will override any existing statements.
    repeated PolicyStatement policy_statements = 2;
}

message AddStatementToPolicyRequest {
    // The id of the policy to update.
    string policy_id = 1;
    // A new statement to add to the policy.
    PolicyStatement policy_statement = 2;
}

message AddStatementToPolicyResponse {
    // The id of the newly created statement.
    string statement_id = 1;
}

message UpdatePolicyMetadataRequest {
    // The id of the policy to update.
    string policy_id = 1;
    // The new name of the policy. If empty - the old name won't be overriden.
    google.protobuf.StringValue name = 2 [(wix.api.maxLength) = 50];
    // The description of the policy. If empty - the old value won't be overriden.
    google.protobuf.StringValue description = 3 [(wix.api.maxLength) = 500];
    // The status of the policy. Can be either "ACTIVE" or "INACTIVE".
    google.protobuf.StringValue status = 4;
}

message UpdatePolicyResponse {
    // Whether or not the update was successful (might not be successful in case the policy doesn't exist).
    bool updated = 1;
    // The updated policy
    Policy policy = 2;
}

message GetPolicyRequest {
    // The id of the policy to return
    string policy_id = 1;
}

message GetPolicyResponse {
    // The full policy.
    Policy policy = 1;
}

message GetPoliciesRequest {}

message GetPoliciesResponse {
    repeated com.wixpress.authorization.abac.management.Policy policies = 1;
}

message DeletePolicyRequest {
    string policy_id = 1;
}

message DeletePolicyResponse {
    // Whether or not something was deleted.
    bool deleted = 1;
}

message DeleteAssignmentsRequest {
    repeated string assignment_ids = 1;
}

message DeleteAssignmentsResponse {
    repeated string deleted_assignment_ids = 1;
}

message UpdateAssignmentRequest {
    string assignment_id = 1;
    repeated AssignmentUpdateField assignment_fields = 2;
}

message AssignmentUpdateField {
    oneof assignment_field {
        ResourceUpdate assignment_resource = 1;
    }
}

message ResourceUpdate {
    oneof update {
        Resource resource = 1;
        AllResources all_resources = 2;
    }
}

message AllResources {

}

message UpdateAssignmentResponse {
}

message DeletePolicyStatementRequest {
    // The statement id to delete.
    string statement_id = 1;
}

message DeletePolicyStatementResponse {
    // Whether or not something was deleted.
    bool deleted = 1;
    // The update policy
    Policy policy = 2;
}

message AssignPolicyRequest {
    // The subject to assign to policy to.
    Subject subject = 1;
    // The id of the policy to assign.
    string policy_id = 2;
    // The context of the resource. It can be either site, account or organization.
    ResourceContext resource_context = 3;
    // A condition the is applied on the assignment. Can be a limit on some attribute that needs to be passed on isPermitted
    PolicyCondition condition = 4;
    // The resource you assign the policy to. Can be left empty in case of direct assignment on account/site.
    // However, if it's a custom resource, it must be specified here.
    Resource resource = 5;
}

message AssignPolicyResponse {
    // The unique id of the assignment.
    string assignment_id = 1;
}

message UnassignPolicyFromSubjectRequest {
    // The subject to unassign to policy from.
    Subject subject = 1;
    // The policy id to unassign.
    string policy_id = 2;
    // From which resource context to unassign the policy.
    ResourceContext resource_context = 3;
    // The resource you assign the policy to. Can be left empty in case of direct assignment on account/site.
    // However, if it's a custom resource, it must be specified here.
    Resource resource = 4;
}

message UnassignPolicyFromSubjectResponse {
    // The number of assignments that were unassigned.
    int32 assignments_count = 1;
}

message FoldExperimentRequest {
    // The id of the policy to find and fold the experiment on
    string policy_id = 1;
    // The spec to search and fold.
    string spec = 2;
    // The winning value of the experiment, AKA the desired state.
    string winning_value = 3;
}

message FoldExperimentResponse {

}
