Adding an API to an AdonisJS Web App #2.6

Listing an Organization's Access Tokens

In This Lesson

We'll query all of our organization's access tokens and filter out any tokens that are expired. Then, we'll list the organization's tokens showing it's name, abilities, when it was created, and when it was last used.

Created by
@tomgobich
Published

If you're just here for the API stuff and don't care for the Inertia/Vue side of this application, please feel free to apply the below code changes and continue onward. I'll also have the completed Inertia/Vue code available in the last lesson of this API Authentication module if you'd prefer waiting for that!

First, we need to accept our accessTokens array as a prop in our Organization Settings page. Then, we can go ahead and pass it through to our Organization Access Tokens Card.

<script setup lang="ts">
import { Abilities } from '#actions/abilities/get_abilities'
import AccessTokenDto from '#dtos/access_token'
import OrganizationDto from '#dtos/organization'
import OrganizationInviteDto from '#dtos/organization_invite'
import RoleDto from '#dtos/role'
import UserDto from '#dtos/user'

defineProps<{
  organization: OrganizationDto
  user: UserDto
  users: UserDto[]
  roles: RoleDto[]
  invites: OrganizationInviteDto[]
  accessTokens: AccessTokenDto[] // 👈
  can: Abilities
}>()
</script>

<template>
  <AppHead
    title="Organization Settings"
    :description="`Manage your ${organization.name} organization`"
  />

  <SettingsShell>
    <OrganizationEditCard v-if="can.organization.edit" :organization="organization" />
    <OrganizationUsersCard :user="user" :users="users" :roles="roles" :can="can" />
    <OrganizationUserInvitesCard :invites="invites" :roles="roles" :can="can" />
    <OrganizationAccessTokensCard :tokens="accessTokens" /> // 👈
  </SettingsShell>
</template>
Copied!
  • inertia
  • pages
  • settings
  • organization.vue

Then, within the Organization Access Tokens Card, we need to accept tokens as a prop with a type of our AccessTokensDto[]. While in our component's script also ensure Luxon's DateTime is imported, we'll use that next in our template.

<script setup lang="ts">
import AccessTokenDto from '#dtos/access_token'
import { DateTime } from 'luxon'
import TokenActions from '#enums/token_actions'
import { router } from '@inertiajs/vue3'
import axios from 'axios'
import { Clipboard, ClipboardCheck, Loader } from 'lucide-vue-next'
import { ref } from 'vue'

defineProps<{ tokens: AccessTokenDto[] }>() // 👈

let copyTimeout: NodeJS.Timeout | null = null
const isDialogShown = ref(false)
const processing = ref(false)
const isCopied = ref(false)
const token = ref<string | null>(null)
const permissionOptions = Object.values(TokenActions)
const form = ref({
  name: '',
  permissions: new Set(['read']),
})

// ...
</script>
Copied!
  • inertia
  • components
  • OrganizationAccessTokensCard.vue

Lastly, let's add a table within our card to list the tokens on our page.

<template>
  <Card>
    <CardHeader>
      <CardTitle>Organization Access Tokens</CardTitle>
      <CardDescription>Manage tokens your organization can use to access our API.</CardDescription>
    </CardHeader>
    <CardContent>
      <Table>
        <TableHeader>
          <TableRow>
            <TableHead>Name</TableHead>
            <TableHead>Permissions</TableHead>
            <TableHead>Created</TableHead>
            <TableHead>Last Used</TableHead>
            <TableHead></TableHead>
          </TableRow>
        </TableHeader>
        <TableBody>
          <TableRow v-for="item in tokens" :key="item.id">
            <TableCell>
              {{ item.name }}
            </TableCell>
            <TableCell class="capitalize">
              {{ item.abilities.join(', ') }}
            </TableCell>
            <TableCell>
              {{ DateTime.fromISO(item.createdAt).toLocaleString() }}
            </TableCell>
            <TableCell>
              <span v-if="item.lastUsedAt">
                {{ DateTime.fromISO(item.lastUsedAt).toLocaleString() }}
              </span>
            </TableCell>
            <TableCell>
              <!-- delete button -->
            </TableCell>
          </TableRow>
        </TableBody>
      </Table>

      <div class="flex justify-end mt-4">
        <Button type="button" @click="isDialogShown = true"> Add Access Token </Button>
      </div>
    </CardContent>
  </Card>
</template>
Copied!
  • inertia
  • components
  • OrganizationAccessTokensCard.vue

That's all for now!

Join the Discussion 0 comments

Create a free account to join in on the discussion
robot comment bubble

Be the first to comment!