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.

ConnectionManager.js 7.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. // @flow
  2. import * as SecureStore from 'expo-secure-store';
  3. export const ERROR_TYPE = {
  4. SUCCESS: 0,
  5. BAD_CREDENTIALS: 1,
  6. BAD_TOKEN: 2,
  7. NO_CONSENT: 3,
  8. BAD_INPUT: 400,
  9. FORBIDDEN: 403,
  10. CONNECTION_ERROR: 404,
  11. SERVER_ERROR: 500,
  12. UNKNOWN: 999,
  13. };
  14. type response_format = {
  15. error: number,
  16. data: Object,
  17. }
  18. /**
  19. * champ: error
  20. *
  21. * 0 : SUCCESS -> pas d'erreurs
  22. * 1 : BAD_CREDENTIALS -> email ou mdp invalide
  23. * 2 : BAD_TOKEN -> session expirée
  24. * 3 : NO_CONSENT
  25. * 403 : FORBIDDEN -> accès a la ressource interdit
  26. * 500 : SERVER_ERROR -> pb coté serveur
  27. */
  28. const API_ENDPOINT = "https://www.amicale-insat.fr/api/";
  29. const AUTH_PATH = "password";
  30. export default class ConnectionManager {
  31. static instance: ConnectionManager | null = null;
  32. #email: string;
  33. #token: string | null;
  34. listeners: Array<Function>;
  35. constructor() {
  36. this.#token = null;
  37. this.listeners = [];
  38. }
  39. /**
  40. * Get this class instance or create one if none is found
  41. * @returns {ConnectionManager}
  42. */
  43. static getInstance(): ConnectionManager {
  44. return ConnectionManager.instance === null ?
  45. ConnectionManager.instance = new ConnectionManager() :
  46. ConnectionManager.instance;
  47. }
  48. getToken() {
  49. return this.#token;
  50. }
  51. onLoginStateChange(newState: boolean) {
  52. for (let i = 0; i < this.listeners.length; i++) {
  53. if (this.listeners[i] !== undefined)
  54. this.listeners[i](newState);
  55. }
  56. }
  57. addLoginStateListener(listener: Function) {
  58. this.listeners.push(listener);
  59. }
  60. async recoverLogin() {
  61. return new Promise((resolve, reject) => {
  62. if (this.getToken() !== null)
  63. resolve(this.getToken());
  64. else {
  65. SecureStore.getItemAsync('token')
  66. .then((token) => {
  67. this.#token = token;
  68. if (token !== null) {
  69. this.onLoginStateChange(true);
  70. resolve(token);
  71. } else
  72. reject(false);
  73. })
  74. .catch(error => {
  75. reject(false);
  76. });
  77. }
  78. });
  79. }
  80. isLoggedIn() {
  81. return this.getToken() !== null;
  82. }
  83. async saveLogin(email: string, token: string) {
  84. return new Promise((resolve, reject) => {
  85. SecureStore.setItemAsync('token', token)
  86. .then(() => {
  87. this.#token = token;
  88. this.#email = email;
  89. this.onLoginStateChange(true);
  90. resolve(true);
  91. })
  92. .catch(error => {
  93. reject(false);
  94. });
  95. });
  96. }
  97. async disconnect() {
  98. return new Promise((resolve, reject) => {
  99. SecureStore.deleteItemAsync('token')
  100. .then(() => {
  101. this.#token = null;
  102. this.onLoginStateChange(false);
  103. resolve(true);
  104. })
  105. .catch((error) => {
  106. reject(false);
  107. });
  108. });
  109. }
  110. async connect(email: string, password: string) {
  111. let data = {
  112. email: email,
  113. password: password,
  114. };
  115. return new Promise((resolve, reject) => {
  116. fetch(API_ENDPOINT + AUTH_PATH, {
  117. method: 'POST',
  118. headers: new Headers({
  119. 'Accept': 'application/json',
  120. 'Content-Type': 'application/json',
  121. }),
  122. body: JSON.stringify(data)
  123. }).then(async (response) => response.json())
  124. .then((response: response_format) => {
  125. if (this.isConnectionResponseValid(response)) {
  126. if (response.error === ERROR_TYPE.SUCCESS) {
  127. this.saveLogin(email, response.data.token)
  128. .then(() => {
  129. resolve(true);
  130. })
  131. .catch(() => {
  132. reject(ERROR_TYPE.UNKNOWN);
  133. });
  134. } else
  135. reject(response.error);
  136. } else
  137. reject(ERROR_TYPE.CONNECTION_ERROR);
  138. })
  139. .catch((error) => {
  140. reject(ERROR_TYPE.CONNECTION_ERROR);
  141. });
  142. });
  143. }
  144. isResponseValid(response: response_format) {
  145. let valid = response !== undefined
  146. && response.error !== undefined
  147. && typeof response.error === "number";
  148. valid = valid
  149. && response.data !== undefined
  150. && typeof response.data === "object";
  151. return valid;
  152. }
  153. isConnectionResponseValid(response: response_format) {
  154. let valid = this.isResponseValid(response);
  155. if (valid && response.error === ERROR_TYPE.SUCCESS)
  156. valid = valid
  157. && response.data.token !== undefined
  158. && response.data.token !== ''
  159. && typeof response.data.token === "string";
  160. return valid;
  161. }
  162. generatePostArguments(keys: Array<string>, values: Array<string>) {
  163. let data = {};
  164. for (let i = 0; i < keys.length; i++) {
  165. data[keys[i]] = values[i];
  166. }
  167. return data;
  168. }
  169. async authenticatedRequest(path: string, keys: Array<string>|null, values: Array<any>|null) {
  170. return new Promise((resolve, reject) => {
  171. if (this.getToken() !== null) {
  172. let data = {};
  173. if (keys !== null && values !== null && keys.length === values.length)
  174. data = this.generatePostArguments(keys, values);
  175. // console.log(data);
  176. fetch(API_ENDPOINT + path, {
  177. method: 'POST',
  178. headers: new Headers({
  179. 'Accept': 'application/json',
  180. 'Content-Type': 'application/json',
  181. }),
  182. body: JSON.stringify({
  183. token: this.getToken(),
  184. ...data
  185. })
  186. }).then(async (response) => response.json())
  187. .then((response: response_format) => {
  188. // console.log(response);
  189. if (this.isResponseValid(response)) {
  190. if (response.error === ERROR_TYPE.SUCCESS)
  191. resolve(response.data);
  192. else
  193. reject(response.error);
  194. } else
  195. reject(ERROR_TYPE.CONNECTION_ERROR);
  196. })
  197. .catch(() => {
  198. reject(ERROR_TYPE.CONNECTION_ERROR);
  199. });
  200. } else
  201. reject(ERROR_TYPE.UNKNOWN);
  202. });
  203. }
  204. }