diff --git a/services/api/src/resolvers.js b/services/api/src/resolvers.js index ab276e3b68..dc0556b0d7 100644 --- a/services/api/src/resolvers.js +++ b/services/api/src/resolvers.js @@ -150,6 +150,7 @@ const { deleteNotificationRocketChat, deleteNotificationSlack, deleteNotificationWebhook, + getAllNotifications, getNotificationsByProjectId, getNotificationsByOrganizationId, removeNotificationFromProject, @@ -582,6 +583,7 @@ const resolvers = { allProjectsInGroup: getAllProjectsInGroup, allProblemHarborScanMatchers: getProblemHarborScanMatches, allUsers: getAllUsers, + allNotifications: getAllNotifications, userByEmail: getUserByEmail, projectsByMetadata: getProjectsByMetadata, projectsByFactSearch: getProjectsByFactSearch, diff --git a/services/api/src/resources/notification/helpers.ts b/services/api/src/resources/notification/helpers.ts index fcc525fb98..e65f4f9169 100644 --- a/services/api/src/resources/notification/helpers.ts +++ b/services/api/src/resources/notification/helpers.ts @@ -56,4 +56,35 @@ export const Helpers = (sqlClientPool: Pool) => ({ await query(sqlClientPool, Sql.deleteProjectNotificationByProjectId(project, "email")); await query(sqlClientPool, Sql.deleteProjectNotificationByProjectId(project, "webhook")); }, + selectAllNotifications: async () => { + let type = "slack" + // get all notifications + const slacks = await query( + sqlClientPool, + Sql.selectAllNotifications(type) + ); + type = "rocketchat" + const rcs = await query( + sqlClientPool, + Sql.selectAllNotifications(type) + ); + type = "microsoftteams" + const teams = await query( + sqlClientPool, + Sql.selectAllNotifications(type) + ); + type = "email" + const email = await query( + sqlClientPool, + Sql.selectAllNotifications(type) + ); + type = "webhook" + const webhook = await query( + sqlClientPool, + Sql.selectAllNotifications(type) + ); + let result = [...slacks, ...rcs, ...teams, ...email, ...webhook] + + return result + }, }); diff --git a/services/api/src/resources/notification/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index 85ecbeabf3..d441984d1c 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -705,3 +705,15 @@ export const removeAllNotificationsFromAllProjects: ResolverFn = async ( // TODO: Check rows for success return 'success'; }; + +export const getAllNotifications: ResolverFn = async ( + root, + args, + { sqlClientPool, hasPermission } +) => { + await hasPermission('notification', 'viewAll'); + + const rows = await Helpers(sqlClientPool).selectAllNotifications(); + + return rows; +}; \ No newline at end of file diff --git a/services/api/src/resources/notification/sql.ts b/services/api/src/resources/notification/sql.ts index 75c2c4731f..7af3fdc615 100644 --- a/services/api/src/resources/notification/sql.ts +++ b/services/api/src/resources/notification/sql.ts @@ -37,6 +37,10 @@ export const Sql = { .select('nt.*', 'pn.*', knex.raw('? as orig_type', [type])) .toString(); }, + selectAllNotifications: (type: string) => + knex(`notification_${type}`) + .select('*', knex.raw(`'${type}' as type`)) + .toString(), deleteProjectNotification: input => { const deleteQuery = knex.raw( `DELETE pn diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index 5f3a567c65..0b9a0201e0 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -1439,6 +1439,10 @@ const typeDefs = gql` deployTargetConfigsByDeployTarget(deployTarget: Int!) : [DeployTargetConfig] @deprecated(reason: "Unstable API, subject to breaking changes in any release. Use at your own risk") allDeployTargetConfigs: [DeployTargetConfig] @deprecated(reason: "Unstable API, subject to breaking changes in any release. Use at your own risk") """ + List all notifications + """ + allNotifications: [Notification] + """ List all organizations """ allOrganizations: [Organization] @deprecated(reason: "Unstable API, subject to breaking changes in any release. Use at your own risk") diff --git a/services/keycloak/lagoon-realm-2.16.0.json b/services/keycloak/lagoon-realm-2.16.0.json index d63e818a60..f37b52c9d8 100644 --- a/services/keycloak/lagoon-realm-2.16.0.json +++ b/services/keycloak/lagoon-realm-2.16.0.json @@ -1044,6 +1044,9 @@ }, { "name": "delete" + }, + { + "name": "viewAll" } ] }, @@ -2290,6 +2293,17 @@ "applyPolicies": "[\"[Lagoon] User has access to project\",\"[Lagoon] Users role for project is Developer\"]" } }, + { + "name": "View All Notifications", + "type": "scope", + "logic": "POSITIVE", + "decisionStrategy": "UNANIMOUS", + "config": { + "resources": "[\"notification\"]", + "scopes": "[\"viewAll\"]", + "applyPolicies": "[\"[Lagoon] Users role for realm is Platform Owner\"]" + } + }, { "name": "View All Groups", "type": "scope", diff --git a/services/keycloak/startup-scripts/00-configure-lagoon.sh b/services/keycloak/startup-scripts/00-configure-lagoon.sh index 08825dd19f..537eed1018 100755 --- a/services/keycloak/startup-scripts/00-configure-lagoon.sh +++ b/services/keycloak/startup-scripts/00-configure-lagoon.sh @@ -204,6 +204,34 @@ function migrate_to_custom_group_mapper { } +function add_notification_view_all { + local api_client_id=$(/opt/keycloak/bin/kcadm.sh get -r lagoon clients?clientId=api --config $CONFIG_PATH | jq -r '.[0]["id"]') + local view_all_notifications=$(/opt/keycloak/bin/kcadm.sh get -r lagoon clients/$api_client_id/authz/resource-server/permission?name=View+All+Notifications --config $CONFIG_PATH) + + + if [ "$view_all_notifications" != "[ ]" ]; then + echo "notification:viewAll already configured" + return 0 + fi + + echo creating \"View All Notifications\" permissions + + NOTIFICATION_RESOURCE_ID=$(/opt/keycloak/bin/kcadm.sh get -r lagoon clients/$api_client_id/authz/resource-server/resource?name=notification --config $CONFIG_PATH | jq -r '.[0]["_id"]') + /opt/keycloak/bin/kcadm.sh update clients/$CLIENT_ID/authz/resource-server/resource/$NOTIFICATION_RESOURCE_ID --config $CONFIG_PATH -r ${KEYCLOAK_REALM:-master} -s 'scopes=[{"name":"add"},{"name":"delete"},{"name":"view"},{"name":"deleteAll"},{"name":"removeAll"},{"name":"update"},{"name":"viewAll"}]' + + /opt/keycloak/bin/kcadm.sh create clients/$api_client_id/authz/resource-server/permission/scope --config $CONFIG_PATH -r lagoon -f - </dev/null; then echo "service-api already has query-groups realm-management role" @@ -241,6 +269,7 @@ function configure_keycloak { migrate_to_custom_group_mapper #post 2.18.0+ migrations after this point service-api_add_query-groups_permission + add_notification_view_all # always run last sync_client_secrets