Application Android et IOS pour l'amicale des élèves
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.

ConnectionManager.js 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. // @flow
  2. import * as Keychain from 'react-native-keychain';
  3. import type {ApiDataLoginType, ApiGenericDataType} from '../utils/WebData';
  4. import {apiRequest, ERROR_TYPE} from '../utils/WebData';
  5. /**
  6. * champ: error
  7. *
  8. * 0 : SUCCESS -> pas d'erreurs
  9. * 1 : BAD_CREDENTIALS -> email ou mdp invalide
  10. * 2 : BAD_TOKEN -> session expirée
  11. * 3 : NO_CONSENT
  12. * 403 : FORBIDDEN -> accès a la ressource interdit
  13. * 500 : SERVER_ERROR -> pb coté serveur
  14. */
  15. const SERVER_NAME = 'amicale-insat.fr';
  16. const AUTH_PATH = 'password';
  17. export default class ConnectionManager {
  18. static instance: ConnectionManager | null = null;
  19. #email: string;
  20. #token: string | null;
  21. constructor() {
  22. this.#token = null;
  23. }
  24. /**
  25. * Gets this class instance or create one if none is found
  26. *
  27. * @returns {ConnectionManager}
  28. */
  29. static getInstance(): ConnectionManager {
  30. if (ConnectionManager.instance == null)
  31. ConnectionManager.instance = new ConnectionManager();
  32. return ConnectionManager.instance;
  33. }
  34. /**
  35. * Gets the current token
  36. *
  37. * @returns {string | null}
  38. */
  39. getToken(): string | null {
  40. return this.#token;
  41. }
  42. /**
  43. * Tries to recover login token from the secure keychain
  44. *
  45. * @returns Promise<string>
  46. */
  47. async recoverLogin(): Promise<string> {
  48. return new Promise(
  49. (resolve: (token: string) => void, reject: () => void) => {
  50. const token = this.getToken();
  51. if (token != null) resolve(token);
  52. else {
  53. Keychain.getInternetCredentials(SERVER_NAME)
  54. .then((data: Keychain.UserCredentials | false) => {
  55. if (
  56. data != null &&
  57. data.password != null &&
  58. typeof data.password === 'string'
  59. ) {
  60. this.#token = data.password;
  61. resolve(this.#token);
  62. } else reject();
  63. })
  64. .catch((): void => reject());
  65. }
  66. },
  67. );
  68. }
  69. /**
  70. * Check if the user has a valid token
  71. *
  72. * @returns {boolean}
  73. */
  74. isLoggedIn(): boolean {
  75. return this.getToken() !== null;
  76. }
  77. /**
  78. * Saves the login token in the secure keychain
  79. *
  80. * @param email
  81. * @param token
  82. * @returns Promise<void>
  83. */
  84. async saveLogin(email: string, token: string): Promise<void> {
  85. return new Promise((resolve: () => void, reject: () => void) => {
  86. Keychain.setInternetCredentials(SERVER_NAME, 'token', token)
  87. .then(() => {
  88. this.#token = token;
  89. this.#email = email;
  90. resolve();
  91. })
  92. .catch((): void => reject());
  93. });
  94. }
  95. /**
  96. * Deletes the login token from the keychain
  97. *
  98. * @returns Promise<void>
  99. */
  100. async disconnect(): Promise<void> {
  101. return new Promise((resolve: () => void, reject: () => void) => {
  102. Keychain.resetInternetCredentials(SERVER_NAME)
  103. .then(() => {
  104. this.#token = null;
  105. resolve();
  106. })
  107. .catch((): void => reject());
  108. });
  109. }
  110. /**
  111. * Sends the given login and password to the api.
  112. * If the combination is valid, the login token is received and saved in the secure keychain.
  113. * If not, the promise is rejected with the corresponding error code.
  114. *
  115. * @param email
  116. * @param password
  117. * @returns Promise<void>
  118. */
  119. async connect(email: string, password: string): Promise<void> {
  120. return new Promise(
  121. (resolve: () => void, reject: (error: number) => void) => {
  122. const data = {
  123. email,
  124. password,
  125. };
  126. apiRequest(AUTH_PATH, 'POST', data)
  127. .then((response: ApiDataLoginType) => {
  128. if (response.token != null) {
  129. this.saveLogin(email, response.token)
  130. .then((): void => resolve())
  131. .catch((): void => reject(ERROR_TYPE.TOKEN_SAVE));
  132. } else reject(ERROR_TYPE.SERVER_ERROR);
  133. })
  134. .catch((error: number): void => reject(error));
  135. },
  136. );
  137. }
  138. /**
  139. * Sends an authenticated request with the login token to the API
  140. *
  141. * @param path
  142. * @param params
  143. * @returns Promise<ApiGenericDataType>
  144. */
  145. async authenticatedRequest(
  146. path: string,
  147. params: {...},
  148. ): Promise<ApiGenericDataType> {
  149. return new Promise(
  150. (
  151. resolve: (response: ApiGenericDataType) => void,
  152. reject: (error: number) => void,
  153. ) => {
  154. if (this.getToken() !== null) {
  155. const data = {
  156. ...params,
  157. token: this.getToken(),
  158. };
  159. apiRequest(path, 'POST', data)
  160. .then((response: ApiGenericDataType): void => resolve(response))
  161. .catch((error: number): void => reject(error));
  162. } else reject(ERROR_TYPE.TOKEN_RETRIEVE);
  163. },
  164. );
  165. }
  166. }