From 82587605d7023684fed53e67830933ad41156881 Mon Sep 17 00:00:00 2001 From: Douglas Barone Date: Mon, 29 Aug 2022 12:54:45 -0400 Subject: [PATCH] Added ability to delete an AP --- .../migration.sql | 5 ++ server/prisma/schema.prisma | 4 +- .../resolvers/Mutation/deleteAccessPoint.js | 54 +++++++++++++++++++ server/src/resolvers/Mutation/index.js | 2 + server/src/schemaDirectives/AuthDirective.js | 5 -- server/src/typeDefs.js | 3 ++ web/src/views/AccessPoints/edit.vue | 44 +++++++++++++++ web/src/views/AccessPoints/index.vue | 1 + 8 files changed, 111 insertions(+), 7 deletions(-) create mode 100644 server/prisma/migrations/20220829163049_enable_ap_delete/migration.sql create mode 100644 server/src/resolvers/Mutation/deleteAccessPoint.js diff --git a/server/prisma/migrations/20220829163049_enable_ap_delete/migration.sql b/server/prisma/migrations/20220829163049_enable_ap_delete/migration.sql new file mode 100644 index 0000000..6a2618b --- /dev/null +++ b/server/prisma/migrations/20220829163049_enable_ap_delete/migration.sql @@ -0,0 +1,5 @@ +-- DropForeignKey +ALTER TABLE "AccessPointStats" DROP CONSTRAINT "AccessPointStats_accessPointId_fkey"; + +-- AddForeignKey +ALTER TABLE "AccessPointStats" ADD CONSTRAINT "AccessPointStats_accessPointId_fkey" FOREIGN KEY ("accessPointId") REFERENCES "AccessPoint"("id") ON DELETE CASCADE ON UPDATE CASCADE; diff --git a/server/prisma/schema.prisma b/server/prisma/schema.prisma index b22089a..765d840 100644 --- a/server/prisma/schema.prisma +++ b/server/prisma/schema.prisma @@ -105,7 +105,7 @@ model WifiDevice { identity String? // The user informed by the controller accessPointId Int? - accessPoint AccessPoint? @relation("wifidevice_to_ap", fields: [accessPointId], references: [id]) + accessPoint AccessPoint? @relation("wifidevice_to_ap", fields: [accessPointId], references: [id], onDelete: SetNull) userId Int? // The connected User user User? @relation("wifidevice_to_user", fields: [userId], references: [id]) @@ -199,7 +199,7 @@ model AccessPointStats { sumUsage BigInt? accessPointId Int - accessPoint AccessPoint @relation("accesspointstats_to_ap", fields: [accessPointId], references: [id]) + accessPoint AccessPoint @relation("accesspointstats_to_ap", fields: [accessPointId], references: [id], onDelete: Cascade) } model Network { diff --git a/server/src/resolvers/Mutation/deleteAccessPoint.js b/server/src/resolvers/Mutation/deleteAccessPoint.js new file mode 100644 index 0000000..79acb2f --- /dev/null +++ b/server/src/resolvers/Mutation/deleteAccessPoint.js @@ -0,0 +1,54 @@ +import prisma from '../../prisma' +import { ACCESS_POINTS_UPDATED, pubsub } from '../../pubsub' +import { logError, logInfo } from '../../lib/logger' +import { getSubnetInfo } from '../../lib/subnetInfo' + +export async function deleteAccessPoint(_, { id }, { auth }) { + const accessPoint = await prisma.accessPoint.findUnique({ + where: { id: parseInt(id) } + }) + + if (!accessPoint) throw new Error('Access Point não encontrado') + + if (getSubnetInfo(accessPoint.ip).shortName !== auth.campus) { + logError({ + tags: ['accessPointEdited', 'accessPoints'], + message: `O usuário ${auth.displayName} (${ + auth.sAMAccountName + }) tentou deletar o + AP ${ + accessPoint.name || accessPoint.hostname + }, mas não tinha permissão.` + }) + + throw new Error( + `O AP ${ + accessPoint.name || accessPoint.hostname + } não está na rede do campus ${ + auth.campus + }. Você só pode deletar APs da rede do seu campus.` + ) + } + + const updatedAccessPoint = await prisma.accessPoint.delete({ + where: { id: parseInt(id) } + }) + + logInfo({ + tags: ['accessPointDeleted', 'accessPoints'], + message: `O usuário ${auth.displayName} (${ + auth.sAMAccountName + }) deletou o AP ${updatedAccessPoint.name || updatedAccessPoint.hostname}`, + data: updatedAccessPoint + }) + + const accessPoints = await prisma.accessPoint.findMany({ + include: { wifiDevices: true } + }) + + pubsub.publish(ACCESS_POINTS_UPDATED, { + accessPointsUpdated: accessPoints + }) + + return updatedAccessPoint +} diff --git a/server/src/resolvers/Mutation/index.js b/server/src/resolvers/Mutation/index.js index 2804d29..ee4fe15 100644 --- a/server/src/resolvers/Mutation/index.js +++ b/server/src/resolvers/Mutation/index.js @@ -8,6 +8,7 @@ import { deleteExpiredTokens } from './deleteExpiredTokens' import { importUsers } from './importUsers' import { addPAHost } from './addPAHost' import { delPAHost } from './delPAHost' +import { deleteAccessPoint } from './deleteAccessPoint' import { updateAccessPoint } from './updateAccessPoint' const Mutation = { @@ -21,6 +22,7 @@ const Mutation = { importUsers, addPAHost, delPAHost, + deleteAccessPoint, updateAccessPoint } diff --git a/server/src/schemaDirectives/AuthDirective.js b/server/src/schemaDirectives/AuthDirective.js index 26a7f9c..d20b837 100755 --- a/server/src/schemaDirectives/AuthDirective.js +++ b/server/src/schemaDirectives/AuthDirective.js @@ -25,11 +25,6 @@ class AuthDirective extends SchemaDirectiveVisitor { context.auth = user - console.log({ - user: user.updatePassword, - context: context.auth.updatePassword - }) - if (user.pwdLastSet.toISOString() === pwdLastSet) { if ( expectedRoles.length === 0 || diff --git a/server/src/typeDefs.js b/server/src/typeDefs.js index 9397a48..71e7606 100644 --- a/server/src/typeDefs.js +++ b/server/src/typeDefs.js @@ -102,6 +102,9 @@ const typeDefs = gql` "Update an Access Point" updateAccessPoint(data: UpdateAccessPointInput): AccessPoint! @auth(roles: ["superAdmin"]) + + "Delete an Access Point" + deleteAccessPoint(id: ID!): AccessPoint! @auth(roles: ["superAdmin"]) } type Subscription { diff --git a/web/src/views/AccessPoints/edit.vue b/web/src/views/AccessPoints/edit.vue index 619231f..c4c8a98 100644 --- a/web/src/views/AccessPoints/edit.vue +++ b/web/src/views/AccessPoints/edit.vue @@ -31,6 +31,9 @@ /> + + mdi-delete + mdi-check @@ -96,6 +99,47 @@ export default { } }) + this.$router.push({ name: 'access-points' }) + } catch (e) { + this.errors = e.graphQLErrors.map(error => error.message) + } finally { + this.loading = false + } + }, + + async onDeleteAccessPoint() { + this.errors = [] + this.loading = true + + try { + if ( + !confirm('Deletar este Access Point?') || + !confirm( + `ATENÇÃO! + +Esta ação desassociará todos os dispositivos que +já se conectaram à este AP. Além disso, se o AP +ainda estiver registrado na controladora, ele +será incluído novamente automaticamente. + +Continuar?` + ) + ) + return + + await this.$apollo.mutate({ + mutation: gql` + mutation ($id: ID!) { + deleteAccessPoint(id: $id) { + id + } + } + `, + variables: { + id: this.$route.params.id + } + }) + this.$router.push({ name: 'access-points' }) } catch (e) { this.errors = e.graphQLErrors.map(error => error.message) diff --git a/web/src/views/AccessPoints/index.vue b/web/src/views/AccessPoints/index.vue index 1b5cc84..734cf56 100644 --- a/web/src/views/AccessPoints/index.vue +++ b/web/src/views/AccessPoints/index.vue @@ -117,6 +117,7 @@ mdi-pencil + {{ item.name }}