Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ services:
- "127.0.0.1:4566:4566" # LocalStack Edge Proxy
environment:
- DEBUG=${DEBUG:-0}
- SERVICES=sns,sqs,s3,lambda,dynamodb,kinesis,kms
- SERVICES=sns,sqs,s3,ses,lambda,dynamodb,kinesis,kms
- DISABLE_CORS_CHECKS=1
- DISABLE_CORS_HANDLERS=1
- SKIP_CORS_PREFLIGHT=1
Expand Down
373 changes: 373 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
},
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.400.0",
"@aws-sdk/client-kinesis": "^3.400.0",
"@aws-sdk/client-kms": "^3.400.0",
"@aws-sdk/client-lambda": "^3.400.0",
"@aws-sdk/client-s3": "^3.400.0",
"@aws-sdk/client-sqs": "^3.400.0",
"@aws-sdk/client-ses": "^3.839.0",
"@aws-sdk/client-sns": "^3.400.0",
"@aws-sdk/client-lambda": "^3.400.0",
"@aws-sdk/client-kms": "^3.400.0",
"@aws-sdk/client-kinesis": "^3.400.0",
"@aws-sdk/client-sqs": "^3.400.0",
"@mdi/font": "^7.4.0",
"axios": "^1.6.0",
"jszip": "^3.10.1",
Expand Down
1 change: 1 addition & 0 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ const menuItems = [
{ title: 'KMS Keys', icon: 'mdi-key', to: '/kms' },
{ title: 'Lambda Functions', icon: 'mdi-function', to: '/lambda' },
{ title: 'S3 Buckets', icon: 'mdi-folder-multiple', to: '/s3' },
{ title: 'SES Emails', icon: 'mdi-email-multiple', to: '/ses' },
{ title: 'SNS Topics', icon: 'mdi-forum', to: '/sns' },
{ title: 'SQS Queues', icon: 'mdi-format-list-bulleted', to: '/sqs' },
]
Expand Down
6 changes: 6 additions & 0 deletions src/router/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import KinesisView from '@/views/KinesisView.vue'
import SNSView from '@/views/SNSView.vue'
import KMSView from '@/views/KMSView.vue'
import AboutView from '@/views/AboutView.vue'
import SESView from '@/views/SESView.vue'

export default [
{
Expand All @@ -19,6 +20,11 @@ export default [
name: 'S3',
component: S3View
},
{
path: '/ses',
name: 'SES',
component: SESView
},
{
path: '/sqs',
name: 'SQS',
Expand Down
4 changes: 4 additions & 0 deletions src/stores/app.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineStore } from 'pinia'
import { ref } from 'vue'
import { S3Client } from '@aws-sdk/client-s3'
import { SESClient} from '@aws-sdk/client-ses'
import { SNSClient } from '@aws-sdk/client-sns'
import { SQSClient } from '@aws-sdk/client-sqs'
import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
Expand Down Expand Up @@ -35,6 +36,7 @@ export const useAppStore = defineStore('app', () => {

// Initialize AWS services
const s3 = ref(null)
const ses = ref(null)
const sns = ref(null)
const sqs = ref(null)
const dynamodb = ref(null)
Expand All @@ -53,6 +55,7 @@ export const useAppStore = defineStore('app', () => {
}

s3.value = new S3Client(config)
ses.value = new SESClient(config)
sns.value = new SNSClient(config)
sqs.value = new SQSClient(config)
dynamodb.value = new DynamoDBClient(config)
Expand Down Expand Up @@ -106,6 +109,7 @@ export const useAppStore = defineStore('app', () => {
connectionStatus,
snackbar,
s3,
ses,
sns,
sqs,
dynamodb,
Expand Down
25 changes: 25 additions & 0 deletions src/utils/api.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import axios from 'axios'

const api = axios.create({
baseURL: import.meta.env.VITE_LOCALSTACK_ENDPOINT || 'http://localhost:4566',
timeout: 10000, // 10 seconds
})

export const getSesData = async (params = {}) => {
try {
const response = await api.get('/_aws/ses', { params })
return response.data
} catch (error) {
console.error('Error fetching SES data:', error);
throw error
}
}

export const deleteSesMessage = async (params = {}) => {
try {
await api.delete('/_aws/ses', { params })
} catch (error) {
console.error('Error deleting SES message:', error);
throw error
}
}
4 changes: 4 additions & 0 deletions src/utils/formatDate.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export const formatDate = (date) => {
if (!date) return 'N/A'
return new Date(date).toLocaleString('pt-BR')
}
58 changes: 50 additions & 8 deletions src/views/Dashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
:color="service.status === 'active' ? 'primary' : 'grey-lighten-2'"
:variant="service.status === 'active' ? 'elevated' : 'outlined'"
class="pa-4"
height="120"
height="150"
@click="service.status === 'active' ? navigateToService(service.route): null"
style="cursor: pointer"
>
Expand Down Expand Up @@ -127,10 +127,12 @@ import { ListFunctionsCommand } from '@aws-sdk/client-lambda'
import { ListBucketsCommand, ListObjectsV2Command, DeleteObjectsCommand, DeleteBucketCommand } from '@aws-sdk/client-s3'
import { ListTopicsCommand } from '@aws-sdk/client-sns'
import { ListQueuesCommand, DeleteQueueCommand } from '@aws-sdk/client-sqs'
import { ListIdentitiesCommand } from '@aws-sdk/client-ses'
import { deleteSesMessage, getSesData } from '@/utils/api.js'

const router = useRouter()
const appStore = useAppStore()
const { s3, sns, sqs, dynamodb, lambda, kinesis, kms } = storeToRefs(appStore)
const { s3, ses, sns, sqs, dynamodb, lambda, kinesis, kms } = storeToRefs(appStore)

const services = ref([
{
Expand Down Expand Up @@ -168,6 +170,13 @@ const services = ref([
status: 'inactive',
stats: null
},
{
name: 'SES',
icon: 'mdi-email',
route: '/ses',
status: 'inactive',
stats: null
},
{
name: 'SNS',
icon: 'mdi-forum',
Expand Down Expand Up @@ -206,6 +215,13 @@ const quickActions = ref([
action: 'clearDynamoDB',
loading: false
},
{
title: 'Limpar SES',
icon: 'mdi-email-remove',
color: 'error',
action: 'clearSES',
loading: false
},
{
title: 'Atualizar Status',
icon: 'mdi-refresh',
Expand Down Expand Up @@ -290,28 +306,42 @@ const loadServiceStats = async () => {
services.value[4].status = 'inactive'
}

// SNS Stats
// SES Stats
try {
const snsTopics = await sns.value.send(new ListTopicsCommand({}))
const sesIdentities = await ses.value.send(new ListIdentitiesCommand({ IdentityType: 'EmailAddress' }))
const sesData = await getSesData();
services.value[5].status = 'active'
services.value[5].stats = {
'E-mails': sesData.messages ? sesData.messages.length : 0,
'Identidades': sesIdentities.Identities ? sesIdentities.Identities.length : 0
}
} catch (error) {
console.error('SES error:', error)
services.value[5].status = 'inactive'
}

// SNS Stats
try {
const snsTopics = await sns.value.send(new ListTopicsCommand({}))
services.value[6].status = 'active'
services.value[6].stats = {
'Tópicos': snsTopics.Topics ? snsTopics.Topics.length : 0
}
} catch (error) {
console.error('SNS error:', error)
services.value[5].status = 'inactive'
services.value[6].status = 'inactive'
}

// SQS Stats
try {
const sqsQueues = await sqs.value.send(new ListQueuesCommand({}))
services.value[6].status = 'active'
services.value[6].stats = {
services.value[7].status = 'active'
services.value[7].stats = {
'Filas': sqsQueues.QueueUrls ? sqsQueues.QueueUrls.length : 0
}
} catch (error) {
console.error('SQS error:', error)
services.value[6].status = 'inactive'
services.value[7].status = 'inactive'
}

} catch (error) {
Expand Down Expand Up @@ -344,6 +374,11 @@ const executeQuickAction = (action) => {
text = 'Esta ação irá deletar todas as filas SQS. Deseja continuar?'
color = 'warning'
break
case 'clearSES':
title = 'Limpar todos os emails SES'
text = 'Esta ação irá deletar todos os emails do SES. Deseja continuar?'
color = 'error'
break
case 'clearDynamoDB':
title = 'Limpar todas as tabelas DynamoDB'
text = 'Esta ação irá deletar todas as tabelas DynamoDB. Deseja continuar?'
Expand Down Expand Up @@ -373,6 +408,9 @@ const performClearAction = async (action) => {
case 'clearSQS':
await clearAllSQSQueues()
break
case 'clearSES':
await clearAllSESData()
break
case 'clearDynamoDB':
await clearAllDynamoDBTables()
break
Expand Down Expand Up @@ -422,6 +460,10 @@ const clearAllSQSQueues = async () => {
}
}

const clearAllSESData = async () => {
await deleteSesMessage()
}

const clearAllDynamoDBTables = async () => {
const tables = await dynamodb.value.send(new ListTablesCommand({}))

Expand Down
5 changes: 1 addition & 4 deletions src/views/DynamoDBView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ import {
DeleteItemCommand,
PutItemCommand
} from '@aws-sdk/client-dynamodb'
import { formatDate } from '../utils/formatDate.js'

const appStore = useAppStore()
const { dynamodb } = storeToRefs(appStore)
Expand Down Expand Up @@ -622,10 +623,6 @@ const getStatusColor = (status) => {
}
}

const formatDate = (date) => {
return new Date(date).toLocaleString('pt-BR')
}

const formatBytes = (bytes) => {
if (bytes === 0) return '0 Bytes'
const k = 1024
Expand Down
6 changes: 1 addition & 5 deletions src/views/KMSView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ import {
DecryptCommand,
ScheduleKeyDeletionCommand
} from '@aws-sdk/client-kms'
import { formatDate } from '../utils/formatDate.js'

const appStore = useAppStore()
const { kms } = storeToRefs(appStore)
Expand Down Expand Up @@ -381,11 +382,6 @@ const getKeyStateColor = (state) => {
}
}

const formatDate = (dateString) => {
if (!dateString) return 'N/A'
return new Date(dateString).toLocaleString('pt-BR')
}

// KMS API functions
const loadKeys = async () => {
try {
Expand Down
5 changes: 1 addition & 4 deletions src/views/KinesisView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,7 @@ import {
GetShardIteratorCommand,
GetRecordsCommand
} from '@aws-sdk/client-kinesis'
import { formatDate } from '../utils/formatDate.js'

const appStore = useAppStore()
const { kinesis } = storeToRefs(appStore)
Expand Down Expand Up @@ -511,10 +512,6 @@ const getStatusColor = (status) => {
}
}

const formatDate = (date) => {
return new Date(date).toLocaleString('pt-BR')
}

const decodeData = (data) => {
try {
// Try to decode as UTF-8 string
Expand Down
4 changes: 0 additions & 4 deletions src/views/LambdaView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -659,10 +659,6 @@ const getStateColor = (state) => {
}
}

const formatDate = (date) => {
return new Date(date).toLocaleString('pt-BR')
}

const decodeLogs = (logResult) => {
try {
return atob(logResult)
Expand Down
5 changes: 1 addition & 4 deletions src/views/S3View.vue
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ import {
DeleteObjectCommand,
PutObjectCommand
} from '@aws-sdk/client-s3'
import { formatDate } from '../utils/formatDate.js'

const appStore = useAppStore()
const { s3 } = storeToRefs(appStore)
Expand Down Expand Up @@ -370,10 +371,6 @@ const uploadFile = async () => {
}
}

const formatDate = (date) => {
return new Date(date).toLocaleString('pt-BR')
}

const formatBytes = (bytes) => {
if (bytes === 0) return '0 Bytes'
const k = 1024
Expand Down
Loading
Loading