Skip to content

Issue/#210 fix sso #214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 5, 2024
Merged
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
3 changes: 1 addition & 2 deletions app.vue
Original file line number Diff line number Diff line change
@@ -5,8 +5,7 @@
<script lang="ts" setup>
import "./src/assets/index.css";
import "./src/assets/vendor";
import { useEventsStore, useSettingsStore } from "~/src/shared/stores";
import { useEventsStore } from "~/src/shared/stores";

useSettingsStore().initialize();
useEventsStore().initialize();
</script>
26 changes: 14 additions & 12 deletions middleware/auth.global.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,32 @@
import { navigateTo, defineNuxtRouteMiddleware } from "#app";
import { useSettings } from "~/src/shared/lib/use-settings";
import {useSettingsStore, useProfileStore} from "~/src/shared/stores";

export default defineNuxtRouteMiddleware(async (to) => {
const { auth} = storeToRefs(useSettingsStore())
const settingsStore = useSettingsStore()
const {isFetched, isAuthEnabled } = storeToRefs(settingsStore)

if (!auth.value.isEnabled) {
if (!isFetched.value) {
await settingsStore.fetchSettings()
}

if (!isAuthEnabled.value) {
return undefined
}

const store = useProfileStore()
store.fetchToken()
const profileStore = useProfileStore()
const { isAuthenticated} = storeToRefs(profileStore)
await profileStore.getStoredToken()

if (store.isAuthenticated) {
const {api: {getProfile}} = useSettings();
const profile = await getProfile();
store.setProfile(profile)
return undefined
if (isAuthenticated.value) {
await profileStore.getProfile();
}

if (to.name !== 'login' && !store.isAuthenticated) {
if (to.name !== 'login' && !isAuthenticated.value) {
return navigateTo('/login')
}

if (to.name === 'login' && to?.query?.token) {
store.setToken(String(to.query.token))
profileStore.setToken(String(to.query.token))
return navigateTo('/')
}

17 changes: 9 additions & 8 deletions pages/login.vue
Original file line number Diff line number Diff line change
@@ -9,13 +9,14 @@ import { IconSvg } from "~/src/shared/ui";
setPageLayout("blank");

const store = useProfileStore();
const { auth } = storeToRefs(useSettingsStore());
const { authLogicUrl } = storeToRefs(useSettingsStore());

if (store.isAuthenticated) {
setPageLayout("default");
await navigateTo("/");
}

const loginUrl = computed(() => `${REST_API_URL}/${auth.value.loginUrl}`);
const loginUrl = computed(() => `${REST_API_URL}/${authLogicUrl.value}`);

const redirect = async () => {
await navigateTo(loginUrl.value, {
@@ -42,11 +43,11 @@ const redirect = async () => {
</div>
<div
class="login-form-right-block"
style="
background: url('/bg.jpg');
background-size: cover;
background-position: center center;
"
:style="{
background: `url('/bg.jpg')`,
backgroundSize: 'cover',
backgroundPosition: 'center center',
}"
></div>
</div>
</div>
@@ -91,7 +92,7 @@ const redirect = async () => {
}

.login-form--title {
@apply text-4xl text-center font-thin;
@apply text-4xl text-center font-thin text-black;
@apply my-10;
}

4 changes: 2 additions & 2 deletions src/shared/lib/use-events/use-events-api.ts
Original file line number Diff line number Diff line change
@@ -86,8 +86,8 @@ export const useEventsApi = (): TUseEventsApi => {
// NOTE: clear cached events hardly
eventsStore.removeAll();
}
}).catch((err) => {
console.error('getAll err', err);
}).catch((e) => {
console.error(e);
})
}

23 changes: 1 addition & 22 deletions src/shared/lib/use-settings/use-settings.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,17 @@
import {useProfileStore} from "../../stores/profile/profile-store";
import type {TProfile, TSettings, TProjects} from "../../types";
import type { TProjects} from "../../types";
import { REST_API_URL } from "../io/constants";


type TUseSettings = {
api: {
getProfile: () => Promise<TProfile>
getSettings: () => Promise<TSettings>
getProjects: () => Promise<TProjects>
}
}

export const useSettings = (): TUseSettings => {
const { token } = storeToRefs(useProfileStore())

const getAppSettings = () => fetch(`${REST_API_URL}/api/settings`)
.then((response) => response.json())
.catch((e) => {
console.error(e);

return null
});

const getProfile = () => fetch(`${REST_API_URL}/api/me`, {
headers: {"X-Auth-Token": token.value || ""}
})
.then((response) => response.json())
.catch((e) => {
console.error(e);

return null
});
const getProjects = () => fetch(`${REST_API_URL}/api/projects`, {
headers: {"X-Auth-Token": token.value || ""}
})
@@ -43,9 +24,7 @@ export const useSettings = (): TUseSettings => {

return {
api: {
getProfile,
getProjects,
getSettings: getAppSettings
}
}
}
42 changes: 39 additions & 3 deletions src/shared/stores/profile/profile-store.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { defineStore } from "pinia";
import {navigateTo} from "#app"; // eslint-disable-line @conarti/feature-sliced/layers-slices
import {REST_API_URL} from "../../lib/io/constants";
import type {TProfile} from "../../types";
import {getStoredToken, removeStoredToken, setStoredToken} from "./local-storage-actions";

@@ -10,19 +12,53 @@ export const useProfileStore = defineStore("profileStore", {
}),
getters: {
isAuthenticated(): boolean {
return this.token !== undefined && this.token !== null && this.token !== "null";
return !!this.token && this.token !== "null";
},
},
actions: {
setToken(token: string): void {
this.token = token;
setStoredToken(token);
},
async getProfile(): Promise<TProfile> {
// TODO: need to remove fetch out of the store
const profile = await fetch(`${REST_API_URL}/api/me`, {
headers: {"X-Auth-Token": this.token || ""}
})
.then((response) => {
if (!response.ok && response.status === 403) {
this.removeToken();

// TODO: add toast to show error
console.error('Auth Error', response.status, response.statusText)

navigateTo('/login')
}

return response
})
.then((response) => response.json())
.catch((e) => {
console.error(e);

return null
});

this.setProfile(profile)

return profile
},
setProfile(profile: TProfile): void {
this.profile = profile;
},
fetchToken(): void {
this.setToken(getStoredToken() || '');
getStoredToken(): string {
const token = getStoredToken()

if (token) {
this.setToken(token);
}

return token
},
removeToken(): void {
this.token = '';
40 changes: 24 additions & 16 deletions src/shared/stores/settings/settings-store.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {defineStore} from "pinia";
import {useSettings} from "../../lib/use-settings";
import {REST_API_URL} from "../../lib/io/constants";
import type { TSettings } from "../../types";
import {THEME_MODES} from "./constants";
import {
@@ -16,29 +16,37 @@ import {
export const useSettingsStore = defineStore("settingsStore", {
state: () => ({
apiVersion: '',
auth: {
isEnabled: false,
loginUrl: '/login',
},
isFetched: false,
isAuthEnabled: false,
authLogicUrl: '/login',
codeEditor: getStoredPrimaryCodeEditor() || 'phpstorm',
themeType: getStoredActiveTheme(),
isFixedHeader: getStoredFixedHeader(),
isVisibleEventCounts: getStoredEventsCountVisibility(),
}),
actions: {
initialize() {
const {api: { getSettings }} = useSettings();
async fetchSettings() {
// TODO: need to remove fetch out of the store
const settings: TSettings = await fetch(`${REST_API_URL}/api/settings`)
.then((response) => response.json())
.catch((e) => {
console.error(e);

return null
});

if (settings.version) {
this.apiVersion = settings.version
}

if (settings.auth) {
this.isAuthEnabled = settings.auth.enabled;
this.authLogicUrl = settings.auth.login_url;
}

getSettings().then(({ version, auth } = {} as TSettings) => {
if (version) {
this.apiVersion = version
}
this.isFetched = true

if (auth) {
this.auth.isEnabled = auth.enabled;
this.auth.loginUrl = auth.login_url;
}
})
return settings
},
changeTheme() {
this.themeType = this.themeType === THEME_MODES.DARK
4 changes: 1 addition & 3 deletions src/widgets/ui/layout-sidebar/layout-sidebar.vue
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ import { version } from "../../../../package.json";
import { EVENTS_LINKS_MAP, EVENTS_NAV_ORDER } from "./constants";

const { isConnectedWS } = storeToRefs(useConnectionStore());
const { isVisibleEventCounts, auth } = storeToRefs(useSettingsStore());
const { isVisibleEventCounts, isAuthEnabled } = storeToRefs(useSettingsStore());
const eventsStore = useEventsStore();
const { availableProjects, isMultipleProjects, activeProject } =
storeToRefs(eventsStore);
@@ -104,8 +104,6 @@ const logout = () => {

const path = computed(() => useRoute().path);

const isAuthEnabled = computed(() => auth.value.isEnabled);

const { apiVersion } = storeToRefs(useSettingsStore());

const clientVersion = ref(
8 changes: 4 additions & 4 deletions src/widgets/ui/page-layout/page-layout.vue
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ const props = withDefaults(defineProps<Props>(), {
const { events, cachedEvents } = useEvents();

const isEventsPaused = computed(
() => cachedEvents.idsByType.value[props.type]?.length > 0
() => cachedEvents.idsByType.value[props.type]?.length > 0,
);

const allEvents = computed(() => {
@@ -35,13 +35,13 @@ const visibleEvents = computed(() => {
}

return allEvents.value.filter(({ uuid }) =>
cachedEvents.idsByType.value[props.type]?.includes(uuid)
cachedEvents.idsByType.value[props.type]?.includes(uuid),
);
});

watchEffect(() => {
useTitle(
`${props.title || "Events"}: ${allEvents.value.length} | Buggregator`
`${props.title || "Events"}: ${allEvents.value.length} | Buggregator`,
);
});
</script>
@@ -67,7 +67,7 @@ watchEffect(() => {
@import "src/assets/mixins";

.page-layout {
@apply flex flex-col h-full
@apply flex flex-col h-full w-full;
}

.page-layout__events {