From 21b5bf34be957952475f0988c277f0a76bc4dd89 Mon Sep 17 00:00:00 2001 From: StarAppeal Date: Wed, 11 Dec 2024 09:14:16 +0100 Subject: [PATCH] refactor RestService.ts --- app/(tabs)/settings.tsx | 2 +- src/components/ChangePasswordModal.tsx | 7 +- src/context/AuthProvider.tsx | 4 +- src/hooks/useSpotifyAuth.ts | 2 +- src/services/RestService.ts | 287 +++++++++++-------------- 5 files changed, 130 insertions(+), 172 deletions(-) diff --git a/app/(tabs)/settings.tsx b/app/(tabs)/settings.tsx index f97307f..20911cd 100644 --- a/app/(tabs)/settings.tsx +++ b/app/(tabs)/settings.tsx @@ -23,7 +23,7 @@ export default function SettingsScreen() { expirationDate: new Date(Date.now() + token.expires_in * 1000), }; - RestService.updateSelfSpotifyConfig(spotifyConfig, jwtToken!).then((result) => { + new RestService(jwtToken).updateSelfSpotifyConfig(spotifyConfig).then((result) => { console.log("Spotify Token gespeichert"); console.log(result); }); diff --git a/src/components/ChangePasswordModal.tsx b/src/components/ChangePasswordModal.tsx index 8968e1f..5dea311 100644 --- a/src/components/ChangePasswordModal.tsx +++ b/src/components/ChangePasswordModal.tsx @@ -2,8 +2,7 @@ import React, {useState} from "react"; import {Button, Paragraph} from "react-native-paper"; import ThemedTextInput from "@/src/components/themed/ThemedTextInput"; import {useTheme} from "@/src/context/ThemeProvider"; -import Modal from "react-native-modal"; -import {StyleSheet, View} from "react-native"; +import {StyleSheet, View, Modal} from "react-native"; import {RestService} from "@/src/services/RestService"; import {useAuth} from "@/src/context/AuthProvider"; @@ -24,7 +23,7 @@ export default function ChangePasswordModal() { setApiResponse({success: false, message: "Passwörter stimmen nicht überein!"}); return; } - RestService.changeSelfPassword(password, confirmPassword, jwtToken!).then( + new RestService(jwtToken).changeSelfPassword(password, confirmPassword).then( (response) => { setApiResponse(response); if (response.success) { @@ -50,7 +49,7 @@ export default function ChangePasswordModal() { - + Passwort ändern {apiResponse && apiResponse.message && ( diff --git a/src/context/AuthProvider.tsx b/src/context/AuthProvider.tsx index 4d5a7a0..30fe86a 100644 --- a/src/context/AuthProvider.tsx +++ b/src/context/AuthProvider.tsx @@ -44,7 +44,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({children} }, []); const saveUser = async (token: string) => { - const user = await RestService.getSelf(token); + const user = await new RestService(token).getSelf(); if (!user) { // token is invalid await removeFromStorage(JWT_TOKEN_KEY); @@ -64,7 +64,7 @@ export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({children} console.log("Already authenticated"); return; } - const response = await RestService.login(username, password); + const response = await new RestService(null).login(username, password); if (!response.success) { console.error("Login failed:", response.message); setError({ diff --git a/src/hooks/useSpotifyAuth.ts b/src/hooks/useSpotifyAuth.ts index e384fa3..47ed84a 100644 --- a/src/hooks/useSpotifyAuth.ts +++ b/src/hooks/useSpotifyAuth.ts @@ -35,7 +35,7 @@ export const useSpotifyAuth = ( if (response?.type === 'success') { try { const {code} = response.params; - const token = (await RestService.exchangeSpotifyCodeForToken(code,jwtToken)); + const token = (await new RestService(jwtToken).exchangeSpotifyCodeForToken(code)); console.log('Token:', token); onAuthSuccess(token); } catch (error) { diff --git a/src/services/RestService.ts b/src/services/RestService.ts index 4dd6735..4f1b5ec 100644 --- a/src/services/RestService.ts +++ b/src/services/RestService.ts @@ -1,178 +1,137 @@ -import axios from 'axios'; +import axios, {AxiosInstance, Method} from 'axios'; import {makeRedirectUri} from "expo-auth-session"; import {SpotifyConfig, User} from "@/src/model/User"; const API_URL = process.env.EXPO_PUBLIC_API_URL; export interface Token { - access_token: string, - refresh_token: string, - expires_in: number, - token_type: string, - scope: string, - + access_token: string; + refresh_token: string; + expires_in: number; + token_type: string; + scope: string; } -const RestService = { - exchangeSpotifyCodeForToken: async (code: string, jwtToken: string) => { - try { - const redirectUri = makeRedirectUri({ - scheme: 'led.matrix', - path: 'callback', - }); - const response = await axios.get<{ token: Token }>( - `${API_URL}/spotify/token/generate/code/${code}/redirect-uri/${encodeURIComponent(redirectUri)}`, { - headers: { - Authorization: `Bearer ${jwtToken}`, - } +class RestService { + private readonly jwtToken: string | null; + private api: AxiosInstance; + + constructor(jwtToken: string | null) { + this.jwtToken = jwtToken; + + this.api = axios.create({ + baseURL: API_URL, + timeout: 10000, // Set a timeout for requests + }); + + this.api.interceptors.request.use( + (config) => { + if (this.jwtToken) { + config.headers.Authorization = `Bearer ${this.jwtToken}`; } - ); - return response.data.token; - } catch (error) { - console.error("Error exchanging Spotify code:", error); - throw error; - } - }, - - fetchAllUser: async (jwtToken: string) => { - try { - const response = await axios.get<{ users: User[] }>(`${API_URL}/user`, { - headers: { - Authorization: `Bearer ${jwtToken}`, - }, - }); - return response.data; - } catch (error) { - console.error("Error fetching users:", error); - throw error; - } - }, - - fetchUserById: async (id: string, jwtToken: string) => { - try { - const response = await axios.get(`${API_URL}/user/${id}`, { - headers: { - Authorization: `Bearer ${jwtToken}`, - }, - }); - return response.data; - } catch (error) { - console.error("Error fetching user by id:", error); - throw error; - } - }, - - getSelf: async (jwtToken: string) => { - try { - const response = await axios.get(`${API_URL}/user/me`, { - headers: { - Authorization: `Bearer ${jwtToken}`, - }, - }); - return response.data; - } catch (error) { - console.error("Error fetching self:", error); - throw error; - } - }, - - changeSelfPassword: async ( - password: string, - passwordConfirmation: string, - jwtToken: string - ) => { - try { - const response = await axios.put<{ result: { success: boolean; message: string } }>( - `${API_URL}/user/me/password`, - {password, passwordConfirmation}, - { - headers: { - Authorization: `Bearer ${jwtToken}`, - 'Content-Type': 'application/json', - }, - validateStatus: (status) => status >= 200 && status < 500, // Erlaube 4xx-Statuscodes - } - ); - - return response.data.result; - } catch (error) { - console.error('Unexpected error:', error); - return {success: false, message: 'An unexpected error occurred.'}; - } - }, - - sendPayloadToSocket: async (userId: string, payload: object, jwtToken: string) => { - try { - const response = await axios.post( - `${API_URL}/websocket/send-message`, - {users: [userId], payload}, - { - headers: { - Authorization: `Bearer ${jwtToken}`, - 'Content-Type': 'application/json', - }, - } - ); - return response.data; - } catch (error) { - console.error("Error sending payload to socket:", error); - throw error; - } - }, - - broadcast: async (payload: object, jwtToken: String) => { - try { - const response = await axios.post( - `${API_URL}/websocket/broadcast`, - {payload}, - { - headers: { - Authorization: `Bearer ${jwtToken}`, - 'Content-Type': 'application/json', - }, - } - ); - return response.data; - } catch (error) { - console.error("Error broadcasting payload:", error); - throw error; - } - }, - - updateSelfSpotifyConfig: async (spotifyConfig: SpotifyConfig, jwtToken: string) => { - try { - const response = await axios.put<{ result: { success: boolean, message: string } }>( - `${API_URL}/user/me/spotify`, - spotifyConfig, - { - headers: { - Authorization: `Bearer ${jwtToken}`, - 'Content-Type': 'application/json', - }, - } - ); - return response.data; - } catch (error) { - console.error("Error updating self:", error); - throw error; - } - }, - - - login: async (username: string, password: string) => { - const response = await axios.post<{ - success: boolean, token: string, message: string, - id: "username" | "password" - }>( - `${API_URL}/auth/login`, { - username, - password, - }, { - validateStatus: (status) => status === 200 || status === 401 || status === 404, + console.log('Request Config:', config); + return config; + }, + (error) => { + console.error('Request Error:', error); + return Promise.reject(error); + } + ); + + this.api.interceptors.response.use( + (response) => { + console.log('Response Data:', response.data); + return response; + }, + (error) => { + console.error('Response Error:', error.response?.data || error.message); + return Promise.reject(error); } ); - return response.data; } -}; + + async exchangeSpotifyCodeForToken(code: string): Promise { + const redirectUri = makeRedirectUri({ + scheme: 'led.matrix', + path: 'callback', + }); + return this.request( + 'GET', + `/spotify/token/generate/code/${code}/redirect-uri/${encodeURIComponent(redirectUri)}` + ); + } + + async fetchAllUser(): Promise<{ users: User[] }> { + return this.request<{ users: User[] }>('GET', '/user'); + } + + async fetchUserById(id: string): Promise { + return this.request('GET', `/user/${id}`); + } + + async getSelf(): Promise { + return this.request('GET', '/user/me'); + } + + async changeSelfPassword(password: string, passwordConfirmation: string): Promise<{ success: boolean; message: string }> { + return this.request<{ success: boolean; message: string }>( + 'PUT', + '/user/me/password', + {password, passwordConfirmation}, + {'Content-Type': 'application/json'} + ); + } + + async sendPayloadToSocket(userId: string, payload: object): Promise { + return this.request( + 'POST', + '/websocket/send-message', + {users: [userId], payload}, + {'Content-Type': 'application/json'} + ); + } + + async broadcast(payload: object): Promise { + return this.request( + 'POST', + '/websocket/broadcast', + {payload}, + {'Content-Type': 'application/json'} + ); + } + + async updateSelfSpotifyConfig(spotifyConfig: SpotifyConfig): Promise<{ success: boolean; message: string }> { + return this.request<{ success: boolean; message: string }>( + 'PUT', + '/user/me/spotify', + spotifyConfig, + {'Content-Type': 'application/json'} + ); + } + + async login(username: string, password: string): Promise<{ success: boolean; token: string; message: string; id: "username" | "password" }> { + return this.request<{ success: boolean; token: string; message: string; id: "username" | "password" }>( + "POST", + '/auth/login', + {username, password}, + {'Content-Type': 'application/json'} + ); + } + + private async request(method: Method, url: string, data?: any, headers?: any): Promise { + try { + const response = await this.api.request({ + method, + url, + data, + headers, + }); + return response.data; + } catch (error) { + console.error('Error during request:', error); + throw error; + } + } +} export {RestService};