Logout OK

This commit is contained in:
Douglas Barone 2023-10-20 11:48:16 -04:00
parent 0bd79eb3d0
commit 08e86da64e
7 changed files with 128 additions and 9 deletions

View File

@ -1,5 +1,7 @@
import { server } from './server'
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
export const SERVER_PORT = process.env.PORT || 8080
server.listen(SERVER_PORT, () => {

View File

@ -5,8 +5,6 @@ import { PaFirewall } from '../paloalto/PaFirewall'
import { paHosts } from '../db/pa'
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
export async function login(username: string, password: string, ip: string) {
const ldapClient = new Client({
url: 'ldap://10.7.0.18'
@ -19,7 +17,7 @@ export async function login(username: string, password: string, ip: string) {
const pa = new PaFirewall(paHosts[0].ip, paHosts[0].key)
await pa.mapUserIDToIP(username, ip, user.domain)
await pa.login(username, ip, user.domain)
return user
} catch (error) {

16
src/server/lib/logout.ts Normal file
View File

@ -0,0 +1,16 @@
import { PaFirewall } from '../paloalto/PaFirewall'
import { paHosts } from '../db/pa'
export async function logout(username: string, domain: string, ip: string) {
try {
const pa = new PaFirewall(paHosts[0].ip, paHosts[0].key)
await pa.logout(username, ip, domain)
return true
} catch (error) {
console.log(error)
throw new Error('Logout failed')
}
}

View File

@ -3,8 +3,8 @@ const MAP_TIMEOUT_IN_MINUTES = process.env.MAPPING_TIMEOUT || '720' // 12 horas
export class PaFirewall {
constructor(private ip: string, private key: string) {}
async mapUserIDToIP(username: string, ip: string, domain: string) {
const command = this.createCommand(username, ip, domain)
async login(username: string, ip: string, domain: string) {
const command = this.createLoginCommand(username, ip, domain)
const url = `https://${this.ip}/api/?type=user-id&key=${this.key}&cmd=${command}`
const response = await fetch(url, { method: 'POST' })
@ -23,16 +23,49 @@ export class PaFirewall {
return true
}
private createCommand(username: string, ip: string, domain: string) {
async logout(username: string, ip: string, domain: string) {
const command = this.createLogoutCommand(username, ip, domain)
const url = `https://${this.ip}/api/?type=user-id&key=${this.key}&cmd=${command}`
const response = await fetch(url, { method: 'POST' })
const data = await response.text()
const success = data.includes('status="success"')
if (!success) {
console.log(data)
throw new Error('Failed to logout user')
}
console.log(`Logged out user ${username} from IP ${ip}`)
return true
}
private createLoginCommand(username: string, ip: string, domain: string) {
return `
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<login>
<entry name="ifms\\${username}" ip="${ip}" timeout="${MAP_TIMEOUT_IN_MINUTES}"/>
<entry name="${domain}\\${username}" ip="${ip}" timeout="${MAP_TIMEOUT_IN_MINUTES}"/>
</login>
</payload>
</uid-message>`
}
private createLogoutCommand(username: string, ip: string, domain: string) {
return `
<uid-message>
<version>1.0</version>
<type>update</type>
<payload>
<logout>
<entry name="${domain}\\${username}" ip="${ip}" timeout="${MAP_TIMEOUT_IN_MINUTES}"/>
</logout>
</payload>
</uid-message>`
}
}

View File

@ -4,6 +4,7 @@ import * as trpcExpress from '@trpc/server/adapters/express'
import { z } from 'zod'
import { login } from './lib/login'
import { getIpFromContext } from './lib/getIpFromContext'
import { logout } from './lib/logout'
// Created for each request
function createContext({ req, res }: trpcExpress.CreateExpressContextOptions) {
@ -23,6 +24,11 @@ export const appRouter = t.router({
.input(z.object({ username: z.string(), password: z.string() }))
.mutation(async ({ input, ctx }) => {
return await login(input.username, input.password, getIpFromContext(ctx))
}),
logout: t.procedure
.input(z.object({ username: z.string(), domain: z.string() }))
.mutation(async ({ input, ctx }) => {
return await logout(input.username, input.domain, getIpFromContext(ctx))
})
})

View File

@ -0,0 +1,48 @@
<template>
<v-card :title="`Logado como ${loginResult.displayName} `">
<v-card-text>
Usuário: {{ `${loginResult.domain}\\${loginResult.username}` }}
<v-alert type="info" variant="outlined" class="mt-4">
Os acessos feitos a partir deste dispositivo agora são registrados com
seu usuário.
</v-alert>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
class="px-6"
@click="onLogout"
color="secondary"
size="large"
variant="outlined"
prepend-icon="mdi-logout"
>Sair</v-btn
>
</v-card-actions>
</v-card>
</template>
<script lang="ts" setup>
import { PropType } from 'vue'
import { trpc } from '../trpc'
const props = defineProps({
loginResult: {
type: Object as PropType<LoginResult>,
required: true
}
})
async function onLogout() {
const success = await trpc.logout.mutate({
username: props.loginResult.username,
domain: props.loginResult.domain
})
if (success) {
window.location.reload()
} else {
alert('Não foi possível fazer logout. Tente novamente.')
}
}
</script>

View File

@ -1,9 +1,11 @@
<template>
<v-container class="justify-center">
<v-row justify="center">
<v-col xl="4" lg="5" md="6" sm="10">
<v-col xl="5" lg="6" md="7" sm="10">
<logo class="mx-auto mb-4" :style="{ maxWidth: '256px' }" />
<login-form @login="console.log" />
<login-form v-if="!loginResult" @login="onLogin" />
<logged-card v-else :login-result="loginResult" />
<ip-alert class="mt-5" />
</v-col>
</v-row>
@ -14,4 +16,18 @@
import LoginForm from '../components/LoginForm.vue'
import IpAlert from '../components/IpAlert.vue'
import Logo from '../components/Logo.vue'
import LoggedCard from '../components/LoggedCard.vue'
import { ref } from 'vue'
const loginResult = ref<LoginResult | null>(null)
function onLogin(event: LoginResult) {
console.log(event)
loginResult.value = event
}
function onLogout() {
loginResult.value = null
}
</script>