Skip to content
1 change: 1 addition & 0 deletions src/models/LocalStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export enum LocalStorageItem {
TokenScopes = 'token-scopes',
MarketingId = 'marketing-id',
SuperappAuth = 'superapp-auth',
AppToken = 'app-token',
}

export class LocalStorage {
Expand Down
7 changes: 7 additions & 0 deletions src/models/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,13 @@ export type Lecturer = timetableComponents['schemas']['LecturerGet'];
export type Room = timetableComponents['schemas']['RoomGet'];
export type StudyGroup = timetableComponents['schemas']['GroupGet'];

// app models
export interface AppToken {
appId: number;
token: string | undefined;
expire: number;
}

// general models
export interface Entity {
id: number;
Expand Down
43 changes: 41 additions & 2 deletions src/store/apps.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,48 @@
import { defineStore } from 'pinia';
import { ref } from 'vue';
import { Category } from '@/models';
import { Category, AppToken } from '@/models';
import { LocalStorage, LocalStorageItem } from '@/models/LocalStorage';

export const useAppsStore = defineStore('apps', () => {
const categories = ref<Category[]>([]);
const appTokens = ref<AppToken[]>([]);

return { categories };
const addAppToken = (appId: number, token: string | undefined, expire: number) => {
appTokens.value.push({
appId,
token,
expire,
});
LocalStorage.set(LocalStorageItem.AppToken, appTokens.value);
};

const checkAppToken = (appId: number) => {
const appToken = appTokens.value.find(item => item.appId === appId);
const currentDate = new Date();

if (!appToken) {
return undefined;
} else {
if (appToken.expire < currentDate.getTime()) {
appTokens.value.splice(appTokens.value.indexOf(appToken), 1);
LocalStorage.set(LocalStorageItem.AppToken, appTokens.value);
return undefined;
} else {
return appToken.token;
}
}
};

const getTokensFromStorage = () => {
appTokens.value = LocalStorage.getObject(LocalStorageItem.AppToken) ?? [];
};

return {
categories,
appTokens,

addAppToken,
checkAppToken,
getTokensFromStorage,
};
});
59 changes: 33 additions & 26 deletions src/views/apps/ApplicationFrame.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@ import { AuthApi } from '@/api/controllers/auth/AuthApi';
import { ServiceData } from '@/models';
import apiClient from '@/api/';
import { msInHour } from '@/utils/time';
import { useAppsStore } from '@/store/apps';

const route = useRoute();
const toolbar = useToolbar();
const router = useRouter();
const profileStore = useProfileStore();
const appStore = useAppsStore();
appStore.getTokensFromStorage();

enum AppState {
WaitLoad = 1,
Expand Down Expand Up @@ -47,14 +50,15 @@ const composeUrl = async (url: URL, token: string | null, scopes: string[]) => {
return url;
};

function showApproveScopesScreen() {
appState.value = AppState.WaitApprove;
// immediately return a Promise
// return new Promise(resolve => {
// watch(userScopeApproved, value => resolve(value));
// });
return true;
}
// function showApproveScopesScreen() {
// appState.value = AppState.WaitApprove;
// // immediately return a Promise
// // Раскомментить, если появятся сторонние приложения
// // return new Promise(resolve => {
// // watch(userScopeApproved, value => resolve(value));
// // });
// return true;
// }

const getToken = async () => {
// Запрашиваем токен. Для этого:
Expand All @@ -67,14 +71,10 @@ const getToken = async () => {
return;
}

console.log(scopes.value);
const valuesToSearch = new Set(scopes.value);
console.log(valuesToSearch);

userInfo.user_scopes.forEach(item => {
console.log(item);
if (valuesToSearch.has(item.name)) {
console.log(' found');
// TODO: Поменять name на comment, когда допилю ручку me (и, возможно, поменять /me на /scope)
if (item.name !== undefined && item.name !== null) {
scopeNamesToRequest.value.push(item.name);
Expand All @@ -85,27 +85,33 @@ const getToken = async () => {
// 2. Если нужен токен без скоупов, то пропускаем запрос на разрешение у пользователя
if (scopes.value.length != 0) {
// 2.1 Показываем пользователю список прав, которые приложение запрашивает, и кнопки "разрешить"/"запретить"
const scopesApproved = await showApproveScopesScreen();
const scopesApproved = true; // await showApproveScopesScreen();

// 2.2 Если пользователь не разрешает – возваращаем undefined
if (!scopesApproved) return undefined;
}

// 3. Если пользователь разрешает – запрашиваем токен на Auth api и возвращаем его
const expiresDate = new Date(Date.now() + msInHour);
const { data } = await apiClient.POST('/auth/session', {
body: {
scopes: scopes.value.length == 0 ? [] : scopes.value,
expires: expiresDate.toISOString(),
},
});
if (!data) {
appState.value = AppState.Error;
return;
}
profileStore.id = data.user_id;
const storageToken = appStore.checkAppToken(appId);
if (storageToken) {
return storageToken;
} else {
const expiresDate = new Date(Date.now() + msInHour / 60);
const { data } = await apiClient.POST('/auth/session', {
body: {
scopes: scopes.value.length == 0 ? [] : scopes.value,
expires: expiresDate.toISOString(),
},
});
if (!data) {
appState.value = AppState.Error;
return;
}
profileStore.id = data.user_id;
appStore.addAppToken(appId, data.token ?? undefined, expiresDate.getTime());

return data.token;
return data.token;
}
};

const openApp = async (data: ServiceData) => {
Expand All @@ -114,6 +120,7 @@ const openApp = async (data: ServiceData) => {
appState.value = AppState.Error;
return;
}

// Приложения открываем только по https
if (data.link === undefined || !data.link?.startsWith('https://')) {
appState.value = AppState.Error;
Expand Down
4 changes: 0 additions & 4 deletions src/views/auth/AuthView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ import ForgotPassordForm from '@/components/ForgotPassordForm.vue';
import IrdomAuthButton from '@/components/IrdomAuthButton.vue';
import { authButtons } from '@/constants/authButtons';
import { ref } from 'vue';
import { useProfileStore } from '@/store/profile';

const profileStore = useProfileStore();

const toolbar = useToolbar();

Expand Down Expand Up @@ -41,7 +38,6 @@ const switchState = async (to: Step) => {
}
};

console.log(profileStore.token);
toolbar.setup({ title: 'Вход в профиль' });
</script>

Expand Down
Loading