From ce268e6f6488b13cfaf5dee938e877a7aa08094c Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Wed, 6 Mar 2024 17:11:15 +1100 Subject: [PATCH 1/8] Commiting progress --- services/api/src/resolvers.js | 2 ++ .../api/src/resources/notification/resolvers.ts | 13 +++++++++++++ services/api/src/resources/notification/sql.ts | 12 ++++++++++++ services/api/src/typeDefs.js | 4 ++++ 4 files changed, 31 insertions(+) diff --git a/services/api/src/resolvers.js b/services/api/src/resolvers.js index 8c192b3174..ab3a47dec9 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/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index f714feac37..a19c45757a 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -705,3 +705,16 @@ export const removeAllNotificationsFromAllProjects: ResolverFn = async ( // TODO: Check rows for success return 'success'; }; + +// WIP +export const getAllNotifications: ResolverFn = async ( + root, + args, + { sqlClientPool, hasPermission } +) => { + await hasPermission('notification', 'view'); + + const rows = await query(sqlClientPool, Sql.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..8336a12fe1 100644 --- a/services/api/src/resources/notification/sql.ts +++ b/services/api/src/resources/notification/sql.ts @@ -37,6 +37,18 @@ export const Sql = { .select('nt.*', 'pn.*', knex.raw('? as orig_type', [type])) .toString(); }, + // TODO - better solution than union + selectAllNotifications:() => { + let query = knex.union([ + knex('notification_slack').select(knex.raw('"slack" as Type, id, name, webhook')), + knex('notification_webhook').select(knex.raw('"webhook" as Type, id, name, webhook')), + knex('notification_rocketchat').select(knex.raw('"rocketchat" as Type, id, name, webhook')), + knex('notification_microsoftteams').select(knex.raw('"microsoftteams" as Type, id, name, webhook')), + knex('notification_email').select(knex.raw('"email" as Type, id, name, email_address')), + ]) + + return query.toString(); + }, deleteProjectNotification: input => { const deleteQuery = knex.raw( `DELETE pn diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index 835ec5d846..f459c7b9d7 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -1456,6 +1456,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") From 29795d6886aecd16abb29ee036234040f5227ad8 Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Thu, 7 Mar 2024 18:12:13 +1100 Subject: [PATCH 2/8] Updated query --- .../api/src/resources/notification/helpers.ts | 31 +++++++++++++++++++ .../src/resources/notification/resolvers.ts | 3 +- .../api/src/resources/notification/sql.ts | 15 +++------ 3 files changed, 37 insertions(+), 12 deletions(-) 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 a19c45757a..2c5be69ecc 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -714,7 +714,8 @@ export const getAllNotifications: ResolverFn = async ( ) => { await hasPermission('notification', 'view'); - const rows = await query(sqlClientPool, Sql.selectAllNotifications()) + 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 8336a12fe1..defb7af693 100644 --- a/services/api/src/resources/notification/sql.ts +++ b/services/api/src/resources/notification/sql.ts @@ -38,17 +38,10 @@ export const Sql = { .toString(); }, // TODO - better solution than union - selectAllNotifications:() => { - let query = knex.union([ - knex('notification_slack').select(knex.raw('"slack" as Type, id, name, webhook')), - knex('notification_webhook').select(knex.raw('"webhook" as Type, id, name, webhook')), - knex('notification_rocketchat').select(knex.raw('"rocketchat" as Type, id, name, webhook')), - knex('notification_microsoftteams').select(knex.raw('"microsoftteams" as Type, id, name, webhook')), - knex('notification_email').select(knex.raw('"email" as Type, id, name, email_address')), - ]) - - return query.toString(); - }, + selectAllNotifications: (type: string) => + knex(`notification_${type}`) + .select('*', knex.raw(`'${type}' as type`)) + .toString(), deleteProjectNotification: input => { const deleteQuery = knex.raw( `DELETE pn From 463e6e245151918440ff5857eec2b3ddd6727094 Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Tue, 12 Mar 2024 16:39:20 +1100 Subject: [PATCH 3/8] Included pid --- services/api/src/resources/notification/helpers.ts | 9 +++++++++ services/api/src/resources/notification/resolvers.ts | 9 ++++++++- services/api/src/resources/notification/sql.ts | 1 - services/api/src/typeDefs.js | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/services/api/src/resources/notification/helpers.ts b/services/api/src/resources/notification/helpers.ts index e65f4f9169..ceca2f6359 100644 --- a/services/api/src/resources/notification/helpers.ts +++ b/services/api/src/resources/notification/helpers.ts @@ -87,4 +87,13 @@ export const Helpers = (sqlClientPool: Pool) => ({ return result }, + selectAllProjectNotifications: async (rows) => { + let nids = new(Array) + await Promise.all(rows.map(async (row) => { + let nid = await query(sqlClientPool,Sql.selectProjectNotificationByNotificationName({name: row.name, type: row.type})) + nid[0] != undefined ? nids.push(nid[0]) : '' + })) + + return nids + }, }); diff --git a/services/api/src/resources/notification/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index 2c5be69ecc..4e85d54b8a 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -716,6 +716,13 @@ export const getAllNotifications: ResolverFn = async ( const rows = await Helpers(sqlClientPool).selectAllNotifications(); - return rows; + const nids = await Helpers(sqlClientPool).selectAllProjectNotifications(rows); + + rows.map((row => { + nids.map((nid => { + row.id == nid.id && row.type == nid.type ? row.pid = nid.pid : null + })) + })) + 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 defb7af693..7af3fdc615 100644 --- a/services/api/src/resources/notification/sql.ts +++ b/services/api/src/resources/notification/sql.ts @@ -37,7 +37,6 @@ export const Sql = { .select('nt.*', 'pn.*', knex.raw('? as orig_type', [type])) .toString(); }, - // TODO - better solution than union selectAllNotifications: (type: string) => knex(`notification_${type}`) .select('*', knex.raw(`'${type}' as type`)) diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index f459c7b9d7..76a8be37c3 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -579,6 +579,7 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int + pid: Int } type NotificationRocketChat { @@ -589,6 +590,7 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int + pid: Int } type NotificationSlack { @@ -599,6 +601,7 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int + pid: Int } type NotificationEmail { @@ -608,6 +611,7 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int + pid: Int } type NotificationWebhook { @@ -617,6 +621,7 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int + pid: Int } type UnassignedNotification { From c7d775eec480500e382abe0c2e66a685fab1936c Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Wed, 20 Mar 2024 11:19:10 +1100 Subject: [PATCH 4/8] Cleaned up comment --- services/api/src/resources/notification/resolvers.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/services/api/src/resources/notification/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index 4e85d54b8a..5c0469db18 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -706,7 +706,6 @@ export const removeAllNotificationsFromAllProjects: ResolverFn = async ( return 'success'; }; -// WIP export const getAllNotifications: ResolverFn = async ( root, args, From 2257447e87bbe479d18fa439cc5a57d248e2b19d Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Wed, 20 Mar 2024 17:40:26 +1100 Subject: [PATCH 5/8] Included permission --- .../api/src/resources/notification/resolvers.ts | 2 +- services/keycloak/lagoon-realm-2.16.0.json | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/services/api/src/resources/notification/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index 5c0469db18..1e5b5c6f35 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -711,7 +711,7 @@ export const getAllNotifications: ResolverFn = async ( args, { sqlClientPool, hasPermission } ) => { - await hasPermission('notification', 'view'); + await hasPermission('notification', 'viewAll'); const rows = await Helpers(sqlClientPool).selectAllNotifications(); diff --git a/services/keycloak/lagoon-realm-2.16.0.json b/services/keycloak/lagoon-realm-2.16.0.json index 5ddf6c58db..efb33c0d29 100644 --- a/services/keycloak/lagoon-realm-2.16.0.json +++ b/services/keycloak/lagoon-realm-2.16.0.json @@ -1213,6 +1213,9 @@ }, { "name": "delete" + }, + { + "name": "viewAll" } ] }, @@ -2205,6 +2208,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": "Run Drush rsync to Development Environment", "type": "scope", From 70537d675d9111ada0032d18a5f17a6437b3ef27 Mon Sep 17 00:00:00 2001 From: cgoodwin90 Date: Thu, 21 Mar 2024 12:17:56 +1100 Subject: [PATCH 6/8] Included migration --- .../api/src/resources/notification/helpers.ts | 9 ------ .../src/resources/notification/resolvers.ts | 8 ----- services/api/src/typeDefs.js | 5 ---- .../startup-scripts/00-configure-lagoon.sh | 29 +++++++++++++++++++ 4 files changed, 29 insertions(+), 22 deletions(-) diff --git a/services/api/src/resources/notification/helpers.ts b/services/api/src/resources/notification/helpers.ts index ceca2f6359..e65f4f9169 100644 --- a/services/api/src/resources/notification/helpers.ts +++ b/services/api/src/resources/notification/helpers.ts @@ -87,13 +87,4 @@ export const Helpers = (sqlClientPool: Pool) => ({ return result }, - selectAllProjectNotifications: async (rows) => { - let nids = new(Array) - await Promise.all(rows.map(async (row) => { - let nid = await query(sqlClientPool,Sql.selectProjectNotificationByNotificationName({name: row.name, type: row.type})) - nid[0] != undefined ? nids.push(nid[0]) : '' - })) - - return nids - }, }); diff --git a/services/api/src/resources/notification/resolvers.ts b/services/api/src/resources/notification/resolvers.ts index 1e5b5c6f35..e523e627db 100644 --- a/services/api/src/resources/notification/resolvers.ts +++ b/services/api/src/resources/notification/resolvers.ts @@ -715,13 +715,5 @@ export const getAllNotifications: ResolverFn = async ( const rows = await Helpers(sqlClientPool).selectAllNotifications(); - const nids = await Helpers(sqlClientPool).selectAllProjectNotifications(rows); - - rows.map((row => { - nids.map((nid => { - row.id == nid.id && row.type == nid.type ? row.pid = nid.pid : null - })) - })) - return rows; }; \ No newline at end of file diff --git a/services/api/src/typeDefs.js b/services/api/src/typeDefs.js index 23b3feebaa..1cf1344857 100644 --- a/services/api/src/typeDefs.js +++ b/services/api/src/typeDefs.js @@ -579,7 +579,6 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int - pid: Int } type NotificationRocketChat { @@ -590,7 +589,6 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int - pid: Int } type NotificationSlack { @@ -601,7 +599,6 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int - pid: Int } type NotificationEmail { @@ -611,7 +608,6 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int - pid: Int } type NotificationWebhook { @@ -621,7 +617,6 @@ const typeDefs = gql` contentType: String notificationSeverityThreshold: ProblemSeverityRating organization: Int - pid: Int } type UnassignedNotification { diff --git a/services/keycloak/startup-scripts/00-configure-lagoon.sh b/services/keycloak/startup-scripts/00-configure-lagoon.sh index 65feb34349..a6a09591fe 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_viewAll { + 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 - < Date: Fri, 7 Jun 2024 16:30:11 +1000 Subject: [PATCH 7/8] Updated function casing --- services/keycloak/startup-scripts/00-configure-lagoon.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/keycloak/startup-scripts/00-configure-lagoon.sh b/services/keycloak/startup-scripts/00-configure-lagoon.sh index d4d83d64aa..b116232dc3 100755 --- a/services/keycloak/startup-scripts/00-configure-lagoon.sh +++ b/services/keycloak/startup-scripts/00-configure-lagoon.sh @@ -204,7 +204,7 @@ function migrate_to_custom_group_mapper { } -function add_notification_viewAll { +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) @@ -267,7 +267,7 @@ function configure_keycloak { check_migrations_version migrate_to_custom_group_mapper - add_notification_viewAll + add_notification_view_all #post 2.18.0+ migrations after this point service-api_add_query-groups_permission From 6ccac359d916c9ed3e6f726439347291b6c7096b Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Wed, 12 Jun 2024 14:25:49 +1000 Subject: [PATCH 8/8] fix: move migration function call --- services/keycloak/startup-scripts/00-configure-lagoon.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/keycloak/startup-scripts/00-configure-lagoon.sh b/services/keycloak/startup-scripts/00-configure-lagoon.sh index b116232dc3..537eed1018 100755 --- a/services/keycloak/startup-scripts/00-configure-lagoon.sh +++ b/services/keycloak/startup-scripts/00-configure-lagoon.sh @@ -267,9 +267,9 @@ function configure_keycloak { check_migrations_version migrate_to_custom_group_mapper - add_notification_view_all #post 2.18.0+ migrations after this point service-api_add_query-groups_permission + add_notification_view_all # always run last sync_client_secrets