Application Android et IOS pour l'amicale des élèves https://play.google.com/store/apps/details?id=fr.amicaleinsat.application
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WebData.ts 4.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. /*
  2. * Copyright (c) 2019 - 2020 Arnaud Vergnet.
  3. *
  4. * This file is part of Campus INSAT.
  5. *
  6. * Campus INSAT is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Campus INSAT is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
  18. */
  19. import Urls from '../constants/Urls';
  20. import { API_REQUEST_CODES, REQUEST_STATUS } from './Requests';
  21. // export const ERROR_TYPE = {
  22. // SUCCESS: 0,
  23. // BAD_CREDENTIALS: 1,
  24. // BAD_TOKEN: 2,
  25. // NO_CONSENT: 3,
  26. // TOKEN_SAVE: 4,
  27. // TOKEN_RETRIEVE: 5,
  28. // BAD_INPUT: 400,
  29. // FORBIDDEN: 403,
  30. // CONNECTION_ERROR: 404,
  31. // SERVER_ERROR: 500,
  32. // UNKNOWN: 999,
  33. // };
  34. export type ApiDataLoginType = {
  35. token: string;
  36. };
  37. type ApiResponseType<T> = {
  38. status: REQUEST_STATUS;
  39. error?: API_REQUEST_CODES;
  40. data?: T;
  41. };
  42. export type ApiRejectType = {
  43. status: REQUEST_STATUS;
  44. code?: API_REQUEST_CODES;
  45. };
  46. /**
  47. * Checks if the given API response is valid.
  48. *
  49. * For a request to be valid, it must match the response_format as defined in this file.
  50. *
  51. * @param response
  52. * @returns {boolean}
  53. */
  54. export function isApiResponseValid<T>(response: ApiResponseType<T>): boolean {
  55. return (
  56. response != null &&
  57. response.error != null &&
  58. response.data != null &&
  59. typeof response.data === 'object'
  60. );
  61. }
  62. /**
  63. * Sends a request to the Amicale Website backend
  64. *
  65. * In case of failure, the promise will be rejected with the error code.
  66. * In case of success, the promise will return the data object.
  67. *
  68. * @param path The API path from the API endpoint
  69. * @param method The HTTP method to use (GET or POST)
  70. * @param params The params to use for this request
  71. * @returns {Promise<T>}
  72. */
  73. export async function apiRequest<T>(
  74. path: string,
  75. method: string,
  76. params?: object,
  77. token?: string
  78. ): Promise<T> {
  79. return new Promise(
  80. (resolve: (data: T) => void, reject: (error: ApiRejectType) => void) => {
  81. let requestParams = {};
  82. if (params != null) {
  83. requestParams = { ...params };
  84. }
  85. if (token) {
  86. requestParams = { ...requestParams, token: token };
  87. }
  88. fetch(Urls.amicale.api + path, {
  89. method,
  90. headers: new Headers({
  91. 'Accept': 'application/json',
  92. 'Content-Type': 'application/json',
  93. }),
  94. body: JSON.stringify(requestParams),
  95. })
  96. .then((response: Response) => {
  97. const status = response.status;
  98. if (status === REQUEST_STATUS.SUCCESS) {
  99. return response.json().then((data): ApiResponseType<T> => {
  100. return { status: status, error: data.error, data: data.data };
  101. });
  102. } else {
  103. return { status: status };
  104. }
  105. })
  106. .then((response: ApiResponseType<T>) => {
  107. if (isApiResponseValid(response) && response.data) {
  108. if (response.error === API_REQUEST_CODES.SUCCESS) {
  109. resolve(response.data);
  110. } else {
  111. reject({
  112. status: REQUEST_STATUS.SUCCESS,
  113. code: response.error,
  114. });
  115. }
  116. } else {
  117. reject({
  118. status: response.status,
  119. });
  120. }
  121. })
  122. .catch(() => {
  123. reject({
  124. status: REQUEST_STATUS.CONNECTION_ERROR,
  125. });
  126. });
  127. }
  128. );
  129. }
  130. export async function connectToAmicale(email: string, password: string) {
  131. return new Promise(
  132. (
  133. resolve: (token: string) => void,
  134. reject: (error: ApiRejectType) => void
  135. ) => {
  136. const data = {
  137. email,
  138. password,
  139. };
  140. apiRequest<ApiDataLoginType>('password', 'POST', data)
  141. .then((response: ApiDataLoginType) => {
  142. if (response.token != null) {
  143. resolve(response.token);
  144. } else {
  145. reject({
  146. status: REQUEST_STATUS.SERVER_ERROR,
  147. });
  148. }
  149. })
  150. .catch((err) => {
  151. reject(err);
  152. });
  153. }
  154. );
  155. }
  156. /**
  157. * Reads data from the given url and returns it.
  158. *
  159. * Only use this function for non API calls.
  160. * For Amicale API calls, please use the apiRequest function.
  161. *
  162. * If no data was found, returns an empty object
  163. *
  164. * @param url The urls to fetch data from
  165. * @return Promise<any>
  166. */
  167. export async function readData<T>(url: string): Promise<T> {
  168. return new Promise((resolve: (response: T) => void, reject: () => void) => {
  169. fetch(url)
  170. .then(async (response: Response): Promise<any> => response.json())
  171. .then((data: T) => resolve(data))
  172. .catch(() => reject());
  173. });
  174. }