/* * Copyright (c) 2019 - 2020 Arnaud Vergnet. * * This file is part of Campus INSAT. * * Campus INSAT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Campus INSAT is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Campus INSAT. If not, see . */ import Urls from '../constants/Urls'; import { API_REQUEST_CODES, REQUEST_STATUS } from './Requests'; // export const ERROR_TYPE = { // SUCCESS: 0, // BAD_CREDENTIALS: 1, // BAD_TOKEN: 2, // NO_CONSENT: 3, // TOKEN_SAVE: 4, // TOKEN_RETRIEVE: 5, // BAD_INPUT: 400, // FORBIDDEN: 403, // CONNECTION_ERROR: 404, // SERVER_ERROR: 500, // UNKNOWN: 999, // }; export type ApiDataLoginType = { token: string; }; type ApiResponseType = { status: REQUEST_STATUS; error?: API_REQUEST_CODES; data?: T; }; export type ApiRejectType = { status: REQUEST_STATUS; code?: API_REQUEST_CODES; }; /** * Checks if the given API response is valid. * * For a request to be valid, it must match the response_format as defined in this file. * * @param response * @returns {boolean} */ export function isApiResponseValid(response: ApiResponseType): boolean { return ( response != null && response.error != null && response.data != null && typeof response.data === 'object' ); } /** * Sends a request to the Amicale Website backend * * In case of failure, the promise will be rejected with the error code. * In case of success, the promise will return the data object. * * @param path The API path from the API endpoint * @param method The HTTP method to use (GET or POST) * @param params The params to use for this request * @returns {Promise} */ export async function apiRequest( path: string, method: string, params?: object, token?: string ): Promise { return new Promise( (resolve: (data: T) => void, reject: (error: ApiRejectType) => void) => { let requestParams = {}; if (params != null) { requestParams = { ...params }; } if (token) { requestParams = { ...requestParams, token: token }; } fetch(Urls.amicale.api + path, { method, headers: new Headers({ 'Accept': 'application/json', 'Content-Type': 'application/json', }), body: JSON.stringify(requestParams), }) .then((response: Response) => { const status = response.status; if (status === REQUEST_STATUS.SUCCESS) { return response.json().then( (data): ApiResponseType => { return { status: status, error: data.error, data: data.data }; } ); } else { return { status: status }; } }) .then((response: ApiResponseType) => { if (isApiResponseValid(response) && response.data) { if (response.error === API_REQUEST_CODES.SUCCESS) { resolve(response.data); } else { reject({ status: REQUEST_STATUS.SUCCESS, code: response.error, }); } } else { reject({ status: response.status, }); } }) .catch(() => { reject({ status: REQUEST_STATUS.CONNECTION_ERROR, }); }); } ); } export async function connectToAmicale(email: string, password: string) { return new Promise( ( resolve: (token: string) => void, reject: (error: ApiRejectType) => void ) => { const data = { email, password, }; apiRequest('password', 'POST', data) .then((response: ApiDataLoginType) => { if (response.token != null) { resolve(response.token); } else { reject({ status: REQUEST_STATUS.SERVER_ERROR, }); } }) .catch((err) => { reject(err); }); } ); } /** * Reads data from the given url and returns it. * * Only use this function for non API calls. * For Amicale API calls, please use the apiRequest function. * * If no data was found, returns an empty object * * @param url The urls to fetch data from * @return Promise */ export async function readData(url: string): Promise { return new Promise((resolve: (response: T) => void, reject: () => void) => { fetch(url) .then(async (response: Response): Promise => response.json()) .then((data: T) => resolve(data)) .catch(() => reject()); }); }