Skip to content

Commit

Permalink
chore: merge pull request #324 from tom-theret/service/multi
Browse files Browse the repository at this point in the history
Feat: Ajout des universités prise en charge par ESUP Multi
  • Loading branch information
Vexcited authored Nov 2, 2024
2 parents 7ca90a8 + 232ccda commit 1464d7c
Show file tree
Hide file tree
Showing 19 changed files with 105 additions and 81 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ Voici un aperçu de ce que nous avons accompli jusqu'à présent et de ce qu'il
- [x] 🟡 Skolengo
- [x] 🏫 Universités
- Limoges
- Lorraine
- Nîmes
- Polytechnique Hauts-de-France (UPHF)
- Rennes 1
- Rennes 2
Expand Down
Binary file added assets/images/service_ulorraine.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/images/service_unimes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
35 changes: 18 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"buffer": "^6.0.3",
"cal-parser": "^1.0.2",
"date-fns": "^3.6.0",
"esup-multi.js": "^1.0.1",
"expo": "^51.0.36",
"expo-asset": "^10.0.10",
"expo-auth-session": "~5.5.2",
Expand Down Expand Up @@ -92,7 +93,6 @@
"scolengo-api": "^3.0.5",
"text-encoding": "^0.7.0",
"turbawself": "^1.1.1",
"uphf-api": "^2.2.0",
"zustand": "^4.5.2"
},
"devDependencies": {
Expand Down
3 changes: 2 additions & 1 deletion src/router/helpers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import type pronote from "pawnote";
import type React from "react";
import type { School as SkolengoSchool} from "scolengo-api/types/models/School";
import {Information} from "@/services/shared/Information";
import { ImageSourcePropType } from "react-native";

export type RouteParameters = {
// welcome.index
Expand Down Expand Up @@ -51,11 +52,11 @@ export type RouteParameters = {

// login.identityProvider
IdentityProviderSelector: undefined;
Multi_Login: { instanceURL: string, title: string, image: ImageSourcePropType };
UnivRennes1_Login: undefined;
UnivRennes2_Login: undefined;
UnivLimoges_Login: undefined;
UnivSorbonneParisNord_login: undefined;
UnivUphf_Login: undefined;

// login.skolengo
SkolengoAuthenticationSelector: undefined;
Expand Down
6 changes: 3 additions & 3 deletions src/router/screens/login/identityProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import UnivRennes1_Login from "@/views/login/IdentityProvider/providers/UnivRenn
import UnivLimoges_Login from "@/views/login/IdentityProvider/providers/UnivLimoges";
import UnivRennes2_Login from "@/views/login/IdentityProvider/providers/UnivRennes2";
import UnivSorbonneParisNord_login from "@/views/login/IdentityProvider/providers/UnivSorbonneParisNord";
import UnivUphf_Login from "@/views/login/IdentityProvider/providers/UnivUphf";
import Muli_Login from "@/views/login/IdentityProvider/providers/Multi";

export default [
createScreen("IdentityProviderSelector", IdentityProviderSelector, {
Expand Down Expand Up @@ -33,9 +33,9 @@ export default [
headerTitle: "Université Sorbonne Paris Nord",
}),

createScreen("UnivUphf_Login", UnivUphf_Login, {
createScreen("Multi_Login", Muli_Login, {
headerBackVisible: true,
headerTitle: "Université Polytechnique Hauts-de-France",
headerTitle: "ESUP Multi",
}),

] as const;
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { UphfAccount } from "@/stores/account/types";
import { MultiAccount } from "@/stores/account/types";
import { Information } from "../../shared/Information";
import { type ActualitiesResponse, UPHF } from "uphf-api";
import { AttachmentType } from "@/services/shared/Attachment";
import { ErrorServiceUnauthenticated } from "@/services/shared/errors";
import { ActualitiesResponse } from "esup-multi.js";

const parseInformation = (i: ActualitiesResponse): Information => ({
id: i.pubDate,
Expand All @@ -10,13 +11,16 @@ const parseInformation = (i: ActualitiesResponse): Information => ({
acknowledged: false,
attachments: [{"name": i.title,"type":"link" as AttachmentType, "url": i.link}],
content: i.content,
author: "UPHF Actualités",
author: "Actualités",
category: "Actualités",
read: false,
ref: i,
});

export const getNews = async (account: UphfAccount): Promise<Information[]> => {
const news = await UPHF.getActualities();
export const getNews = async (account: MultiAccount): Promise<Information[]> => {
if (!account.instance)
throw new ErrorServiceUnauthenticated("Multi");

const news = await account.instance.getActualities();
return news.map(parseInformation);
};
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { UphfAccount } from "@/stores/account/types";
import type { MultiAccount } from "@/stores/account/types";
import type { Timetable, TimetableClass} from "../../shared/Timetable";
import { weekNumberToDateRange } from "@/utils/epochWeekNumber";
import type { EventResponse } from "uphf-api";
import type { EventResponse } from "esup-multi.js";
import { ErrorServiceUnauthenticated } from "@/services/shared/errors";

const decodeTimetableClass = (c: EventResponse): TimetableClass => ({
Expand All @@ -17,11 +17,11 @@ const decodeTimetableClass = (c: EventResponse): TimetableClass => ({
source: "UPHF",
});

export const getTimetableForWeek = async (account: UphfAccount, weekNumber: number): Promise<Timetable> => {
export const getTimetableForWeek = async (account: MultiAccount, weekNumber: number): Promise<Timetable> => {
if (!account.instance)
throw new ErrorServiceUnauthenticated("UPHF");
throw new ErrorServiceUnauthenticated("Multi");

const timetable = await account.instance.getSchedule({startDate: weekNumberToDateRange(weekNumber).start.toISOString().split("T")[0], endDate:weekNumberToDateRange(weekNumber).end.toISOString().split("T")[0]});
const timetable = await account.instance.getSchedules({startDate: weekNumberToDateRange(weekNumber).start.toISOString().split("T")[0], endDate:weekNumberToDateRange(weekNumber).end.toISOString().split("T")[0]});
const eventsList = timetable.plannings.flatMap((planning) =>
planning.events.map((event: EventResponse) => ({
id: event.id,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Personalization, UphfAccount } from "@/stores/account/types";
import type { MultiAccount, Personalization } from "@/stores/account/types";
import { defaultTabs } from "@/consts/DefaultTabs";
import type pronote from "pawnote";

Expand All @@ -10,14 +10,10 @@ const defaultUphfTabs = [
"News",
] as typeof defaultTabs[number]["tab"][];

const defaultPersonalization = async (instance: UphfAccount["instance"]): Promise<Partial<Personalization>> => {
const profilePictureAsBase64 = await instance?.getProfilePictureAsBase64();
const defaultPersonalization = async (instance: MultiAccount["instance"]): Promise<Partial<Personalization>> => {
return {
color: colors[0],
magicEnabled: true,
profilePictureB64: (profilePictureAsBase64 !== null && profilePictureAsBase64 != "")
? await profilePictureAsBase64
: void 0,
tabs: defaultTabs.filter(current => defaultUphfTabs.includes(current.tab)).map((tab, index) => ({
name: tab.tab,
enabled: index <= 4
Expand Down
15 changes: 15 additions & 0 deletions src/services/multi/reload-multi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { MultiAccount } from "@/stores/account/types";
import type { Reconnected } from "../reload-account";
import { authWithRefreshToken } from "esup-multi.js";

export const reloadInstance = async (authentication: MultiAccount["authentication"]): Promise<Reconnected<MultiAccount>> => {
const session = await authWithRefreshToken(authentication.instanceURL, { refreshAuthToken: authentication.refreshAuthToken });

return {
instance: session,
authentication: {
instanceURL: authentication.instanceURL,
refreshAuthToken: session.userData.refreshAuthToken || ""
}
};
};
6 changes: 3 additions & 3 deletions src/services/news.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export async function updateNewsInCache <T extends Account> (account: T): Promis
useNewsStore.getState().updateInformations(informations);
break;
}
case AccountService.UPHF: {
const { getNews } = await import("./uphf/data/news");
case AccountService.Multi: {
const { getNews } = await import("./multi/data/news");
const informations = await getNews(account);
useNewsStore.getState().updateInformations(informations);
break;
Expand All @@ -64,7 +64,7 @@ export async function setNewsRead <T extends Account> (account: T, message: Info
}
case AccountService.Local:
case AccountService.EcoleDirecte:
case AccountService.UPHF:
case AccountService.Multi:
break;
default: {
throw new Error("Service not implemented.");
Expand Down
4 changes: 2 additions & 2 deletions src/services/reload-account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ export async function reload <T extends Account> (account: T): Promise<Reconnect
const res = await reload(account);
return { instance: res.instance, authentication: res.authentication };
}
case AccountService.UPHF: {
const { reloadInstance } = await import("./uphf/reload-uphf");
case AccountService.Multi: {
const { reloadInstance } = await import("./multi/reload-multi");
return await reloadInstance(account.authentication) as Reconnected<T>;
}
default: {
Expand Down
2 changes: 1 addition & 1 deletion src/services/shared/errors.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export class ErrorServiceUnauthenticated extends Error {
constructor (service: "pronote"|"ARD"|"turboself"|"skolengo"|"ecoledirecte"|"UPHF") {
constructor (service: "pronote"|"ARD"|"turboself"|"skolengo"|"ecoledirecte"|"Multi") {
super(`${service}: "account.instance" is not defined, you need to authenticate first.`);
this.name = "ErrorServiceUnauthenticated";
}
Expand Down
4 changes: 2 additions & 2 deletions src/services/timetable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export async function updateTimetableForWeekInCache <T extends Account> (account
useTimetableStore.getState().updateClasses(epochWeekNumber, timetable);
break;
}
case AccountService.UPHF: {
const { getTimetableForWeek } = await import("./uphf/data/timetable");
case AccountService.Multi: {
const { getTimetableForWeek } = await import("./multi/data/timetable");
const timetable = await getTimetableForWeek(account, epochWeekNumber);
useTimetableStore.getState().updateClasses(epochWeekNumber, timetable);
break;
Expand Down
14 changes: 0 additions & 14 deletions src/services/uphf/reload-uphf.ts

This file was deleted.

13 changes: 7 additions & 6 deletions src/stores/account/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { Account as PawdirecteAccount, Session as PawdirecteSession } from
import type { Session as TSSession, Authentication as TSAuthentication } from "turbawself";
import type { Client as ARDClient } from "pawrd";
import type ScolengoAPI from "scolengo-api";
import type UphfAPI from "uphf-api";
import type MultiAPI from "esup-multi.js";
import { SkolengoAuthConfig } from "@/services/skolengo/skolengo-types";
import { User as ScolengoAPIUser } from "scolengo-api/types/models/Common";

Expand Down Expand Up @@ -75,7 +75,7 @@ export enum AccountService {
ARD,
Parcoursup,
Onisep,
UPHF
Multi
}

/**
Expand Down Expand Up @@ -134,10 +134,11 @@ export interface SkolengoAccount extends BaseAccount {
identityProvider?: undefined
}

export interface UphfAccount extends BaseAccount {
service: AccountService.UPHF
instance?: UphfAPI.UPHF
export interface MultiAccount extends BaseAccount {
service: AccountService.Multi
instance?: MultiAPI.Multi
authentication: {
instanceURL: string
refreshAuthToken: string
}
identityProvider?: undefined
Expand Down Expand Up @@ -181,7 +182,7 @@ export type PrimaryAccount = (
| PronoteAccount
| EcoleDirecteAccount
| SkolengoAccount
| UphfAccount
| MultiAccount
| LocalAccount
);
export type ExternalAccount = (
Expand Down
23 changes: 20 additions & 3 deletions src/views/login/IdentityProvider/IdentityProviderSelector.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React, { memo, useEffect, useState } from "react";
import { Image, View, StyleSheet, Text } from "react-native";
import { Image, View, StyleSheet, Text, ImageSourcePropType } from "react-native";

import type { Screen } from "@/router/helpers/types";
import { ScrollView } from "react-native-gesture-handler";
Expand All @@ -8,12 +8,29 @@ import { Info } from "lucide-react-native";

const IdentityProviderSelector: Screen<"IdentityProviderSelector"> = ({ navigation }) => {
const universityProviders = [
{
name: "univ_lorraine",
title: "Université de Lorraine",
description: "Utilisez votre compte Sésame pour vous connecter",
image: require("@/../assets/images/service_ulorraine.png"),
instanceURL: "https://mobile-back.univ-lorraine.fr",
navigate: (instanceURL: string, title: string, image: ImageSourcePropType) => navigation.navigate("Multi_Login", { instanceURL, title, image }),
},
{
name: "univ_unimes",
title: "Université de Nîmes",
description: "Utilisez votre compte Sésame pour vous connecter",
image: require("@/../assets/images/service_unimes.png"),
instanceURL: "https://mobile-back.unimes.fr",
navigate: (instanceURL: string, title: string, image: ImageSourcePropType) => navigation.navigate("Multi_Login", { instanceURL, title, image }),
},
{
name: "univ_uphf",
title: "Université Polytechnique Hauts-de-France",
description: "Utilisez votre compte UPHF pour vous connecter",
image: require("@/../assets/images/service_uphf.png"),
navigate: () => navigation.navigate("UnivUphf_Login"),
instanceURL: "https://appmob.uphf.fr/backend",
navigate: (instanceURL: string, title: string, image: ImageSourcePropType) => navigation.navigate("Multi_Login", { instanceURL, title, image }),
},
];

Expand Down Expand Up @@ -59,7 +76,7 @@ const IdentityProviderSelector: Screen<"IdentityProviderSelector"> = ({ navigati
{universityProviders.map((identityProvider) => (
<NativeItem
key={identityProvider.name}
onPress={() => identityProvider.navigate()}
onPress={() => identityProvider.navigate(identityProvider.instanceURL, identityProvider.title, identityProvider.image)}
leading={<Image source={identityProvider.image} style={{ width: 40, height: 40, borderRadius: 10 }} />}
>
<NativeText variant="title">{identityProvider.title}</NativeText>
Expand Down
Loading

0 comments on commit 1464d7c

Please sign in to comment.