Session api token validation

This commit is contained in:
2026-06-27 19:11:23 +10:00
parent 6e69bea82a
commit 164b590a6c
7 changed files with 66 additions and 17 deletions
+18 -7
View File
@@ -15,16 +15,27 @@ class UpdateAlliances extends Command
{ {
public function handle() public function handle()
{ {
$time = now('UTC')->startOfMinute(); $day = now('UTC')->startOfMinute()->toDateString();
$day = Date('Y-m-d', $time);
if($day == '2026-12-17'){ $schedules = [
Airline::whereInternalName('asiana')->update(['alliance' => null]); '2026-12-17' => [
['airline' => 'asiana', 'alliance' => null],
],
'2027-12-12' => [
['airline' => 'philippine-airlines', 'alliance' => 'oneworld'],
],
];
if (!isset($schedules[$day])) {
return;
} }
if($day == '2027-12-12'){ foreach ($schedules[$day] as $change) {
$oneworld = Alliance::whereInternalName('oneworld')->first(); $allianceId = $change['alliance']
Airline::whereInternalName('philippine-airlines')->update(['alliance' => $oneworld->id]); ? Alliance::whereInternalName($change['alliance'])->value('id')
: null;
Airline::whereInternalName($change['airline'])->update(['alliance' => $allianceId]);
} }
} }
+1 -1
View File
@@ -65,7 +65,7 @@ class FeedController extends Controller
->pluck('id'); ->pluck('id');
return UserFlight::query() return UserFlight::query()
->with(['departureAirport', 'arrivalAirport', 'user']) ->with(['departureAirport', 'departureAirport.region.country', 'arrivalAirport', 'arrivalAirport.region.country', 'user', 'airline'])
->whereIn('user_id', $followingIds) ->whereIn('user_id', $followingIds)
->orderByDesc('departure_date') ->orderByDesc('departure_date')
->limit(100) ->limit(100)
+1 -1
View File
@@ -15,7 +15,7 @@ class HomePageController extends Controller
{ {
return Cache::remember('splash_flights', now()->addHours(12), function () { return Cache::remember('splash_flights', now()->addHours(12), function () {
return UserFlight::query() return UserFlight::query()
->with(['departureAirport', 'arrivalAirport', 'user']) ->with(['departureAirport', 'departureAirport.region.country', 'arrivalAirport', 'arrivalAirport.region.country' ,'user', 'airline'])
->whereHas('user', function ($query) { ->whereHas('user', function ($query) {
$query->whereRaw(DB::raw("settings->>'profile_privacy' is distinct from 'private'")); $query->whereRaw(DB::raw("settings->>'profile_privacy' is distinct from 'private'"));
}) })
+7
View File
@@ -74,6 +74,13 @@ class SettingsRegistry
'category' => 'FlightsGoneBy Settings', 'category' => 'FlightsGoneBy Settings',
'default' => true, 'default' => true,
], ],
[
'key' => 'hide_map_filters',
'type' => 'checkbox',
'label' => 'Hide Map Filters By Default',
'category' => 'FlightsGoneBy Settings',
'default' => false,
],
[ [
'key' => 'hide_impossible_achievements', 'key' => 'hide_impossible_achievements',
'type' => 'checkbox', 'type' => 'checkbox',
@@ -2,6 +2,7 @@
import {computed, ref} from "vue"; import {computed, ref} from "vue";
import {Flight, User} from "@/Types/types"; import {Flight, User} from "@/Types/types";
import {router} from "@inertiajs/vue3"; import {router} from "@inertiajs/vue3";
import { copyToClipboard } from "@/Composables/useClipboard";
defineProps<{ defineProps<{
profileUser: User profileUser: User
@@ -21,6 +22,21 @@ const showDeleteDialog = computed({
set: (val) => { if (!val) flightToDelete.value = null } set: (val) => { if (!val) flightToDelete.value = null }
}) })
function copyFlightToClipboard(flight: Flight) {
const dep = `${flight.departure_airport.display_code} (${flight.departure_airport.municipality})`
const arr = `${flight.arrival_airport.display_code} (${flight.arrival_airport.municipality})`
const times = `${flight.departure_time_display}${flight.arrival_time_display}`
const dayDiff = flight.arrival_day_difference !== 0
? `(${flight.arrival_day_difference > 0 ? '+' : ''}${flight.arrival_day_difference})`
: ''
const airline = flight.airline?.display_name
const aircraft = flight.aircraft?.display_name
const reg = flight.aircraft_registration ? `(${flight.aircraft_registration})` : ''
const text = `${airline} | ${dep}${arr} ${dayDiff} | ${times} · ${flight.departure_date_display} | ${aircraft} ${reg}`
copyToClipboard(text)
}
</script> </script>
<template> <template>
@@ -40,6 +56,11 @@ const showDeleteDialog = computed({
title="View Details" title="View Details"
:href="route('profile.flight', { userFlight: flight.id, user: profileUser.name })" :href="route('profile.flight', { userFlight: flight.id, user: profileUser.name })"
/> />
<v-list-item
prepend-icon="mdi-content-copy"
title="Copy to Clipboard"
@click="copyFlightToClipboard(flight)"
/>
<v-list-item v-if="canEdit" <v-list-item v-if="canEdit"
prepend-icon="mdi-pencil-outline" prepend-icon="mdi-pencil-outline"
title="Edit" title="Edit"
+17 -8
View File
@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import MainLayout from "@/Layouts/MainLayout.vue" import MainLayout from "@/Layouts/MainLayout.vue"
import { Head, router } from '@inertiajs/vue3' import {Head, router, usePage} from '@inertiajs/vue3'
import { computed, ref, watchEffect } from 'vue' import {computed, ref, watch, watchEffect} from 'vue'
import { Flight, ProfileView, RegionRange, User, FlightRange, FlightScope } from "@/Types/types" import {Flight, ProfileView, RegionRange, User, FlightRange, FlightScope, SharedProps} from "@/Types/types"
import { useFlightStats } from "@/Composables/useFlightStats" import { useFlightStats } from "@/Composables/useFlightStats"
import ProfileViewSwitcher from "@/Components/FlightsGoneBy/ProfileViewSwitcher.vue" import ProfileViewSwitcher from "@/Components/FlightsGoneBy/ProfileViewSwitcher.vue"
import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue" import ProfileLayout from "@/Components/FlightsGoneBy/ProfileLayout.vue"
@@ -11,9 +11,13 @@ import BoardingPasses from "@/Components/FlightsGoneBy/BoardingPasses.vue"
import FlightMapAndCharts from "@/Components/FlightsGoneBy/FlightMapAndCharts.vue" import FlightMapAndCharts from "@/Components/FlightsGoneBy/FlightMapAndCharts.vue"
import FlightFilter from "@/Components/FlightsGoneBy/FlightFilter.vue" import FlightFilter from "@/Components/FlightsGoneBy/FlightFilter.vue"
import { useFlights } from "@/Composables/useFlights" import { useFlights } from "@/Composables/useFlights"
import {useUpdateSetting} from "@/Composables/useUpdateSetting";
defineOptions({ layout: MainLayout }) defineOptions({ layout: MainLayout })
const {updateSetting} = useUpdateSetting()
const page = usePage<SharedProps>().props
const props = defineProps<{ const props = defineProps<{
user: User user: User
canEdit: boolean canEdit: boolean
@@ -24,6 +28,13 @@ const props = defineProps<{
flightCount: number flightCount: number
}>() }>()
const hideFilters = ref(page.auth?.user?.resolved_settings?.hide_map_filters ?? false)
watch(hideFilters, (value) => {
updateSetting('hide_map_filters', value).catch(() => {})
})
// ── Flights state ───────────────────────────────────────────────────────────── // ── Flights state ─────────────────────────────────────────────────────────────
const { flights, flightsLoading } = useFlights(`/internal/user/${props.user.name}/flights`) const { flights, flightsLoading } = useFlights(`/internal/user/${props.user.name}/flights`)
@@ -31,8 +42,6 @@ const localSelectedFlightId = ref(props.selectedFlightId ?? null)
// ── Filter state ────────────────────────────────────────────────────────────── // ── Filter state ──────────────────────────────────────────────────────────────
const filtersOpen = ref(window.innerWidth >= 1024)
const selectedYears = ref<number[]>([]) const selectedYears = ref<number[]>([])
const selectedAirlines = ref<number[]>([]) const selectedAirlines = ref<number[]>([])
const selectedAlliances = ref<number[]>([]) const selectedAlliances = ref<number[]>([])
@@ -162,7 +171,7 @@ const routeNames: Record<Exclude<ProfileView, 'achievements'>, string> = {
} as const } as const
function toggleFilters(e: MouseEvent) { function toggleFilters(e: MouseEvent) {
filtersOpen.value = !filtersOpen.value hideFilters.value = !hideFilters.value
;(e.currentTarget as HTMLButtonElement).blur() ;(e.currentTarget as HTMLButtonElement).blur()
} }
@@ -193,7 +202,7 @@ function switchView(view: ProfileView) {
<ProfileViewSwitcher :user="user" :active-view="activeView" @update:active-view="switchView" /> <ProfileViewSwitcher :user="user" :active-view="activeView" @update:active-view="switchView" />
<button <button
class="filter-toggle" class="filter-toggle"
:class="{ active: filtersOpen || activeFilterCount > 0 }" :class="{ active: !hideFilters || activeFilterCount > 0 }"
@click="toggleFilters" @click="toggleFilters"
> >
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> <svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
@@ -204,7 +213,7 @@ function switchView(view: ProfileView) {
</button> </button>
</div> </div>
<div v-show="filtersOpen" class="filter-panel"> <div v-show="!hideFilters" class="filter-panel">
<FlightFilter :flights="flights" @change="onFiltersChange" /> <FlightFilter :flights="flights" @change="onFiltersChange" />
</div> </div>
+1
View File
@@ -29,6 +29,7 @@ export interface UserSettings {
departure_board_columns: string[] departure_board_columns: string[]
show_map_legend: boolean show_map_legend: boolean
hide_impossible_achievements: boolean hide_impossible_achievements: boolean
hide_map_filters: boolean
} }