Skip to content

Commit b8257c5

Browse files
committed
Replace policy type authentication with password login
1 parent e22573a commit b8257c5

19 files changed

+311
-96
lines changed

README.md

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,10 @@ To make use of it, publish its assets:
103103
php artisan vendor:publish --tag=cloud-tasks-assets
104104
```
105105

106-
We expose a dashboard at the /cloud-tasks URI. By default, you will only be able to access this dashboard in the local environment. However, within your app/Providers/AppServiceProvider.php file, there is an authorization gate definition. This authorization gate controls access to Cloud Tasks in non-local environments. You are free to modify this gate as needed to restrict access to your Cloud Tasks installation:
106+
We expose a dashboard at the /cloud-tasks URI.
107107

108108

109109
```php
110-
Gate::define('viewCloudTasks', function ($user) {
111-
return in_array($user->email, [
112-
113-
]);
114-
});
115110
```
116111

117112
# Authentication

config/cloud-tasks.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
return [
66
'monitor' => [
77
'enabled' => env('CLOUD_TASKS_MONITOR_ENABLED', false),
8+
'password' => env('CLOUD_TASKS_MONITOR_PASSWORD', '$2a$12$q3pRT5jjjjPlTSaGhoy.gupULnK.5lQEiquK5RVaWbGw9nYRy7gwi') // MyPassword1!
89
],
910
];

dashboard/.prettierignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# Ignore artifacts:
2+
build
3+
coverage
4+
.vscode
5+
node_modules
6+
.idea

dashboard/.prettierrc.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"semi": false,
3+
"singleQuote": true
4+
}

dashboard/src/App.vue

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
--popper-theme-box-shadow: 0 6px 30px -6px rgba(0, 0, 0, 0.25);
2525
}
2626
</style>
27-
<script>
27+
<script setup>
2828
import Menu from './components/Menu.vue'
29-
export default {
30-
components: { Menu },
31-
}
3229
</script>

dashboard/src/api.js

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,39 @@
11
import { onUnmounted, watch } from 'vue'
22
import { onBeforeRouteUpdate } from 'vue-router'
33

4-
export async function fetchTasks(into, query = {}) {
4+
export async function callApi({
5+
endpoint,
6+
router,
7+
body = null,
8+
method = 'GET',
9+
login = false,
10+
} = {}) {
11+
const response = await fetch(
12+
`${import.meta.env.VITE_API_URL || ''}/cloud-tasks-api/${endpoint}`,
13+
{
14+
method,
15+
...(body ? { body } : {}),
16+
headers: {
17+
...(!login
18+
? {
19+
Authorization: `Bearer ${localStorage.getItem(
20+
'cloud-tasks-token'
21+
)}`,
22+
}
23+
: {}),
24+
},
25+
}
26+
)
27+
28+
if (response.status === 403 && !login) {
29+
localStorage.removeItem('cloud-tasks-token')
30+
router.push({ name: 'login' })
31+
}
32+
33+
return login ? await response.text() : await response.json()
34+
}
35+
36+
export async function fetchTasks(into, query = {}, router) {
537
let paused = false
638

739
const f = async function (into) {
@@ -17,14 +49,11 @@ export async function fetchTasks(into, query = {}) {
1749
}
1850

1951
paused = true
20-
fetch(
21-
`${import.meta.env.VITE_API_URL || ''}/cloud-tasks-api/tasks?${queryParams.toString()}`
22-
)
23-
.then((response) => response.json())
24-
.then((response) => {
25-
into.value = response
26-
paused = false
27-
})
52+
into.value = await callApi({
53+
endpoint: `tasks?${queryParams.toString()}`,
54+
router,
55+
})
56+
paused = false
2857
}
2958

3059
f(into)

dashboard/src/components/Dashboard.vue

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
<script setup>
2-
import { ref } from 'vue'
2+
import { onMounted, ref } from 'vue'
3+
import { useRouter } from 'vue-router'
4+
import { callApi } from '../api'
35
6+
const router = useRouter()
47
const dashboard = ref({
58
recent: {
69
this_minute: '...',
@@ -14,11 +17,12 @@ const dashboard = ref({
1417
},
1518
})
1619
17-
const tsLoaded = Math.floor(Date.now() / 1000)
18-
19-
fetch(`${import.meta.env.VITE_API_URL || ''}/cloud-tasks-api/dashboard`)
20-
.then((response) => response.json())
21-
.then((response) => (dashboard.value = response))
20+
onMounted(async () => {
21+
dashboard.value = await callApi({
22+
endpoint: 'dashboard',
23+
router,
24+
})
25+
})
2226
</script>
2327

2428
<template>

dashboard/src/components/Failed.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22
import { ref } from 'vue'
33
import { fetchTasks } from '../api'
44
import Overview from './Overview.vue'
5+
import { useRouter } from 'vue-router'
56
67
defineProps({
78
tasks: Array,
89
})
910
1011
const tasks = ref(null)
12+
const router = useRouter()
1113
12-
fetchTasks(tasks, {
13-
filter: 'failed',
14-
})
14+
fetchTasks(
15+
tasks,
16+
{
17+
filter: 'failed',
18+
},
19+
router
20+
)
1521
</script>
1622

1723
<template>

dashboard/src/components/Login.vue

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<template>
2+
<div class="block w-full h-full flex items-center justify-center">
3+
<div>
4+
<h3 class="text-4xl">This application is password protected.</h3>
5+
<input
6+
type="password"
7+
class="w-full p-2 px-6 text-2xl font-light mt-8 text-center outline-none shadow rounded-full"
8+
:class="{ shake: incorrect }"
9+
@keyup.enter="attemptLogin"
10+
v-model="pw"
11+
:disabled="loading"
12+
ref="inputRef"
13+
/>
14+
<div class="text-center mt-6 text-xl">
15+
Press
16+
<span class="bg-blue-200 py-1 px-2 ml-2 mr-2 rounded text-blue-800"
17+
>Enter</span
18+
>
19+
to log in.
20+
</div>
21+
</div>
22+
</div>
23+
</template>
24+
25+
<script setup>
26+
import { onMounted, ref } from 'vue'
27+
import { useRouter } from 'vue-router'
28+
import { callApi } from '../api'
29+
30+
const router = useRouter()
31+
const inputRef = ref(null)
32+
const pw = ref('')
33+
const pwPrev = ref('')
34+
const incorrect = ref(false)
35+
const loading = ref(false)
36+
37+
onMounted(() => {
38+
inputRef.value.focus()
39+
})
40+
41+
async function attemptLogin() {
42+
if (pw.value === '' || pw.value === pwPrev.value) {
43+
return
44+
}
45+
pwPrev.value = pw.value
46+
const formData = new FormData()
47+
formData.append('password', pw.value)
48+
49+
loading.value = true
50+
const token = await callApi({
51+
endpoint: 'login',
52+
method: 'POST',
53+
body: formData,
54+
login: true,
55+
})
56+
loading.value = false
57+
58+
if (token) {
59+
localStorage.setItem('cloud-tasks-token', token)
60+
router.push({ name: 'home' })
61+
} else {
62+
incorrect.value = true
63+
setTimeout(() => {
64+
incorrect.value = false
65+
}, 820)
66+
setTimeout(() => inputRef.value.focus(), 50)
67+
}
68+
}
69+
</script>
70+
71+
<style lang="css" scoped>
72+
@keyframes shake {
73+
8%,
74+
41% {
75+
transform: translateX(-10px);
76+
}
77+
25%,
78+
58% {
79+
transform: translateX(10px);
80+
}
81+
75% {
82+
transform: translateX(-5px);
83+
}
84+
92% {
85+
transform: translateX(5px);
86+
}
87+
0%,
88+
100% {
89+
transform: translateX(0);
90+
}
91+
}
92+
93+
.shake {
94+
animation: shake 0.3s linear;
95+
}
96+
97+
input[type='password'] {
98+
font: small-caption;
99+
font-size: 36px;
100+
}
101+
</style>

dashboard/src/components/Queued.vue

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,22 @@
22
import { ref } from 'vue'
33
import { fetchTasks } from '../api'
44
import Overview from './Overview.vue'
5+
import { useRouter } from 'vue-router'
56
67
defineProps({
78
tasks: Array,
89
})
910
1011
const tasks = ref(null)
12+
const router = useRouter()
1113
12-
fetchTasks(tasks, {
13-
status: 'queued',
14-
})
14+
fetchTasks(
15+
tasks,
16+
{
17+
status: 'queued',
18+
},
19+
router
20+
)
1521
</script>
1622

1723
<template>

0 commit comments

Comments
 (0)