Add role management
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
707
pkg/authz/permissions.go
Normal file
707
pkg/authz/permissions.go
Normal file
@@ -0,0 +1,707 @@
|
||||
// Copyright (c) 2025 Probo Inc <hello@getprobo.com>.
|
||||
//
|
||||
// Permission to use, copy, modify, and/or distribute this software for any
|
||||
// purpose with or without fee is hereby granted, provided that the above
|
||||
// copyright notice and this permission notice appear in all copies.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
// PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
package authz
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"go.probo.inc/probo/pkg/coredata"
|
||||
)
|
||||
|
||||
type (
|
||||
Role string
|
||||
|
||||
Action string
|
||||
)
|
||||
|
||||
const (
|
||||
RoleOwner Role = "OWNER"
|
||||
RoleAdmin Role = "ADMIN"
|
||||
RoleViewer Role = "VIEWER"
|
||||
RoleFull Role = "FULL"
|
||||
)
|
||||
|
||||
const (
|
||||
ActionGet Action = "get"
|
||||
|
||||
ActionGetAssetType Action = "getAssetType"
|
||||
ActionGetAssignedTo Action = "getAssignedTo"
|
||||
ActionGetAuthMethod Action = "getAuthMethod"
|
||||
ActionGetBusinessAssociateAgreement Action = "getBusinessAssociateAgreement"
|
||||
ActionGetBusinessOwner Action = "getBusinessOwner"
|
||||
ActionGetCustomDomain Action = "getCustomDomain"
|
||||
ActionGetDataPrivacyAgreement Action = "getDataPrivacyAgreement"
|
||||
ActionGetFile Action = "getFile"
|
||||
ActionGetFileUrl Action = "getFileUrl"
|
||||
ActionGetFramework Action = "getFramework"
|
||||
ActionGetHorizontalLogoUrl Action = "getHorizontalLogoUrl"
|
||||
ActionGetLogoUrl Action = "getLogoUrl"
|
||||
ActionGetMeasure Action = "getMeasure"
|
||||
ActionGetNdaFileUrl Action = "getNdaFileUrl"
|
||||
ActionGetOrganization Action = "getOrganization"
|
||||
ActionGetOwner Action = "getOwner"
|
||||
ActionGetSecurityOwner Action = "getSecurityOwner"
|
||||
ActionGetSnapshot Action = "getSnapshot"
|
||||
ActionGetTask Action = "getTask"
|
||||
ActionGetTrustCenter Action = "getTrustCenter"
|
||||
ActionGetTrustCenterFile Action = "getTrustCenterFile"
|
||||
ActionGetVendor Action = "getVendor"
|
||||
|
||||
ActionActiveCount Action = "activeCount"
|
||||
ActionAudit Action = "audit"
|
||||
ActionAvailableDocumentAccesses Action = "availableDocumentAccesses"
|
||||
ActionDocument Action = "document"
|
||||
ActionDocumentVersion Action = "documentVersion"
|
||||
ActionDownloadUrl Action = "downloadUrl"
|
||||
ActionMemberships Action = "memberships"
|
||||
ActionPendingRequestCount Action = "pendingRequestCount"
|
||||
ActionPeoples Action = "peoples"
|
||||
ActionReport Action = "report"
|
||||
ActionReportUrl Action = "reportUrl"
|
||||
ActionSignatures Action = "signatures"
|
||||
ActionSignedBy Action = "signedBy"
|
||||
ActionSpMetadataUrl Action = "spMetadataUrl"
|
||||
ActionTestLoginUrl Action = "testLoginUrl"
|
||||
ActionTotalCount Action = "totalCount"
|
||||
ActionTrustCenterFile Action = "trustCenterFile"
|
||||
|
||||
ActionListAccesses Action = "listAccesses"
|
||||
ActionListAssets Action = "listAssets"
|
||||
ActionListAudits Action = "listAudits"
|
||||
ActionListComplianceReports Action = "listComplianceReports"
|
||||
ActionListContacts Action = "listContacts"
|
||||
ActionListContinualImprovements Action = "listContinualImprovements"
|
||||
ActionListControls Action = "listControls"
|
||||
ActionListData Action = "listData"
|
||||
ActionListDocuments Action = "listDocuments"
|
||||
ActionListEvidences Action = "listEvidences"
|
||||
ActionListFrameworks Action = "listFrameworks"
|
||||
ActionListInvitations Action = "listInvitations"
|
||||
ActionListMeasures Action = "listMeasures"
|
||||
ActionListMeetings Action = "listMeetings"
|
||||
ActionListMembers Action = "listMembers"
|
||||
ActionListNonconformities Action = "listNonconformities"
|
||||
ActionListObligations Action = "listObligations"
|
||||
ActionListPeople Action = "listPeople"
|
||||
ActionListProcessingActivities Action = "listProcessingActivities"
|
||||
ActionListReferences Action = "listReferences"
|
||||
ActionListRiskAssessments Action = "listRiskAssessments"
|
||||
ActionListRisks Action = "listRisks"
|
||||
ActionListSAMLConfigurations Action = "listSAMLConfigurations"
|
||||
ActionListServices Action = "listServices"
|
||||
ActionListSlackConnections Action = "listSlackConnections"
|
||||
ActionListSnapshots Action = "listSnapshots"
|
||||
ActionListTasks Action = "listTasks"
|
||||
ActionListTrustCenterFiles Action = "listTrustCenterFiles"
|
||||
ActionListVendors Action = "listVendors"
|
||||
ActionListVersions Action = "listVersions"
|
||||
|
||||
ActionCreateAsset Action = "createAsset"
|
||||
ActionCreateAudit Action = "createAudit"
|
||||
ActionCreateContinualImprovement Action = "createContinualImprovement"
|
||||
ActionCreateControl Action = "createControl"
|
||||
ActionCreateControlAuditMapping Action = "createControlAuditMapping"
|
||||
ActionCreateControlDocumentMapping Action = "createControlDocumentMapping"
|
||||
ActionCreateControlMeasureMapping Action = "createControlMeasureMapping"
|
||||
ActionCreateControlSnapshotMapping Action = "createControlSnapshotMapping"
|
||||
ActionCreateCustomDomain Action = "createCustomDomain"
|
||||
ActionCreateDatum Action = "createDatum"
|
||||
ActionCreateDocument Action = "createDocument"
|
||||
ActionCreateDraftDocumentVersion Action = "createDraftDocumentVersion"
|
||||
ActionCreateFramework Action = "createFramework"
|
||||
ActionCreateMeasure Action = "createMeasure"
|
||||
ActionCreateMeeting Action = "createMeeting"
|
||||
ActionCreateNonconformity Action = "createNonconformity"
|
||||
ActionCreateObligation Action = "createObligation"
|
||||
ActionCreatePeople Action = "createPeople"
|
||||
ActionCreateProcessingActivity Action = "createProcessingActivity"
|
||||
ActionCreateRisk Action = "createRisk"
|
||||
ActionCreateRiskDocumentMapping Action = "createRiskDocumentMapping"
|
||||
ActionCreateRiskMeasureMapping Action = "createRiskMeasureMapping"
|
||||
ActionCreateRiskObligationMapping Action = "createRiskObligationMapping"
|
||||
ActionCreateSAMLConfiguration Action = "createSAMLConfiguration"
|
||||
ActionCreateSnapshot Action = "createSnapshot"
|
||||
ActionCreateTask Action = "createTask"
|
||||
ActionCreateTrustCenter Action = "createTrustCenter"
|
||||
ActionCreateTrustCenterAccess Action = "createTrustCenterAccess"
|
||||
ActionCreateTrustCenterFile Action = "createTrustCenterFile"
|
||||
ActionCreateTrustCenterReference Action = "createTrustCenterReference"
|
||||
ActionCreateVendor Action = "createVendor"
|
||||
ActionCreateVendorContact Action = "createVendorContact"
|
||||
ActionCreateVendorRiskAssessment Action = "createVendorRiskAssessment"
|
||||
ActionCreateVendorService Action = "createVendorService"
|
||||
|
||||
ActionUpdateAsset Action = "updateAsset"
|
||||
ActionUpdateAudit Action = "updateAudit"
|
||||
ActionUpdateContinualImprovement Action = "updateContinualImprovement"
|
||||
ActionUpdateControl Action = "updateControl"
|
||||
ActionUpdateDatum Action = "updateDatum"
|
||||
ActionUpdateDocument Action = "updateDocument"
|
||||
ActionUpdateDocumentVersion Action = "updateDocumentVersion"
|
||||
ActionUpdateFramework Action = "updateFramework"
|
||||
ActionUpdateMeasure Action = "updateMeasure"
|
||||
ActionUpdateMeeting Action = "updateMeeting"
|
||||
ActionUpdateMembership Action = "updateMembership"
|
||||
ActionUpdateNonconformity Action = "updateNonconformity"
|
||||
ActionUpdateObligation Action = "updateObligation"
|
||||
ActionUpdateOrganization Action = "updateOrganization"
|
||||
ActionUpdatePeople Action = "updatePeople"
|
||||
ActionUpdateProcessingActivity Action = "updateProcessingActivity"
|
||||
ActionUpdateRisk Action = "updateRisk"
|
||||
ActionUpdateSAMLConfiguration Action = "updateSAMLConfiguration"
|
||||
ActionUpdateTask Action = "updateTask"
|
||||
ActionUpdateTrustCenter Action = "updateTrustCenter"
|
||||
ActionUpdateTrustCenterAccess Action = "updateTrustCenterAccess"
|
||||
ActionUpdateTrustCenterFile Action = "updateTrustCenterFile"
|
||||
ActionUpdateTrustCenterReference Action = "updateTrustCenterReference"
|
||||
ActionUpdateVendor Action = "updateVendor"
|
||||
ActionUpdateVendorBusinessAssociateAgreement Action = "updateVendorBusinessAssociateAgreement"
|
||||
ActionUpdateVendorContact Action = "updateVendorContact"
|
||||
ActionUpdateVendorDataPrivacyAgreement Action = "updateVendorDataPrivacyAgreement"
|
||||
ActionUpdateVendorService Action = "updateVendorService"
|
||||
|
||||
ActionDeleteAsset Action = "deleteAsset"
|
||||
ActionDeleteAudit Action = "deleteAudit"
|
||||
ActionDeleteAuditReport Action = "deleteAuditReport"
|
||||
ActionDeleteContinualImprovement Action = "deleteContinualImprovement"
|
||||
ActionDeleteControl Action = "deleteControl"
|
||||
ActionDeleteControlAuditMapping Action = "deleteControlAuditMapping"
|
||||
ActionDeleteControlDocumentMapping Action = "deleteControlDocumentMapping"
|
||||
ActionDeleteControlMeasureMapping Action = "deleteControlMeasureMapping"
|
||||
ActionDeleteControlSnapshotMapping Action = "deleteControlSnapshotMapping"
|
||||
ActionDeleteCustomDomain Action = "deleteCustomDomain"
|
||||
ActionDeleteDatum Action = "deleteDatum"
|
||||
ActionDeleteDocument Action = "deleteDocument"
|
||||
ActionDeleteDraftDocumentVersion Action = "deleteDraftDocumentVersion"
|
||||
ActionDeleteEvidence Action = "deleteEvidence"
|
||||
ActionDeleteFramework Action = "deleteFramework"
|
||||
ActionDeleteInvitation Action = "deleteInvitation"
|
||||
ActionDeleteMeasure Action = "deleteMeasure"
|
||||
ActionDeleteMeeting Action = "deleteMeeting"
|
||||
ActionDeleteNonconformity Action = "deleteNonconformity"
|
||||
ActionDeleteObligation Action = "deleteObligation"
|
||||
ActionDeleteOrganization Action = "deleteOrganization"
|
||||
ActionDeleteOrganizationHorizontalLogo Action = "deleteOrganizationHorizontalLogo"
|
||||
ActionDeletePeople Action = "deletePeople"
|
||||
ActionDeleteProcessingActivity Action = "deleteProcessingActivity"
|
||||
ActionDeleteRisk Action = "deleteRisk"
|
||||
ActionDeleteRiskDocumentMapping Action = "deleteRiskDocumentMapping"
|
||||
ActionDeleteRiskMeasureMapping Action = "deleteRiskMeasureMapping"
|
||||
ActionDeleteRiskObligationMapping Action = "deleteRiskObligationMapping"
|
||||
ActionDeleteSAMLConfiguration Action = "deleteSAMLConfiguration"
|
||||
ActionDeleteSnapshot Action = "deleteSnapshot"
|
||||
ActionDeleteTask Action = "deleteTask"
|
||||
ActionDeleteTrustCenterAccess Action = "deleteTrustCenterAccess"
|
||||
ActionDeleteTrustCenterFile Action = "deleteTrustCenterFile"
|
||||
ActionDeleteTrustCenterNDA Action = "deleteTrustCenterNDA"
|
||||
ActionDeleteTrustCenterReference Action = "deleteTrustCenterReference"
|
||||
ActionDeleteVendor Action = "deleteVendor"
|
||||
ActionDeleteVendorBusinessAssociateAgreement Action = "deleteVendorBusinessAssociateAgreement"
|
||||
ActionDeleteVendorComplianceReport Action = "deleteVendorComplianceReport"
|
||||
ActionDeleteVendorContact Action = "deleteVendorContact"
|
||||
ActionDeleteVendorDataPrivacyAgreement Action = "deleteVendorDataPrivacyAgreement"
|
||||
ActionDeleteVendorService Action = "deleteVendorService"
|
||||
|
||||
ActionAcceptInvitation Action = "acceptInvitation"
|
||||
ActionAssessVendor Action = "assessVendor"
|
||||
ActionAssignTask Action = "assignTask"
|
||||
ActionBulkDeleteDocuments Action = "bulkDeleteDocuments"
|
||||
ActionBulkExportDocuments Action = "bulkExportDocuments"
|
||||
ActionBulkPublishDocumentVersions Action = "bulkPublishDocumentVersions"
|
||||
ActionBulkRequestSignatures Action = "bulkRequestSignatures"
|
||||
ActionCancelSignatureRequest Action = "cancelSignatureRequest"
|
||||
ActionConfirmEmail Action = "confirmEmail"
|
||||
ActionDisableSAML Action = "disableSAML"
|
||||
ActionEnableSAML Action = "enableSAML"
|
||||
ActionExportDocumentVersionPDF Action = "exportDocumentVersionPDF"
|
||||
ActionExportFramework Action = "exportFramework"
|
||||
ActionGenerateDocumentChangelog Action = "generateDocumentChangelog"
|
||||
ActionGenerateFrameworkStateOfApplicability Action = "generateFrameworkStateOfApplicability"
|
||||
ActionImportFramework Action = "importFramework"
|
||||
ActionImportMeasure Action = "importMeasure"
|
||||
ActionInitiateDomainVerification Action = "initiateDomainVerification"
|
||||
ActionInviteUser Action = "inviteUser"
|
||||
ActionPublishDocumentVersion Action = "publishDocumentVersion"
|
||||
ActionRemoveMember Action = "removeMember"
|
||||
ActionRequestSignature Action = "requestSignature"
|
||||
ActionSendSigningNotifications Action = "sendSigningNotifications"
|
||||
ActionUnassignTask Action = "unassignTask"
|
||||
ActionUploadAuditReport Action = "uploadAuditReport"
|
||||
ActionUploadMeasureEvidence Action = "uploadMeasureEvidence"
|
||||
ActionUploadTrustCenterNDA Action = "uploadTrustCenterNDA"
|
||||
ActionUploadVendorBusinessAssociateAgreement Action = "uploadVendorBusinessAssociateAgreement"
|
||||
ActionUploadVendorComplianceReport Action = "uploadVendorComplianceReport"
|
||||
ActionUploadVendorDataPrivacyAgreement Action = "uploadVendorDataPrivacyAgreement"
|
||||
ActionVerifyDomain Action = "verifyDomain"
|
||||
)
|
||||
|
||||
var (
|
||||
AllRoles = []Role{RoleOwner, RoleAdmin, RoleViewer, RoleFull}
|
||||
EditRoles = []Role{RoleOwner, RoleAdmin, RoleFull}
|
||||
)
|
||||
|
||||
var Permissions = map[uint16]map[Action][]Role{
|
||||
coredata.OrganizationEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetLogoUrl: AllRoles,
|
||||
ActionGetHorizontalLogoUrl: AllRoles,
|
||||
ActionMemberships: AllRoles,
|
||||
ActionPeoples: AllRoles,
|
||||
ActionTotalCount: AllRoles,
|
||||
ActionListMembers: AllRoles,
|
||||
ActionListInvitations: AllRoles,
|
||||
ActionListSlackConnections: AllRoles,
|
||||
ActionListFrameworks: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
ActionListVendors: AllRoles,
|
||||
ActionListPeople: AllRoles,
|
||||
ActionListDocuments: AllRoles,
|
||||
ActionListMeetings: AllRoles,
|
||||
ActionListMeasures: AllRoles,
|
||||
ActionListRisks: AllRoles,
|
||||
ActionListTasks: AllRoles,
|
||||
ActionListAssets: AllRoles,
|
||||
ActionListData: AllRoles,
|
||||
ActionListAudits: AllRoles,
|
||||
ActionListNonconformities: AllRoles,
|
||||
ActionListObligations: AllRoles,
|
||||
ActionListContinualImprovements: AllRoles,
|
||||
ActionListProcessingActivities: AllRoles,
|
||||
ActionListSnapshots: AllRoles,
|
||||
ActionListTrustCenterFiles: AllRoles,
|
||||
ActionGetTrustCenter: AllRoles,
|
||||
ActionGetCustomDomain: AllRoles,
|
||||
ActionListSAMLConfigurations: AllRoles,
|
||||
ActionConfirmEmail: AllRoles,
|
||||
ActionAcceptInvitation: AllRoles,
|
||||
|
||||
ActionUpdateOrganization: EditRoles,
|
||||
ActionDeleteOrganizationHorizontalLogo: EditRoles,
|
||||
ActionCreateTrustCenter: EditRoles,
|
||||
ActionInviteUser: EditRoles,
|
||||
ActionDeleteInvitation: EditRoles,
|
||||
ActionUpdateMembership: EditRoles,
|
||||
ActionCreatePeople: EditRoles,
|
||||
ActionCreateVendor: EditRoles,
|
||||
ActionCreateFramework: EditRoles,
|
||||
ActionImportFramework: EditRoles,
|
||||
ActionCreateControl: EditRoles,
|
||||
ActionCreateMeasure: EditRoles,
|
||||
ActionImportMeasure: EditRoles,
|
||||
ActionCreateMeeting: EditRoles,
|
||||
ActionCreateTask: EditRoles,
|
||||
ActionCreateRisk: EditRoles,
|
||||
ActionCreateDocument: EditRoles,
|
||||
ActionCreateAsset: EditRoles,
|
||||
ActionCreateDatum: EditRoles,
|
||||
ActionCreateAudit: EditRoles,
|
||||
ActionCreateNonconformity: EditRoles,
|
||||
ActionCreateObligation: EditRoles,
|
||||
ActionCreateContinualImprovement: EditRoles,
|
||||
ActionCreateProcessingActivity: EditRoles,
|
||||
ActionCreateSnapshot: EditRoles,
|
||||
ActionCreateTrustCenterFile: EditRoles,
|
||||
ActionSendSigningNotifications: EditRoles,
|
||||
|
||||
ActionRemoveMember: {RoleOwner, RoleFull},
|
||||
|
||||
ActionCreateCustomDomain: {RoleOwner},
|
||||
ActionInitiateDomainVerification: {RoleOwner},
|
||||
ActionVerifyDomain: {RoleOwner},
|
||||
ActionCreateSAMLConfiguration: {RoleOwner},
|
||||
ActionDeleteOrganization: {RoleOwner},
|
||||
},
|
||||
coredata.TrustCenterEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetNdaFileUrl: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListAccesses: AllRoles,
|
||||
ActionListReferences: AllRoles,
|
||||
|
||||
ActionUpdateTrustCenter: EditRoles,
|
||||
ActionUploadTrustCenterNDA: EditRoles,
|
||||
ActionDeleteTrustCenterNDA: EditRoles,
|
||||
ActionCreateTrustCenterAccess: EditRoles,
|
||||
ActionCreateTrustCenterReference: EditRoles,
|
||||
},
|
||||
coredata.TrustCenterAccessEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionActiveCount: AllRoles,
|
||||
ActionPendingRequestCount: AllRoles,
|
||||
ActionAvailableDocumentAccesses: AllRoles,
|
||||
|
||||
ActionUpdateTrustCenterAccess: EditRoles,
|
||||
ActionDeleteTrustCenterAccess: EditRoles,
|
||||
},
|
||||
coredata.TrustCenterReferenceEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetLogoUrl: AllRoles,
|
||||
|
||||
ActionUpdateTrustCenterReference: EditRoles,
|
||||
ActionDeleteTrustCenterReference: EditRoles,
|
||||
},
|
||||
coredata.TrustCenterFileEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFileUrl: AllRoles,
|
||||
|
||||
ActionUpdateTrustCenterFile: EditRoles,
|
||||
ActionGetTrustCenterFile: EditRoles,
|
||||
ActionDeleteTrustCenterFile: EditRoles,
|
||||
},
|
||||
coredata.UserEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
},
|
||||
coredata.MembershipEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetAuthMethod: AllRoles,
|
||||
},
|
||||
coredata.InvitationEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
},
|
||||
coredata.PeopleEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
|
||||
ActionUpdatePeople: EditRoles,
|
||||
ActionDeletePeople: EditRoles,
|
||||
},
|
||||
coredata.VendorEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListComplianceReports: AllRoles,
|
||||
ActionGetBusinessAssociateAgreement: AllRoles,
|
||||
ActionGetDataPrivacyAgreement: AllRoles,
|
||||
ActionListContacts: AllRoles,
|
||||
ActionListServices: AllRoles,
|
||||
ActionListRiskAssessments: AllRoles,
|
||||
ActionGetBusinessOwner: AllRoles,
|
||||
ActionGetSecurityOwner: AllRoles,
|
||||
|
||||
ActionUpdateVendor: EditRoles,
|
||||
ActionDeleteVendor: EditRoles,
|
||||
ActionCreateVendorContact: EditRoles,
|
||||
ActionCreateVendorService: EditRoles,
|
||||
ActionUploadVendorComplianceReport: EditRoles,
|
||||
ActionUploadVendorBusinessAssociateAgreement: EditRoles,
|
||||
ActionDeleteVendorBusinessAssociateAgreement: EditRoles,
|
||||
ActionUploadVendorDataPrivacyAgreement: EditRoles,
|
||||
ActionCreateVendorRiskAssessment: EditRoles,
|
||||
ActionAssessVendor: EditRoles,
|
||||
},
|
||||
coredata.VendorComplianceReportEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetVendor: AllRoles,
|
||||
ActionGetFile: AllRoles,
|
||||
|
||||
ActionDeleteVendorComplianceReport: EditRoles,
|
||||
},
|
||||
coredata.VendorBusinessAssociateAgreementEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetVendor: AllRoles,
|
||||
ActionGetFileUrl: AllRoles,
|
||||
|
||||
ActionUpdateVendorBusinessAssociateAgreement: EditRoles,
|
||||
ActionDeleteVendorBusinessAssociateAgreement: EditRoles,
|
||||
},
|
||||
coredata.VendorContactEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetVendor: AllRoles,
|
||||
|
||||
ActionUpdateVendorContact: EditRoles,
|
||||
ActionDeleteVendorContact: EditRoles,
|
||||
},
|
||||
coredata.VendorServiceEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetVendor: AllRoles,
|
||||
|
||||
ActionUpdateVendorService: EditRoles,
|
||||
ActionDeleteVendorService: EditRoles,
|
||||
},
|
||||
coredata.VendorDataPrivacyAgreementEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetVendor: AllRoles,
|
||||
ActionGetFileUrl: AllRoles,
|
||||
|
||||
ActionUpdateVendorDataPrivacyAgreement: EditRoles,
|
||||
ActionDeleteVendorDataPrivacyAgreement: EditRoles,
|
||||
},
|
||||
coredata.VendorRiskAssessmentEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
},
|
||||
coredata.FrameworkEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
|
||||
ActionCreateControl: EditRoles,
|
||||
ActionUpdateFramework: EditRoles,
|
||||
ActionDeleteFramework: EditRoles,
|
||||
ActionGenerateFrameworkStateOfApplicability: EditRoles,
|
||||
ActionExportFramework: EditRoles,
|
||||
},
|
||||
coredata.ControlEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFramework: AllRoles,
|
||||
ActionListMeasures: AllRoles,
|
||||
ActionListDocuments: AllRoles,
|
||||
ActionListAudits: AllRoles,
|
||||
ActionListSnapshots: AllRoles,
|
||||
|
||||
ActionUpdateControl: EditRoles,
|
||||
ActionDeleteControl: EditRoles,
|
||||
ActionCreateControlMeasureMapping: EditRoles,
|
||||
ActionCreateControlDocumentMapping: EditRoles,
|
||||
ActionDeleteControlMeasureMapping: EditRoles,
|
||||
ActionDeleteControlDocumentMapping: EditRoles,
|
||||
ActionCreateControlAuditMapping: EditRoles,
|
||||
ActionDeleteControlAuditMapping: EditRoles,
|
||||
ActionCreateControlSnapshotMapping: EditRoles,
|
||||
ActionDeleteControlSnapshotMapping: EditRoles,
|
||||
},
|
||||
coredata.MeasureEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionListEvidences: AllRoles,
|
||||
ActionListTasks: AllRoles,
|
||||
ActionListRisks: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
ActionTotalCount: AllRoles,
|
||||
|
||||
ActionUpdateMeasure: EditRoles,
|
||||
ActionDeleteMeasure: EditRoles,
|
||||
ActionUploadMeasureEvidence: EditRoles,
|
||||
},
|
||||
coredata.TaskEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetAssignedTo: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionGetMeasure: AllRoles,
|
||||
ActionListEvidences: AllRoles,
|
||||
|
||||
ActionUpdateTask: EditRoles,
|
||||
ActionDeleteTask: EditRoles,
|
||||
ActionAssignTask: EditRoles,
|
||||
ActionUnassignTask: EditRoles,
|
||||
},
|
||||
coredata.EvidenceEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFile: AllRoles,
|
||||
ActionGetTask: AllRoles,
|
||||
ActionGetMeasure: AllRoles,
|
||||
|
||||
ActionDeleteEvidence: EditRoles,
|
||||
},
|
||||
coredata.DocumentEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionExportDocumentVersionPDF: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListVersions: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
ActionTotalCount: AllRoles,
|
||||
|
||||
ActionUpdateDocument: EditRoles,
|
||||
ActionDeleteDocument: EditRoles,
|
||||
ActionPublishDocumentVersion: EditRoles,
|
||||
ActionBulkPublishDocumentVersions: EditRoles,
|
||||
ActionBulkDeleteDocuments: EditRoles,
|
||||
ActionBulkExportDocuments: EditRoles,
|
||||
ActionGenerateDocumentChangelog: EditRoles,
|
||||
ActionCreateDraftDocumentVersion: EditRoles,
|
||||
ActionDeleteDraftDocumentVersion: EditRoles,
|
||||
ActionUpdateDocumentVersion: EditRoles,
|
||||
ActionRequestSignature: EditRoles,
|
||||
ActionBulkRequestSignatures: EditRoles,
|
||||
ActionSendSigningNotifications: EditRoles,
|
||||
ActionCancelSignatureRequest: EditRoles,
|
||||
},
|
||||
coredata.DocumentVersionEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFile: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionDocument: AllRoles,
|
||||
ActionSignatures: AllRoles,
|
||||
|
||||
ActionUpdateDocumentVersion: EditRoles,
|
||||
},
|
||||
coredata.DocumentVersionSignatureEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionDocumentVersion: AllRoles,
|
||||
ActionSignedBy: AllRoles,
|
||||
},
|
||||
coredata.RiskEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionTotalCount: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
ActionListMeasures: AllRoles,
|
||||
ActionListDocuments: AllRoles,
|
||||
ActionListObligations: AllRoles,
|
||||
|
||||
ActionUpdateRisk: EditRoles,
|
||||
ActionDeleteRisk: EditRoles,
|
||||
ActionCreateRiskMeasureMapping: EditRoles,
|
||||
ActionDeleteRiskMeasureMapping: EditRoles,
|
||||
ActionCreateRiskDocumentMapping: EditRoles,
|
||||
ActionDeleteRiskDocumentMapping: EditRoles,
|
||||
ActionCreateRiskObligationMapping: EditRoles,
|
||||
ActionDeleteRiskObligationMapping: EditRoles,
|
||||
},
|
||||
coredata.AssetEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionListVendors: AllRoles,
|
||||
ActionGetAssetType: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
|
||||
ActionUpdateAsset: EditRoles,
|
||||
ActionDeleteAsset: EditRoles,
|
||||
},
|
||||
coredata.DatumEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListVendors: AllRoles,
|
||||
|
||||
ActionUpdateDatum: EditRoles,
|
||||
ActionDeleteDatum: EditRoles,
|
||||
},
|
||||
coredata.AuditEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFile: AllRoles,
|
||||
ActionGetFramework: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionReport: AllRoles,
|
||||
ActionReportUrl: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
|
||||
ActionUpdateAudit: EditRoles,
|
||||
ActionDeleteAudit: EditRoles,
|
||||
ActionUploadAuditReport: EditRoles,
|
||||
ActionDeleteAuditReport: EditRoles,
|
||||
},
|
||||
coredata.ReportEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetFile: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionGetSnapshot: AllRoles,
|
||||
ActionDownloadUrl: AllRoles,
|
||||
},
|
||||
coredata.NonconformityEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionAudit: AllRoles,
|
||||
|
||||
ActionUpdateNonconformity: EditRoles,
|
||||
ActionDeleteNonconformity: EditRoles,
|
||||
},
|
||||
coredata.ObligationEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionListRisks: AllRoles,
|
||||
|
||||
ActionUpdateObligation: EditRoles,
|
||||
ActionDeleteObligation: EditRoles,
|
||||
},
|
||||
coredata.ContinualImprovementEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOwner: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
|
||||
ActionUpdateContinualImprovement: EditRoles,
|
||||
ActionDeleteContinualImprovement: EditRoles,
|
||||
},
|
||||
coredata.ProcessingActivityEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListVendors: AllRoles,
|
||||
|
||||
ActionUpdateProcessingActivity: EditRoles,
|
||||
ActionDeleteProcessingActivity: EditRoles,
|
||||
},
|
||||
coredata.SnapshotEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionListControls: AllRoles,
|
||||
|
||||
ActionDeleteSnapshot: EditRoles,
|
||||
},
|
||||
coredata.CustomDomainEntityType: {
|
||||
ActionGet: {RoleOwner, RoleAdmin},
|
||||
|
||||
ActionDeleteCustomDomain: {RoleOwner},
|
||||
},
|
||||
coredata.SAMLConfigurationEntityType: {
|
||||
ActionGet: {RoleOwner, RoleAdmin},
|
||||
ActionSpMetadataUrl: {RoleOwner, RoleAdmin},
|
||||
ActionTestLoginUrl: {RoleOwner, RoleAdmin},
|
||||
|
||||
ActionUpdateSAMLConfiguration: {RoleOwner, RoleAdmin},
|
||||
ActionDeleteSAMLConfiguration: {RoleOwner, RoleAdmin},
|
||||
ActionEnableSAML: {RoleOwner, RoleAdmin},
|
||||
ActionDisableSAML: {RoleOwner, RoleAdmin},
|
||||
},
|
||||
coredata.FileEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionDownloadUrl: AllRoles,
|
||||
},
|
||||
coredata.TrustCenterDocumentAccessEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionReport: AllRoles,
|
||||
ActionTrustCenterFile: AllRoles,
|
||||
},
|
||||
coredata.MeetingEntityType: {
|
||||
ActionGet: AllRoles,
|
||||
ActionGetOrganization: AllRoles,
|
||||
ActionTotalCount: AllRoles,
|
||||
|
||||
ActionUpdateMeeting: EditRoles,
|
||||
ActionDeleteMeeting: EditRoles,
|
||||
},
|
||||
}
|
||||
|
||||
func GetPermissionsForAction(entityType uint16, action Action) []Role {
|
||||
if entityActions, ok := Permissions[entityType]; ok {
|
||||
if roles, ok := entityActions[action]; ok {
|
||||
return roles
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetPermissionsByRole(userRole Role) map[string]map[Action]bool {
|
||||
permissions := make(map[string]map[Action]bool)
|
||||
|
||||
for entityType, actions := range Permissions {
|
||||
entityTypeName, ok := coredata.EntityModel(entityType)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if permissions[entityTypeName] == nil {
|
||||
permissions[entityTypeName] = make(map[Action]bool)
|
||||
}
|
||||
|
||||
for action, allowedRoles := range actions {
|
||||
if slices.Contains(allowedRoles, userRole) {
|
||||
permissions[entityTypeName][action] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return permissions
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"go.gearno.de/kit/pg"
|
||||
@@ -37,6 +38,14 @@ func (e *TenantAccessError) Error() string {
|
||||
return "not authorized"
|
||||
}
|
||||
|
||||
type PermissionDeniedError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e *PermissionDeniedError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
type (
|
||||
Service struct {
|
||||
pg *pg.Client
|
||||
@@ -103,6 +112,27 @@ func (s *Service) GetAllUserOrganizations(
|
||||
return organizations, err
|
||||
}
|
||||
|
||||
func (s *Service) GetUserOrganizationsWithRole(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
role coredata.MembershipRole,
|
||||
) (coredata.Organizations, error) {
|
||||
organizations := coredata.Organizations{}
|
||||
|
||||
err := s.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := organizations.LoadAllByUserIDWithRole(ctx, conn, userID, role); err != nil {
|
||||
return fmt.Errorf("cannot load user organizations with role: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
return organizations, err
|
||||
}
|
||||
|
||||
func (s *Service) GetAllOrganizationsForUserAPIKeyId(
|
||||
ctx context.Context,
|
||||
userAPIKeyID gid.GID,
|
||||
@@ -143,70 +173,6 @@ func (s *Service) GetUserOrganizations(
|
||||
return organizations, err
|
||||
}
|
||||
|
||||
func (s *Service) AcceptInvitation(
|
||||
ctx context.Context,
|
||||
token string,
|
||||
userID gid.GID,
|
||||
) error {
|
||||
payload, err := statelesstoken.ValidateToken[coredata.InvitationData](
|
||||
s.tokenSecret,
|
||||
TokenTypeOrganizationInvitation,
|
||||
token,
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid invitation token: %w", err)
|
||||
}
|
||||
|
||||
invitationData := payload.Data
|
||||
scope := coredata.NewScope(invitationData.InvitationID.TenantID())
|
||||
|
||||
return s.pg.WithTx(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
invitation := &coredata.Invitation{}
|
||||
if err := invitation.LoadByID(ctx, tx, scope, invitationData.InvitationID); err != nil {
|
||||
var errInvitationNotFound *coredata.ErrInvitationNotFound
|
||||
if errors.As(err, &errInvitationNotFound) {
|
||||
return fmt.Errorf("invitation was deleted or no longer exists")
|
||||
}
|
||||
return fmt.Errorf("cannot load invitation: %w", err)
|
||||
}
|
||||
|
||||
if invitation.AcceptedAt != nil {
|
||||
return fmt.Errorf("invitation already accepted")
|
||||
}
|
||||
|
||||
if time.Now().After(invitation.ExpiresAt) {
|
||||
return fmt.Errorf("invitation expired")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
membershipID := gid.New(scope.GetTenantID(), coredata.MembershipEntityType)
|
||||
|
||||
membership := &coredata.Membership{
|
||||
ID: membershipID,
|
||||
UserID: userID,
|
||||
OrganizationID: invitation.OrganizationID,
|
||||
Role: invitation.Role,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
if err := membership.Create(ctx, tx, scope); err != nil {
|
||||
return fmt.Errorf("cannot add user to organization: %w", err)
|
||||
}
|
||||
|
||||
invitation.AcceptedAt = &now
|
||||
if err := invitation.Update(ctx, tx, scope); err != nil {
|
||||
return fmt.Errorf("cannot mark invitation as accepted: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
func (s *Service) AcceptInvitationByID(
|
||||
ctx context.Context,
|
||||
invitationID gid.GID,
|
||||
@@ -274,36 +240,11 @@ func (s *Service) AcceptInvitationByID(
|
||||
return acceptedInvitation, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetUserInvitations(
|
||||
ctx context.Context,
|
||||
email string,
|
||||
cursor *page.Cursor[coredata.InvitationOrderField],
|
||||
filter *coredata.InvitationFilter,
|
||||
) (*page.Page[*coredata.Invitation, coredata.InvitationOrderField], error) {
|
||||
var invitations coredata.Invitations
|
||||
|
||||
err := s.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := invitations.LoadByEmail(ctx, conn, coredata.NewNoScope(), email, cursor, filter); err != nil {
|
||||
return fmt.Errorf("cannot load invitations: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return page.NewPage(invitations, cursor), nil
|
||||
}
|
||||
|
||||
type UserInvitation struct {
|
||||
ID gid.GID
|
||||
Email string
|
||||
FullName string
|
||||
Role coredata.Role
|
||||
Role coredata.MembershipRole
|
||||
ExpiresAt time.Time
|
||||
AcceptedAt *time.Time
|
||||
CreatedAt time.Time
|
||||
@@ -417,7 +358,7 @@ func (s *TenantAuthzService) AddUserToOrganization(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
role coredata.Role,
|
||||
role coredata.MembershipRole,
|
||||
) error {
|
||||
now := time.Now()
|
||||
membershipID := gid.New(s.scope.GetTenantID(), coredata.MembershipEntityType)
|
||||
@@ -538,6 +479,30 @@ func (s *TenantAuthzService) DeleteInvitation(
|
||||
)
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) GetMembershipByUserAndOrganizationID(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
) (*coredata.Membership, error) {
|
||||
membership := &coredata.Membership{}
|
||||
|
||||
err := s.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := membership.LoadByUserAndOrg(ctx, conn, s.scope, userID, orgID); err != nil {
|
||||
return fmt.Errorf("cannot load membership: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return membership, nil
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) GetMembershipsByOrganizationID(
|
||||
ctx context.Context,
|
||||
orgID gid.GID,
|
||||
@@ -609,41 +574,11 @@ func (s *TenantAuthzService) CountOrganizationUsers(
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) CanUserAccessOrganization(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
) (bool, error) {
|
||||
membership := &coredata.Membership{}
|
||||
|
||||
haveAccess := false
|
||||
|
||||
err := s.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if err := membership.LoadByUserAndOrg(ctx, conn, s.scope, userID, orgID); err != nil {
|
||||
if _, ok := err.(coredata.ErrMembershipNotFound); ok {
|
||||
return nil // Not an error, just no access
|
||||
}
|
||||
return fmt.Errorf("cannot check organization access: %w", err)
|
||||
}
|
||||
haveAccess = true
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return haveAccess, nil
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) GetUserRoleInOrganization(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
) (coredata.Role, error) {
|
||||
) (coredata.MembershipRole, error) {
|
||||
membership := &coredata.Membership{}
|
||||
|
||||
err := s.pg.WithConn(
|
||||
@@ -690,30 +625,55 @@ func (s *TenantAuthzService) RemoveMemberFromOrganization(
|
||||
)
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) UpdateUserRole(
|
||||
func (s *TenantAuthzService) UpdateMembershipRole(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
newRole coredata.Role,
|
||||
) error {
|
||||
return s.pg.WithTx(
|
||||
memberID gid.GID,
|
||||
newRole coredata.MembershipRole,
|
||||
) (*coredata.Membership, error) {
|
||||
membership := &coredata.Membership{}
|
||||
|
||||
err := s.pg.WithTx(
|
||||
ctx,
|
||||
func(tx pg.Conn) error {
|
||||
membership := &coredata.Membership{}
|
||||
if err := membership.LoadByUserAndOrg(ctx, tx, s.scope, userID, orgID); err != nil {
|
||||
return fmt.Errorf("cannot find membership: %w", err)
|
||||
if err := membership.LoadByID(ctx, tx, s.scope, memberID); err != nil {
|
||||
return fmt.Errorf("cannot load membership: %w", err)
|
||||
}
|
||||
|
||||
if membership.OrganizationID != orgID {
|
||||
return fmt.Errorf("membership does not belong to organization")
|
||||
}
|
||||
|
||||
// If the new role cannot create API keys, delete all related API key memberships
|
||||
if newRole != coredata.MembershipRoleOwner {
|
||||
var apiKeyMemberships coredata.UserAPIKeyMemberships
|
||||
if err := apiKeyMemberships.LoadByMembershipID(ctx, tx, s.scope, memberID); err != nil {
|
||||
return fmt.Errorf("cannot load api key memberships: %w", err)
|
||||
}
|
||||
|
||||
for _, apiKeyMembership := range apiKeyMemberships {
|
||||
if err := apiKeyMembership.Delete(ctx, tx, s.scope); err != nil {
|
||||
return fmt.Errorf("cannot delete api key membership: %w", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
membership.Role = newRole
|
||||
membership.UpdatedAt = time.Now()
|
||||
|
||||
if err := membership.Update(ctx, tx, s.scope); err != nil {
|
||||
return fmt.Errorf("cannot update user role: %w", err)
|
||||
return fmt.Errorf("cannot update membership role: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return membership, nil
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) InviteUserToOrganization(
|
||||
@@ -721,7 +681,7 @@ func (s *TenantAuthzService) InviteUserToOrganization(
|
||||
organizationID gid.GID,
|
||||
emailAddress string,
|
||||
fullName string,
|
||||
role coredata.Role,
|
||||
role coredata.MembershipRole,
|
||||
) (*coredata.Invitation, error) {
|
||||
var invitation *coredata.Invitation
|
||||
|
||||
@@ -827,7 +787,7 @@ func (s *TenantAuthzService) EnsureSAMLMembership(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
organizationID gid.GID,
|
||||
role *coredata.Role,
|
||||
role *coredata.MembershipRole,
|
||||
) error {
|
||||
now := time.Now()
|
||||
|
||||
@@ -842,7 +802,7 @@ func (s *TenantAuthzService) EnsureSAMLMembership(
|
||||
return fmt.Errorf("cannot load membership: %w", err)
|
||||
}
|
||||
|
||||
membershipRole := coredata.RoleMember
|
||||
membershipRole := coredata.MembershipRoleViewer
|
||||
if role != nil {
|
||||
membershipRole = *role
|
||||
}
|
||||
@@ -878,15 +838,94 @@ func (s *TenantAuthzService) EnsureSAMLMembership(
|
||||
)
|
||||
}
|
||||
|
||||
// This is a placeholder for future permission system
|
||||
func (s *TenantAuthzService) HasPermission(
|
||||
func (s *TenantAuthzService) Authorize(
|
||||
ctx context.Context,
|
||||
userID gid.GID,
|
||||
orgID gid.GID,
|
||||
resource string,
|
||||
action string,
|
||||
) (bool, error) {
|
||||
// For now, just check if user is a member
|
||||
// In the future, this will check specific permissions based on role
|
||||
return s.CanUserAccessOrganization(ctx, userID, orgID)
|
||||
user *coredata.User,
|
||||
apiKey *coredata.UserAPIKey,
|
||||
entityGID gid.GID,
|
||||
action Action,
|
||||
) error {
|
||||
requiredRoles := GetPermissionsForAction(entityGID.EntityType(), action)
|
||||
if requiredRoles == nil {
|
||||
return &PermissionDeniedError{
|
||||
Message: fmt.Sprintf("no permissions defined for action %s on entity type %d", action, entityGID.EntityType()),
|
||||
}
|
||||
}
|
||||
|
||||
role, err := s.GetUserOrAPIKeyRole(ctx, user, apiKey, entityGID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get user or API key role: %w", err)
|
||||
}
|
||||
|
||||
if !slices.Contains(requiredRoles, role) {
|
||||
return &PermissionDeniedError{
|
||||
Message: fmt.Sprintf("role %s not authorized for action %s, requires one of %v", role, action, requiredRoles),
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) CanAssignRole(
|
||||
ctx context.Context,
|
||||
user *coredata.User,
|
||||
apiKey *coredata.UserAPIKey,
|
||||
entityGID gid.GID,
|
||||
targetRole coredata.MembershipRole,
|
||||
) error {
|
||||
currentRole, err := s.GetUserOrAPIKeyRole(ctx, user, apiKey, entityGID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot get user or API key role: %w", err)
|
||||
}
|
||||
|
||||
if currentRole == RoleOwner || currentRole == RoleFull {
|
||||
return nil
|
||||
}
|
||||
|
||||
if currentRole == RoleAdmin {
|
||||
if targetRole == coredata.MembershipRoleOwner {
|
||||
return &PermissionDeniedError{Message: "admin users cannot assign owner role"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return &PermissionDeniedError{Message: fmt.Sprintf("role %s cannot assign roles", currentRole)}
|
||||
}
|
||||
|
||||
func (s *TenantAuthzService) GetUserOrAPIKeyRole(
|
||||
ctx context.Context,
|
||||
user *coredata.User,
|
||||
apiKey *coredata.UserAPIKey,
|
||||
entityGID gid.GID,
|
||||
) (Role, error) {
|
||||
var role Role
|
||||
err := s.pg.WithConn(
|
||||
ctx,
|
||||
func(conn pg.Conn) error {
|
||||
if user != nil {
|
||||
membership := &coredata.Membership{}
|
||||
if err := membership.LoadRoleByUserAndEntityID(ctx, conn, s.scope, user.ID, entityGID); err != nil {
|
||||
return fmt.Errorf("cannot get user role: %w", err)
|
||||
}
|
||||
role = Role(membership.Role.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
if apiKey != nil {
|
||||
apiKeyMembership := &coredata.UserAPIKeyMembership{}
|
||||
if err := apiKeyMembership.LoadRoleByAPIKeyAndEntityID(ctx, conn, s.scope, apiKey.ID, entityGID); err != nil {
|
||||
return fmt.Errorf("cannot get API key role: %w", err)
|
||||
}
|
||||
role = Role(apiKeyMembership.Role.String())
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("no user or API key provided")
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user